0

I am using jwt tokens in my project. When the client logins, he will receive a token with his device id (in mobile) -that was sent to the server in the request body- as the payload...

The thing I want to do is for further requests when the client sends his device id in the body (as a convention in my project) and of course the token in the header request, I want to check if the device id and the token's payload are equal or not.

I did this in a service like this:

public class AuthenticationService
{
    public bool IsAuthenticated(HttpRequest req, string deviceId)
    {


        var token = req.Headers["authorization"];
        var handler = new JwtSecurityTokenHandler();

        JwtSecurityToken tokenS;  

        foreach (var stringValue in token)
        {
            var ss = stringValue.Replace("Bearer ", "");
            if (handler.CanReadToken(ss))
            {
                tokenS = handler.ReadToken(ss) as JwtSecurityToken;
                return tokenS.Claims.Any(c => c.Value == deviceId);

            }
        }

        return false;
    }
}

And I should inject it in every controller that I want to authorize the user...

if (_authenticationService.IsAuthenticated(Request, deviceId))
        {
            _logger.LogInformation("authorized!");
        }
        else
        {
            _logger.LogCritical("unauthorized");
        }

I want to know that if there is a more cleaner way of doing this? Something to do in the Startup class when I'm configuring the Authentication:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(
                        Configuration.GetSection("AppSettings:Token").Value)),
                    ValidateIssuer = false,
                    ValidateAudience = false,

                };
            });
2
  • You could use a Base Controller which is inherited by all your other controllers, and then override OnActionExecuting to validate the user before processing the request. This would cut down on boilerplate code. Commented Feb 4, 2020 at 15:39
  • Why not do it in the request pipeline , insted of every controller... Commented Feb 4, 2020 at 15:40

1 Answer 1

1

AddJwtBearer extension will map the claims in token to user's cliams , you can get the device ID by (if cliam type is deviceId):

var deviceID= context.HttpContext.User.Claims.Where(x => x.Type == "deviceId").FirstOrDefault().Value;

Then you can use Filter or Middleware to read request body and compare the device ID in reuqest body with the one in User's claim . For example , if using Filter :

public class CustomActionFilter : ActionFilterAttribute
{
    public override async void OnActionExecuting(ActionExecutingContext context)
    {

        if (context.HttpContext.User.Identity.IsAuthenticated) { 

        //read request body 
        var bodyStr = "";
        var req = context.HttpContext.Request;
        req.EnableBuffering();
        req.Body.Position = 0;
        using (var stream = new StreamReader(req.Body))
        {
            bodyStr = await stream.ReadToEndAsync();
        }

        // here you get device ID from bodyStr ,for example : deviceIDFromReq

        var deviceID= context.HttpContext.User.Claims.Where(x => x.Type == "deviceId").FirstOrDefault().Value;

        // then compare 

        if (deviceIDFromReq.Equals(deviceID))
        {
            context.Result = new BadRequestObjectResult(new
            {
                status = "error",
                description = "deviceID not matched"
            });
        }
        }
        base.OnActionExecuting(context);
    }
}

Register as global filter :

services.AddControllers(config =>
{
    config.Filters.Add<CustomActionFilter>();

});
Sign up to request clarification or add additional context in comments.

1 Comment

That depends on how you send the device id in request , put checkpoint on bodyStr to confirm it , use string spilt or json.net to convert json string to object . like hereand here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.