title | author | description | monikerRange | ms.author | ms.custom | ms.date | uid |
---|---|---|---|---|---|---|---|
Configure JWT bearer authentication in ASP.NET Core |
damienbod |
Learn how to set up JWT bearer authentication in an ASP.NET Core app. |
>= aspnetcore-8.0 |
riande |
mvc |
12/7/2024 |
security/authentication/configure-jwt-bearer-authentication |
This article covers the following areas:
- Token types
- Using JWT tokens to secure an APIs
- How OIDC/OAuth fits into this?
- Examples with code snippets
- Recommended approaches to create a JWT
- Downstream APIs
- Advanced features, standards
- Testing APIs
Is this really authentication?
Using Bearer tokens as the authentication method is not really authentication but more authorization. The authentication is implemented when requesting access tokens for the first time in a UI application. This can also be described as delegated authorization. Using bearer tokens, you do not know who or what sent the access token and you do not know how the access token was acquired. The application can only say if the token is valid to use the requested API.
There are many different types of tokens and many formats. You should not be creating access tokens or ID tokens yourself unless in testing scenarios. Creating self-made tokens and not following standards usually ends up with security problems and can only be used in closed systems. It is recommended to use OpenID Connect and/or OAuth to create access tokens for API access.
An access token is a string used by a client application to make requests to the server implementing an API. Access tokens can vary in format and different APIs may use different formats for their tokens.
An access token can be encrypted. Access tokens should never be read or interpreted by a web client or UI application holding the access token, only an API is the intended audience.
Access tokens are intended solely for making requests to an API. This is normally sent to the API is the Authorization request header as a bearer token.
When requesting or creating an access token, an application or an application acting on behalf of a user can request and access token. The tokens are application access tokens or delegated access tokens. The tokens have different claims and are handled and persisted in different ways. An application is normally persisted once in the application until it expires where the delegated access token is persisted per user, either in a cookie or in a cache on a secure server.
It is recommended to user-delegated user access tokens whenever a user is involved. Downstream APIs can request a delegated user access token on behalf of the authenticated user.
There are two types of access tokens: bearer tokens and sender-constrained tokens. Sender-constrained tokens require the requesting client to prove possession of a private key to use the token, making the token unusable on its own. Sender-constrained tokens can be implemented in two ways:
- Demonstrating Proof-of-Possession (DPoP)
- MTLS
ID tokens are security tokens that confirm a user’s successful authentication. They allow the client to verify the user’s identity. The authorization server issues ID tokens containing claims with user information. ID tokens are always in JWT (JSON Web Token) format.
ID tokens should never be used to access APIs.
There are many different types of tokens as well as access tokens and ID tokens. OpenID Connect and OAuth standards specify many different types. Refresh tokens can be used to refresh a UI application without authenticating the user again, OAuth JAR tokens can be used to send authorization requests is a secure way. Verifiable credentials using JWT types in issuing or verifying credentials. It is important to use the tokens following the specifications. Please refer to the Standards provided in the links for more information.
When using JWT access tokens to authorize an API, the request is valid, or not valid. If the request is not valid, a 401 response or a 403 response is returned. The API should never redirect to the identity provider to acquire more permissions or the correct access token. That is the responsibility of the UI requesting the data from the API.
A 401 response is returned when the access token has an invalid standard requirement. The OAuth specifications are clear which claims must be valid and how to validate the claims in the access token. This could be the wrong signature, or the token has expired or one of the required claims like the audience or the issuer is incorrect.
A 403 forbidden response is normally returned when a business permission is missing. The authorization has nothing to do with the authentication or the standard claims used in the access token. This could be implemented using an ASP.NET requirement with a policy or also a role authorization.
When using access tokens, only the access token is validated on the API. The process of acquiring the access token is unspecified. OpenID Connect and OAuth specify standards on how to acquire access tokens in a safe way. This process is different for every type of application. It is complicated to implement this in a safe way. This is why it is recommended to use one of the standards to create access tokens. OpenID Connect is used to create access tokens for an application and a user. These access tokens are user delegated access tokens. In a web application, a confidential OpenID Connect code flow using PKCE is the recommended way to implement this. If the application has no user, OAuth client credentials can be used to acquire an application access token.
Refer to the following document:
Mapping, customizing, and transforming claims in ASP.NET Core
The OAuth 2.0 Authorization Framework
OAuth 2.0 Demonstrating Proof of Possession DPoP
OAuth 2.0 JWT-Secured Authorization Request (JAR) RFC 9101
OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens