A JSON Web Token (JWT) commonly carries authentication information from an identity provider to a web API. The API can leave account management to the provider and verify the token presented with a request. In ASP.NET Core, JWT bearer authentication handles the token; authorization determines which authenticated users may call an endpoint. section 9.5 section 9.6
Listing 9.15 Adding authentication and authorization
using Microsoft.AspNetCore.Authentication.JwtBearer; #1
builder.Services
.AddAuthentication(
JwtBearerDefaults.AuthenticationScheme) #2
.AddJwtBearer(); #3
var app = builder.Build(); #4
app.UseAuthentication(); #5
app.UseAuthorization(); #6
Register JWT bearer authentication, then place UseAuthentication before UseAuthorization in the request pipeline. The bearer scheme name used in policies must match the name configured for authentication; ASP.NET Core scheme names are not the same thing as HTTP authentication schemes. section 9.5
A JWT has three parts: a header, payload, and signature. The header identifies the token type and signing algorithm. The payload contains properties called claims. The signature can be checked against a signing key published through the provider’s discovery document to detect tampering. section 9.6
Claims and provider settings matter when deciding whether to accept a token:
- The audience (`aud`) identifies the intended recipient; the issuer (`iss`) identifies the authority that created the token. The not-before claim (`nbf`) says when use may begin. section 9.6
- An issuer mismatch can make a token invalid. For the illustrated Azure AD setup, `accessTokenAcceptedVersion` is set to `2` so the access-token issuer matches the authority in the OpenID configuration document. section 9.5.1
- Do not assume every provider issues JWT access tokens: Google does not use that format for its access tokens, while Microsoft’s tokens for its own properties can require custom settings when used by another application. section 9.5.1
Inspect a request, then authorize an action
Authenticate in Swagger UI, call a GET endpoint, and inspect the request in the browser’s Network tab. Its `Authorization` header contains `Bearer` followed by the token. A decoder can reveal claims, but treat the token as sensitive: it may contain personal information and can be used to impersonate you until it expires. A local desktop decoder is safer than pasting it into a website. In ASP.NET Core, an `[Authorize("AuthenticatedUsers")]` policy can protect GET actions, while a separate policy and requirement can restrict write actions using a claim. section 9.6
Listing 9.22 Custom authorization requirement and handler
using Microsoft.AspNetCore.Authorization;
namespace ManningBooksApi;
public class OnlyMeRequirement : #1
IAuthorizationRequirement { } #2
public class OnlyMeRequirementHandler :
AuthorizationHandler<OnlyMeRequirement> #3
{
protected override Task HandleRequirementAsync( #4
AuthorizationHandlerContext context, #5
OnlyMeRequirement requirement)
{
if (context.User != null) #6
{
var emailClaim = context.User
.FindFirst("preferred_username"); #7
if (emailClaim != null
&& emailClaim.Value == "your@email.com") #8
{
context.Succeed(requirement); #9
}
}
return Task.CompletedTask; #10
}
}
The custom authorization handler reads the `preferred_username` claim and succeeds only when it matches the configured email address. This is an application-specific authorization decision made after authentication, not a property that makes the JWT valid. section 9.6










