Discussion: Microsoft.AspNetCore.Authentication.JwtBearer contains absurd amount of black magic
See original GitHub issueFrom @ryanelian on August 28, 2016 14:56
I am trying to develop a ASP.NET application using JWT for securing certain routes and then decided that I would use app.UseJwtBearerAuthentication()
to make my life easier by not reinventing the wheel. (And so I can use [Authorize]
and call it a day)
However, instead of speeding up an entire day of work, I ended up investigating for hours why a perfectly fine Authorization: Bearer insert_jwt_token_here
results in 401 Unauthorized response from the server.
The token in question was generated using the trusty jose-jwt and successfully parsed and verified using jwt.io and the jose-jwt itself so I’m quite confident that the token is correct.
After hours of browsing and reading blogs with no avail, I decided to download the source from Release branch directly and perform step by step debugging by putting a breakpoint in JwtBearerHandler
. (Curiously, Microsoft.AspNetCore.Authentication
failed to compile unless I enable the nightly myget feed for alpha 1.1.0, because Microsoft.Extensions.SecurityHelper.Sources
1.0.0 doesn’t exist in NuGet.)
Surprisingly, the token in question was failed to be validated by the signature validator because of this:
IDX10503: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey , KeyId:
'.
Exceptions caught:
'System.ArgumentOutOfRangeException: IDX10603: The algorithm: 'HS256' cannot have less than: '128' bits. KeySize is: '112'.
Parameter name: key.KeySize
at Microsoft.IdentityModel.Tokens.SymmetricSignatureProvider..ctor(SecurityKey key, String algorithm)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForVerifying(SecurityKey key, String algorithm)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(Byte[] encodedBytes, Byte[] signature, SecurityKey key, String algorithm, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
'.
token: '{"alg":"HS256","typ":"JWT"}.{"iss":"TAM.Passport","sub":"ryanelian","iat":1472392366,"exp":1472393266,"jti":"9edb6556-dfa8-4d3e-99ee-4517e986bd01","FirstName":"Ryan","LastName":"Elian","Email":"ryan@email.com","EmployeeId":"12345678","Roles":["Administrator","Programmer"]}'
Apparently, my development secret key ACCELISTROCKS!
was too short according to the validator. This is quite an undocumented surprise. So I ended up increasing the secret key to ACCELISTROCKSBOOMBOOMFIRE!
and the validator works.
However, the token failed to be validated once again:
IDX10208: Unable to validate audience. validationParameters.ValidAudience is null or whitespace and validationParameters.ValidAudiences is null.
at Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateAudience(IEnumerable`1 audiences, JwtSecurityToken securityToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.<HandleAuthenticateAsync>d__1.MoveNext() in D:\VS\TAM.Passport\src\Microsoft.AspNetCore.Authentication.JwtBearer\JwtBearerHandler.cs:line 100
I didn’t remember asking the TokenValidationParameters to validate Audience…
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(this.TokenSecretKey),
ValidateIssuer = true,
ValidIssuer = TokenService.Issuer,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticChallenge = true,
AutomaticAuthenticate = true,
TokenValidationParameters = tokenValidationParameters,
});
So I ended up putting these into the TokenValidationParameters
for good measure:
ValidateAudience = false,
ValidateActor = false,
After I did that, the authorization finally works as intended.
I hope this issue can serve as a mini-blog for other people who are scratching their head over this issue.
Copied from original issue: aspnet/Security#959
Issue Analytics
- State:
- Created 7 years ago
- Reactions:5
- Comments:8 (4 by maintainers)
Top GitHub Comments
That seems like a really bad idea to me.
Doesn’t it do that via logging already?
Thanks