0

I have been working on a system to authenticate and authorize users on my website using JSON Web Tokens. My system is just about completed, but I am running into an error when I attempt to use the [Authorize("Bearer")] attribute in my code. The error is as follows:

System.IdentityModel.Tokens.SecurityTokenInvalidSignatureException occurred Message: Exception thrown: 'System.IdentityModel.Tokens.SecurityTokenInvalidSignatureException' in Microsoft.IdentityModel.Logging.dll Additional information: IDX10503: Signature validation failed. Keys tried: ''. Exceptions caught: ''. token: '{"typ":"JWT","alg":"RS256","kid":null}.{"nameid":"6581f5a0-1775-4ce4-8650-a3d7e613b216","unique_name":"alex","AspNet.Identity.SecurityStamp":"8da933c3-0f88-42ea-876d-c07e99d1eecc","iss":"Uniti","aud":"Uniti","exp":1436849284,"nbf":1436845684}'

I don't understand why it isn't testing any keys with the JWT. I have an RSA key defined in my startup file. Without further dragging this on, I have provided the code that may be necessary to solve this error below.

My startup code (generating key and OAuthBearer options):

#region RSA Key Generation

        var rsa = new RSACryptoServiceProvider(2048);
        var rsaKey = rsa.ExportParameters(true);
        var key = new RsaSecurityKey(rsaKey);

        services.AddInstance(new SigningCredentials(key, SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest));

        #endregion

        services.AddInstance(new OAuthBearerAuthenticationOptions
        {
            SecurityTokenValidators = new List<ISecurityTokenValidator>
            {
                new JwtSecurityTokenHandler()
            },
            TokenValidationParameters = new TokenValidationParameters
            {
                IssuerSigningKey = key,
                ValidIssuer = "Uniti",
                ValidAudience = "Uniti"
            },
        });

        services.AddAuthorization();
        services.ConfigureAuthorization(auth =>
        {
            auth.AddPolicy("Bearer", builder =>
            {
                builder.AddAuthenticationSchemes(OAuthBearerAuthenticationDefaults.AuthenticationScheme);
                builder.RequireAuthenticatedUser();
            });
        });

My token generation code:

var claimsIdentity = (ClaimsIdentity) User.Identity;

            var handler = BearerOptions.SecurityTokenValidators.OfType<JwtSecurityTokenHandler>().First();
            var securityToken = handler.CreateToken(
                issuer: "Uniti",
                audience: "Uniti",
                signingCredentials: BearerCredentials,
                subject: claimsIdentity
                );

            var token = handler.WriteToken(securityToken);

Am I forgetting to add something somewhere, or am I generating the keys incorrectly? Thanks ahead of time if you can help me!

Alex Justi
  • 167
  • 4
  • 13

1 Answers1

2

I bet it's due to the incorrect way of registering the OAuth2 bearer options, as already explained in my previous answer: https://stackoverflow.com/a/31322654/542757

services.AddInstance(new OAuthBearerAuthenticationOptions());

When you use services.AddInstance, the OAuth2 bearer middleware is unable to retrieve the options (and thus, the key), as it internally uses IOptions<OAuthBearerAuthenticationOptions> and not OAuthBearerAuthenticationOptions.

This is the correct way to register the OAuth2 bearer options:

services.ConfigureOAuthBearerAuthentication(options => {
    // Configure the options used by the OAuth2 bearer middleware.
});
Community
  • 1
  • 1
Kévin Chalet
  • 39,509
  • 7
  • 121
  • 131
  • When I use the ConfigureOAuthBearer function, it doesn't add the service to the service collection. Do I have to add it, and then configure it? – Alex Justi Jul 14 '15 at 15:17
  • 1
    You **shouldn't** try to manually add `OAuthBearerAuthenticationOptions`. If you need to resolve `OAuthBearerAuthenticationOptions` from your own code, use `IOptions` instead: `context.RequestServices.GetRequiredService>().Options` – Kévin Chalet Jul 14 '15 at 15:22
  • That just returns null – Alex Justi Jul 14 '15 at 15:30
  • Then you're doing something wrong, as the default options manager CANNOT return null: https://github.com/aspnet/Options/blob/dev/src/Microsoft.Framework.OptionsModel/OptionsManager.cs#L37 – Kévin Chalet Jul 14 '15 at 15:33
  • It still throws IDX10503 Signature validation failed. I have to take a step back and review this before I continue. – Alex Justi Jul 14 '15 at 15:36
  • You should share your updated code (or better, a repro). Is the "Keys tried" message still empty? Are you sure you use a new JWT token after restarting your app? (since you generate a new RSA key each time your apps starts, old tokens are not valid anymore). – Kévin Chalet Jul 14 '15 at 15:41
  • I've got it to work. I've finally solved an issue that started a month ago. Thank you very much! – Alex Justi Jul 14 '15 at 15:44
  • 1
    You're welcome! As a side note, you **should really** consider using an OAuth2 or OpenID Connect server instead of directly relying on `JwtSecurityTokenHandler` to create your tokens, as it would offer a standardized and safer approach. – Kévin Chalet Jul 14 '15 at 15:46