fix(auth): preserve JWT claim names in bearer middleware

JwtBearerOptions.MapInboundClaims defaulted to true, which mapped the
'sub' claim to ClaimTypes.NameIdentifier in HttpContext.User. Logout
endpoint read User.FindFirst("sub") and got null, returning 401 for
any authenticated caller.

Fix: set MapInboundClaims=false and pin NameClaimType="name" so the
JWT claims land in the principal with their original names, aligning
with how JwtService.GetPrincipalFromExpiredToken (used by refresh)
already consumes them.

Unblocks Login_Refresh_Logout_FullFlow integration test (15/15 green).
This commit is contained in:
2026-04-15 11:03:15 -03:00
parent dd99e5cc69
commit bce591e63c

View File

@@ -72,10 +72,13 @@ public static class DependencyInjection
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(); .AddJwtBearer();
// Post-configure JWT Bearer — wire RSA public key + validation params from resolved options // Post-configure JWT Bearer — wire RSA public key + validation params from resolved options.
// MapInboundClaims=false: preserve JWT claim names as-is ("sub", "rol", etc.).
// Without this, the middleware maps "sub" → ClaimTypes.NameIdentifier and breaks User.FindFirst("sub").
services.AddOptions<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme) services.AddOptions<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme)
.PostConfigure<RsaSecurityKey, JwtOptions>((jwtBearerOpts, rsaKey, jwtOpts) => .PostConfigure<RsaSecurityKey, JwtOptions>((jwtBearerOpts, rsaKey, jwtOpts) =>
{ {
jwtBearerOpts.MapInboundClaims = false;
jwtBearerOpts.TokenValidationParameters = new TokenValidationParameters jwtBearerOpts.TokenValidationParameters = new TokenValidationParameters
{ {
ValidateIssuerSigningKey = true, ValidateIssuerSigningKey = true,
@@ -86,7 +89,8 @@ public static class DependencyInjection
ValidAudience = jwtOpts.Audience, ValidAudience = jwtOpts.Audience,
ValidateLifetime = true, ValidateLifetime = true,
ClockSkew = TimeSpan.Zero, ClockSkew = TimeSpan.Zero,
RoleClaimType = "rol" RoleClaimType = "rol",
NameClaimType = "name"
}; };
}); });