0

I'm implementing JWT token bases authentication in my .net core 3.1 api.

i'm setting expire time As Datetime.Now.AddMinutes(2)

but when token is generating its ValidFrom and ValidTo time is different than current time, and when generating refresh token using tokenHandler.ValidateToken it's throwing an error

IDX10223: Lifetime validation failed. The token is expired. ValidTo: '10/7/2022 6:34:40 AM', Current time: '10/7/2022 10:46:53 AM'

below is my code samples,

refresh Token

   public async Task<IActionResult> Refresh(TokenResponse Token)
        {
         
            var tokenHandler = new JwtSecurityTokenHandler();
            JwtSecurityToken jwtToken = ReadJWTToken(Token.jwtToken);
            SecurityToken securityToken;
            var principal = tokenHandler.ValidateToken(Token.jwtToken, new TokenValidationParameters {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwt.SecurityKey)),
                ValidateIssuer = true,
                ValidIssuer = _jwt.Issuer,

                ValidateAudience = true,
                ValidAudience = _jwt.Audience,

                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero,
            }, out securityToken);
            var _token=securityToken as JwtSecurityToken;

            if(_token!=null && !_token.Header.Alg.Equals(SecurityAlgorithms.HmacSha256))
            {
                return Unauthorized(new { message = "UnAuthorized Access" });
            }
            string username = principal.Identity.Name;
            RefreshToken refreshT = await _common.RefreshTokenValidate(Token, username);
            if (refreshT == null)
            {
                return Unauthorized(new { message = "UnAuthorized Access" });
            }
          
            if (jwtToken.ValidTo > DateTime.UtcNow)
            {
                return BadRequest(new { message = "Token Not Expired" });
            }

            TokenResponse result =await _common.AuthenticateToken(username, principal.Claims.ToArray());
            return Ok(result);
        }
public string GenerateToken(AppUser user)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwt.SecurityKey));
            var tokenDesciptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(
                    new Claim[] {
                        new Claim(ClaimTypes.Name,user.username),
                        new Claim(ClaimTypes.Role,user.userType),
                        new Claim("userCode",user.userCode),
                        new Claim("userTypeCode",user.userTypeCode),
                        new Claim("Mobile",user.Mobile??""),
                        new Claim("email",user.email??""),
                        new Claim("gender",user.genderCode??""),
                        new Claim("username",user.username),
                        new Claim("fname",user.name)
                    }
                ),
                Expires = DateTime.Now.AddMinutes(_jwt.DurationInMinutes),
                SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256),
                Audience=_jwt.Audience,
                Issuer=_jwt.Issuer

            };
            var tokenStr = tokenHandler.CreateToken(tokenDesciptor);
            string token = tokenHandler.WriteToken(tokenStr);
            return token;
        }

appsetting.json

  "JWTSettings": {
    "SecurityKey": "some key",
    "Issuer": "https://localhost:44331/",
    "Audience": "https://localhost:44331/",
    "DurationInMinutes": 2
  },

Statup.cs

 #region JWT Authentication
            var _jwtSetting = Configuration.GetSection("JWTSettings");
            services.Configure<JWTSettings>(_jwtSetting);

            services.AddAuthentication(item =>
            {
                item.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                item.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(item =>
            {
                item.RequireHttpsMetadata = true;
                item.SaveToken = true;
                item.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWTSettings:SecurityKey"])),
                    ValidateIssuer = true,
                    ValidIssuer = Configuration["JWTSettings:Issuer"],

                    ValidateAudience = true,
                    ValidAudience = Configuration["JWTSettings:Audience"],

                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero,
               
                };
            });
            #endregion

from above code

var tokenStr = tokenHandler.CreateToken(tokenDesciptor);

at the when api is trigger time = {07-Oct-2022 3:36:36 PM} /

tokenDesciptor Expires value = {07-Oct-2022 3:38:36 PM}

tokenStr ValidFrom value = {07-Oct-2022 10:12:00 AM}

tokenStr ValidTo value = {07-Oct-2022 10:08:36 AM}

So is there any thing I'm missing?

  • generally the times in the token are UTC, so you're probably in a timezone 5.5 hours ahead of UTC. But the tokenStr ValidFrom 10:12:00 AM seems odd. Is this a typo? I would have expected 10:06:36 AM. – jps Oct 07 '22 at 10:33
  • it seems it is getting converted to UTC time. – CodingMytra Oct 07 '22 at 10:33
  • @jps my bad, its {07-Oct-2022 10:06:36 AM}
    and by time zone is IST. getting using TimeZone curTimeZone = TimeZone.CurrentTimeZone; curTimeZone.StandardName
    – nitin mandal Oct 07 '22 at 10:41
  • ok, fine, but then that's it, the token stored times in UTC, nothing wrong with it, you just have to consider that. – jps Oct 07 '22 at 10:43
  • @jps The problem is when i'm generating refresh token tokenHandler.ValidateToken throwing an error IDX10223: Lifetime validation failed. The token is expired. ValidTo: '10/7/2022 6:34:40 AM', Current time: '10/7/2022 10:46:53 AM' some thing like this – nitin mandal Oct 07 '22 at 10:48
  • var tokenHandler = new JwtSecurityTokenHandler(); var principal = tokenHandler.ValidateToken(Token.jwtToken, new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwt.SecurityKey)), ValidateIssuer = true, ValidIssuer = _jwt.Issuer, ValidateAudience = true, ValidAudience = _jwt.Audience, ValidateLifetime = true, ClockSkew = TimeSpan.Zero, }, out securityToken); – nitin mandal Oct 07 '22 at 10:50
  • Then please update your question. Right now you asked why there's a difference (because of UTC), but in your comment you reveal your true problem (validation fails). Usually I would expect the framework to work with the different timezones. I don't have the time now to dive deeper into that matter. I found [this Q/A](https://stackoverflow.com/questions/55341414/how-to-validate-jwt-using-utc-time-using-net-core), maybe that has some information for you. – jps Oct 07 '22 at 11:05

0 Answers0