JwtSecurityToken doesn't expire when it should

后端 未结 6 1935
耶瑟儿~
耶瑟儿~ 2021-02-02 07:55

I am currently using the JwtSecurityToken class in System.IdentityModels.Tokens namespace. I create a token using the following:

DateTime expires = DateTime.Utc         


        
相关标签:
6条回答
  • 2021-02-02 08:28

    .NET Core Update

    This is handled slightly differently in .NET Core, as the TokenValidationParameters are set in Startup.cs using the ConfigureServices() method and then handled automatically by the middleware.

    Also note that the older InMemorySymmetricSecurityKey for signing the secret is now deprecated in favor of SymmetricSecurityKey, which is shown below.

    public void ConfigureServices(IServiceCollection services)
    {
        // ...
    
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = _config.AuthenticationSettings.TokenAuthority,
                    ValidAudience = _config.AuthenticationSettings.TokenAuthority,
                    LifetimeValidator = TokenLifetimeValidator.Validate,
                    IssuerSigningKey = new SymmetricSecurityKey(
                        Encoding.UTF8.GetBytes(_config.AuthenticationSettings.SecurityKey))
                };
            });
    
        // ...
    }
    

    And so I also made my own version of the token validator in @tkd_aj's answer above and threw it in a static class:

    public static class TokenLifetimeValidator
    {
        public static bool Validate(
            DateTime? notBefore,
            DateTime? expires,
            SecurityToken tokenToValidate,
            TokenValidationParameters @param
        ) {
            return (expires != null && expires > DateTime.UtcNow);
        }
    }
    
    0 讨论(0)
  • 2021-02-02 08:30

    The problem is related ClockSkew. Normally, the validation libraries (at least the MS one) compensate for clock skew. ClockSkew default value is 5 minutes. See some answer here

    You can change ClockSkew in TokenValidationParameters:

    var tokenValidationParameters = new TokenValidationParameters
    {
        //...your setting
    
        // set ClockSkew is zero
        ClockSkew = TimeSpan.Zero
    };
    
    app.UseJwtBearerAuthentication(new JwtBearerOptions
    {
        AutomaticAuthenticate = true,
        AutomaticChallenge = true,
        TokenValidationParameters = tokenValidationParameters
    });
    

    Happy coding!

    0 讨论(0)
  • 2021-02-02 08:34

    After reading through @Denis Kucherov's answer, I found out that I could use the same custom validator he posted without using the JwtBearerOptions class which would have required me to add a new library.

    Also, Since there are two namespaces which contain a lot of these same classes I will make sure to mention that all of these are using the System.IdentityModels... namespaces. (NOT Microsoft.IdentityModels...)

    Below is the code I ended up using:

    private bool CustomLifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken tokenToValidate, TokenValidationParameters @param)
    {
        if (expires != null)
        {
            return expires > DateTime.UtcNow;
        }
        return false;
    }
    private JwtSecurityToken ValidateJwtToken(string tokenString)
    {
       string secret = ConfigurationManager.AppSettings["jwtSecret"].ToString();
       var securityKey = new InMemorySymmetricSecurityKey(Encoding.Default.GetBytes(secret));
       JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
       TokenValidationParameters validation = new TokenValidationParameters()
       {
           ValidAudience = "MyAudience",
           ValidIssuer = "MyIssuer",
           ValidateIssuer = true,
           ValidateLifetime = true,
           LifetimeValidator = CustomLifetimeValidator,
           RequireExpirationTime = true,
           IssuerSigningKey = securityKey,
           ValidateIssuerSigningKey = true,
       };
       SecurityToken token;
       ClaimsPrincipal principal = handler.ValidateToken(tokenString, validation, out token);
       return (JwtSecurityToken)token;
    }
    
    0 讨论(0)
  • 2021-02-02 08:40

    Below link give you the exact answer, as by default MS have expire time of 5mins. So either you have to make it custom or time which you will give in expires: DateTime.Now.AddSeconds(30) 30seconds in above line will be added in expirey time. So total expire time will be 5mins and 30secs

    https://github.com/IdentityServer/IdentityServer3/issues/1251

    Hope this will help.

    0 讨论(0)
  • 2021-02-02 08:42

    There are seems to be some issue with LifeTimeValidator. You can just override its logic with a custom delegate. Also, use JwtBearerOptions class to control authentication middleware behavior. For example:

    new JwtBearerOptions
    {
         AutomaticAuthenticate = true,
         AutomaticChallenge = true,
         TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
         {
               ValidIssuer = _configuration["Tokens:Issuer"],
               ValidAudience = _configuration["Tokens:Audience"],
               ValidateIssuer = true,
               ValidateAudience = true,
               ValidateLifetime = true,
               LifetimeValidator = LifetimeValidator,
               ValidateIssuerSigningKey = true,
               IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Tokens:Key"]))
          }
    }
    

    And assign LifetimeValidotor delegate, to provide its own timeout validation logic:

    private bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken token, TokenValidationParameters @params)
    {
         if (expires != null)
         {
              return expires > DateTime.UtcNow;
         }
         return false;
    }
    
    0 讨论(0)
  • 2021-02-02 08:47

    I just implemented a JWT token middleware too and although the examples on the internet use UtcNow, I had to use Now or the expire time is off. When I use Now, expiration is spot on.

    0 讨论(0)
提交回复
热议问题