简体   繁体   中英

ASP.NET Core MVC JWT expires too early

I am working on mob app backend and I am using JWT. My porblem is that it expires early, and I think I set it for 365 days. I am using asp.net core mvc v1 in VS2015.

Here is my Auth configuration for JWT. This method is called from Startup class.

private void ConfigureAuth(IApplicationBuilder app)
    {
        secretKey = Guid.NewGuid().ToString();

        var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));

    app.UseSimpleTokenProvider(new TokenProviderOptions
    {
        Path = "/api/token",
        Audience = Audience,
        Issuer = Issuer,
        SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256),
        IdentityResolver = GetIdentity,
    });

    var tokenValidationParameters = new TokenValidationParameters
    {
        // The signing key must match!
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = signingKey,

        // Validate the JWT Issuer (iss) claim
        ValidateIssuer = true,
        ValidIssuer = Issuer,

        // Validate the JWT Audience (aud) claim
        ValidateAudience = true,
        ValidAudience = Audience,

        // Validate the token expiry
        ValidateLifetime = true,

        // If you want to allow a certain amount of clock drift, set that here:
        ClockSkew = TimeSpan.Zero
    };

    app.UseJwtBearerAuthentication(new JwtBearerOptions
    {
        AutomaticAuthenticate = true,
        AutomaticChallenge = true,
        TokenValidationParameters = tokenValidationParameters
    });

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AutomaticAuthenticate = true,
        AutomaticChallenge = true,
        AuthenticationScheme = "Cookie",
        CookieName = "access_token",
        TicketDataFormat = new CustomJwtDataFormat(SecurityAlgorithms.HmacSha256, tokenValidationParameters),
        Events = new CustomCookieAuthenticationEvents()
    });
}

private Task<ClaimsIdentity> GetIdentity(string email)
{
    ServiceMessage<UserEntity> request = _userService.FindByEmailAsync(email).Result;

    if (request != null && request.Success && request.ResultObject != null)
    {
        return Task.FromResult(CreateClaimsIdentity(request.ResultObject, "Token"));
    }

    // Credentials are invalid, or account doesn't exist
    return Task.FromResult<ClaimsIdentity>(null);
}

private ClaimsIdentity CreateClaimsIdentity(UserEntity user, string authenticationType)
{
    List<Claim> claimCollection = new List<Claim>
    {
        new Claim(ClaimTypes.NameIdentifier, user.Email, ClaimValueTypes.String),
        new Claim(ClaimTypes.Role, user.Role, ClaimValueTypes.String),
        new Claim(ClaimTypes.Name, user.Email.Split('@')[0], ClaimValueTypes.String),
        new Claim(ClaimTypes.Expiration, TimeSpan.FromDays(365).ToString(), ClaimValueTypes.DaytimeDuration)
    };

    ClaimsIdentity claimsIdentity = new ClaimsIdentity(claimCollection, authenticationType);

    return claimsIdentity;
}

In my token provider middleware I generate JWT like this:

DateTime now = DateTime.Now;

            // Specifically add the jti (nonce), iat (issued timestamp), and sub (subject/user) claims.
            // You can add other claims here, if you want:
            Claim[] claims = new Claim[]
            {
                new Claim(ClaimTypes.Name,validation.ResultObject.Email,ClaimValueTypes.String),
                new Claim(JwtRegisteredClaimNames.Email, validation.ResultObject.Email),
                new Claim(JwtRegisteredClaimNames.Aud, Audience),
                new Claim(JwtRegisteredClaimNames.Iss, issuer),
                new Claim(JwtRegisteredClaimNames.Typ, validation.ResultObject.Role),
                new Claim(JwtRegisteredClaimNames.Jti, await _options.NonceGenerator()),
                new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(now).ToString(), ClaimValueTypes.Integer64),
                new Claim(ClaimTypes.Role, "user")
            };

            // Create the JWT and write it to a string
            JwtSecurityToken jwt = new JwtSecurityToken
            (
                issuer: _options.Issuer,
                audience: _options.Audience,
                claims: claims,
                notBefore: now,
                expires: now.Add(_options.Expiration),
                signingCredentials: _options.SigningCredentials
            );
            string encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

            var response = new
            {
                access_token = encodedJwt,
                expires_in = (int)_options.Expiration.TotalSeconds
            };

            // Serialize and return the response
            context.Response.ContentType = "application/json";
            await context.Response.WriteAsync(JsonConvert.SerializeObject(response, _serializerSettings));

_options is the next class:

public class TokenProviderOptions
    {
        /// <summary>
        /// The relative request path to listen on.
        /// </summary>
        /// <remarks>The default path is <c>/token</c>.</remarks>
        public string Path { get; set; } = "api/token";

        /// <summary>
        ///  The Issuer (iss) claim for generated tokens.
        /// </summary>
        public string Issuer { get; set; }

        /// <summary>
        /// The Audience (aud) claim for the generated tokens.
        /// </summary>
        public string Audience { get; set; }

        /// <summary>
        /// The expiration time for the generated tokens.
        /// </summary>
        /// <remarks>The default is five minutes (300 seconds).</remarks>
        public TimeSpan Expiration { get; set; } = TimeSpan.FromDays(360);

        /// <summary>
        /// The signing key to use when generating tokens.
        /// </summary>
        public SigningCredentials SigningCredentials { get; set; }

        /// <summary>
        /// Resolves a user identity given a username and password.
        /// </summary>
        public Func<string, Task<ClaimsIdentity>> IdentityResolver { get; set; }

        /// <summary>
        /// Generates a random value (nonce) for each generated token.
        /// </summary>
        /// <remarks>The default nonce is a random GUID.</remarks>
        public Func<Task<string>> NonceGenerator { get; set; } = new Func<Task<string>>(() => Task.FromResult(Guid.NewGuid().ToString()));

After a time I get the error message, but still don't know what is wrong. The error message are:

WWW-Authenticate:Bearer error="invalid_token", error_description="The signature is invalid"

I can provide more code if you needed. thnx

I realized that my secretKey was generated by GIUD, and every time when u closed and reopened mobile app, new GUID was generated, sto the old token was not valid any more. The secret has to be constant. Store it in your json config file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM