'Validate Google JWT with .NET Core 6 - Always ending up with a 401
My ASP.NET Core WebApi (.NET 6) should authenticate incoming requests using a JWT in their Bearer header.
JWTs are being issued by Google, so in Program.cs I have a custom token validator, i.e. GoogleTokenValidator
:
builder.Services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o =>
{
o.IncludeErrorDetails = true;
o.SecurityTokenValidators.Clear();
o.SecurityTokenValidators.Add(new GoogleTokenValidator());
o.SaveToken = true;
});
Here's the validator code:
using Google.Apis.Auth;
// ..
public class GoogleTokenValidator : ISecurityTokenValidator
{
// ...
public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
{
var payload = GoogleJsonWebSignature.ValidateAsync(securityToken, new GoogleJsonWebSignature.ValidationSettings()).Result;
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, payload.Name),
new Claim(ClaimTypes.Name, payload.Name),
new Claim(JwtRegisteredClaimNames.FamilyName, payload.FamilyName),
new Claim(JwtRegisteredClaimNames.GivenName, payload.GivenName),
new Claim(JwtRegisteredClaimNames.Email, payload.Email),
new Claim(JwtRegisteredClaimNames.Sub, payload.Subject),
new Claim(JwtRegisteredClaimNames.Iss, payload.Issuer),
};
var principal = new ClaimsPrincipal();
principal.AddIdentity(new ClaimsIdentity(claims, "Google"));
validatedToken = new JwtSecurityToken(securityToken); // it was = null;
return principal;
}
}
Which is exactly what I see in this answer apart from the second-to-last line of code, where the original validatedToken = null;
got HandleAuthenticateAsync()
in JwtBearerHandler
furiously mad and slapping me with 401s because of this check:
tokenValidatedContext.Properties.ExpiresUtc = GetSafeDateTime(validatedToken.ValidTo);
Is it right to assign new JwtSecurityToken(securityToken)
then? If so, why did the original null
work?
ADDED Here's my full Program.cs:
using Core.API.Infrastructure.OAuth;
using Core.API.Infrastructure.WebApplicationBuilderServices;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using System.Runtime.ExceptionServices;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddAuthentication(authenticationOptions =>
{
authenticationOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
authenticationOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
authenticationOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwtBearerOptions =>
{
jwtBearerOptions.IncludeErrorDetails = true;
jwtBearerOptions.SecurityTokenValidators.Clear();
jwtBearerOptions.SecurityTokenValidators.Add(new GoogleTokenValidator());
jwtBearerOptions.SaveToken = true;
});
builder.Services.AddSwagger();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|