TransWikia.com

Security token from TokenValidatedContext from the OnTokenValidated event listener is missing last string segment

Stack Overflow Asked by Question3r on December 3, 2021

I’m using the Microsoft.AspNetCore.Authentication.JwtBearer and System.IdentityModel.Tokens.Jwt for my .NET Core project.

Whenever I generate a new token I store that to the database. First of all this is how I generate a new token

    public string GenerateToken(Dictionary<string, object> payload)
    {
        DateTime tokenExpiresAt = DateTime.Now.AddMilliseconds(1); // from config
        byte[] symmetricKey = Convert.FromBase64String("secret"); // from config
        SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(symmetricKey);
    
        SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
        {
            Claims = payload,
            Expires = tokenExpiresAt,
            SigningCredentials = new SigningCredentials(symmetricSecurityKey, 
                SecurityAlgorithms.HmacSha256Signature)
        };
    
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
        SecurityToken securityToken = tokenHandler.CreateToken(tokenDescriptor);
        string token = tokenHandler.WriteToken(securityToken);

        return token;
    }

The generated sample token is

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxIiwibmJmIjoxNTk1NDQ1NjMxLCJleHAiOjE1OTU0NDU2OTEsImlhdCI6MTU5NTQ0NTYzMX0.cWvSpKC_yYao2_ziW_ahjjHpUl2SgUZvCmsjXntxCOI

If a client tries to access a protected endpoint the default configuration will handle the basic validation (configured in the DI setup in the Startup file)

        services
            .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(jwtBearerOptions =>
            {
                byte[] symmetricKey = Convert.FromBase64String("secret"); // from config
                SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(symmetricKey);
                
                jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuerSigningKey = true,
                    ValidateLifetime = true,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    IssuerSigningKey = symmetricSecurityKey,
                };

                jwtBearerOptions.Events = new JwtBearerEvents()
                {
                    OnTokenValidated = ProcessAfterTokenValidation
                };
            });

As you can see I added a method to the OnTokenValidated event listener. This method should check, if the token exists in the database.

    public async Task ProcessAfterTokenValidation(TokenValidatedContext tokenValidatedContext)
    {
        JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
        string token = jwtSecurityTokenHandler.WriteToken(tokenValidatedContext.SecurityToken);
        
        // ... check if token exists in db ...
    }

The problem with that method is that the generated token is not the exact token as it is stored in the database. There is missing a last segment. The token variable holds this

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxIiwibmJmIjoxNTk1NDQ1NjMxLCJleHAiOjE1OTU0NDU2OTEsImlhdCI6MTU5NTQ0NTYzMX0.

and the missing last part would be

cWvSpKC_yYao2_ziW_ahjjHpUl2SgUZvCmsjXntxCOI

Does someone know why the last part of the token is missing?

Thanks for help!

One Answer

The last part of the token is the signature. The purpose of the OnTokenValidated method is to provide a ClaimsIdentity. The signature is not a component of the claims of the token holder.

If you had a key rotation policy on the issuing side a given user could present identical claims with a different signature before and after a key rotation.

The identity of the user is derived from a combination of the issuer plus any claims that identify the user (e.g. username in the token from your example).

In your case, since you are the issuer, the token minus the signature simply represents proof that the user has successfully authenticated against your token issuing endpoint. The claims within the token should lead to a database record rather than the token itself.

Answered by bpdohall on December 3, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP