Search code examples
c#authenticationjwtasp.net-core-webapiasp.net-authorization

Check JWT token exists in memory cache before executing the codes in the API


I'm working on a .Net Core project with hundreds of APIs in it.

The APIs accept JWT token to authorize.

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

As JWT tokens cannot be destroyed until the expiration time is over, I need to make sure that the token gets unsuable when the user logsout.

I stored the JWT token with key in the memory cache at it's creation.

memoryCache.Set(ob.MailId, Token.Token);

I want to allow the code execution only if the token exists in the memory cache, so that, when the user logsout, I'll remove the token from the memory cache, then the API will be inaccessible with the same token.

I don't want to put condition check in every APIs and I do not have much detail knowledge with Authorization either.

Is there any way to put a condition along with the header such a way that if the condition fails, it hits the UnauthorizedAccessException?

Please suggest me an efficient way to execute this.


Solution

  • We use http 401 statue code instead of UnauthorizedAccessException to indicate user is unauthenticated in usual.

    You could decide where to get the token when you configure JwtAuthentication,a minimal example:

    in Program.cs:

    builder.Services.AddMemoryCache();
    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(op =>
    {
        op.TokenValidationParameters = new TokenValidationParameters
        {
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey
            (Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = false,
            ValidateIssuerSigningKey = true
        };
        op.Events=new JwtBearerEvents()
        {
    
              
            OnMessageReceived = context =>
            {
                var cache = context.HttpContext.RequestServices.GetService<IMemoryCache>();
                var success = cache.TryGetValue("JwtToken", out var token);
                if (success)
                {
                    // you could decide where to get the token here
                    context.Token = token.ToString();
                }
                
                return Task.CompletedTask;
            }
        };
    });
    

    AuthController:

    [Route("api/[controller]")]
        [ApiController]
        public class MyAuthController : ControllerBase
        {
            private readonly IMemoryCache _cache;
            private readonly IConfiguration _configuration;
            public MyAuthController(IMemoryCache cache, IConfiguration configuration)
            {
                _cache = cache;
                _configuration = configuration;
            }
    
            [HttpGet("Login")]
            public IActionResult Login()
            {
    
                var issuer = _configuration["Jwt:Issuer"];
                var audience = _configuration["Jwt:Audience"];
                var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Key"]);
                var tokenDescriptor = new SecurityTokenDescriptor
                {
                    Subject = new ClaimsIdentity(new[]
                    {
    
                    new Claim(ClaimTypes.Name, "Zhang"),
                    new Claim(ClaimTypes.Role, "Admin"),
    
                             }),
                    Expires = DateTime.UtcNow.AddMinutes(5),
                    Issuer = issuer,
                    Audience = audience,
                    SigningCredentials = new SigningCredentials
                    (new SymmetricSecurityKey(key),
                    SecurityAlgorithms.HmacSha512Signature)
                };
                var tokenHandler = new JwtSecurityTokenHandler();
                var token = tokenHandler.CreateToken(tokenDescriptor);
                var jwtToken = tokenHandler.WriteToken(token);
                var stringToken = tokenHandler.WriteToken(token);
    
                _cache.Set("JwtToken", stringToken);
                return Ok();
            }
    
            [HttpGet("Logout")]
            public IActionResult Logout()
            {
                _cache.Remove("JwtToken");
                return Ok();
            }
        }
    

    Result: enter image description here

    Here's a document related with ASP.NET Core authentication,Hopes help