diff --git a/configuration/application-permissions.md b/configuration/application-permissions.md index be8941c..9f094ad 100644 --- a/configuration/application-permissions.md +++ b/configuration/application-permissions.md @@ -79,6 +79,7 @@ Grant type permissions limit the grant types a client application is allowed to | Refresh token | `OpenIddictConstants.Permissions.GrantTypes.RefreshToken` | To add a custom grant type permission, you can use the following pattern: + ```csharp OpenIddictConstants.Permissions.Prefixes.GrantType + "custom_flow_name" ``` @@ -141,6 +142,7 @@ services.AddOpenIddict() Scope permissions limit the scopes (standard or custom) a client application is allowed to use. +> [!NOTE] > The `openid` and `offline_access` scopes are special-cased by OpenIddict and don't require explicit permissions. ### Supported permissions @@ -154,6 +156,7 @@ Scope permissions limit the scopes (standard or custom) a client application is | roles | `OpenIddictConstants.Permissions.Scopes.Roles` | To add a custom scope permission, you can use the following pattern: + ```csharp OpenIddictConstants.Permissions.Prefixes.Scope + "custom_scope_name" ``` diff --git a/configuration/index.md b/configuration/index.md index 6f39343..8f913ab 100644 --- a/configuration/index.md +++ b/configuration/index.md @@ -9,4 +9,12 @@ +
+
+
+

Token formats

+

Learn more about the token formats supported by OpenIddict.

+
+
+
\ No newline at end of file diff --git a/configuration/toc.yml b/configuration/toc.yml index 60a90d6..07724e5 100644 --- a/configuration/toc.yml +++ b/configuration/toc.yml @@ -2,4 +2,7 @@ href: index.md - name: Application permissions - href: application-permissions.md \ No newline at end of file + href: application-permissions.md + +- name: Token formats + href: token-formats.md \ No newline at end of file diff --git a/configuration/token-formats.md b/configuration/token-formats.md new file mode 100644 index 0000000..6614971 --- /dev/null +++ b/configuration/token-formats.md @@ -0,0 +1,99 @@ +# Token formats + +## JSON Web Token + +OpenIddict 3.0 implements the [JSON Web Token](https://tools.ietf.org/html/rfc7519), [JSON Web Signature](https://tools.ietf.org/html/rfc7515) +and [JSON Web Encryption](https://tools.ietf.org/html/rfc7516) standards and relies on the +[Azure Active Directory IdentityModel Extensions for .NET library](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/) +developed and maintained by Microsoft to generate signed and encrypted tokens using the credentials registered in the server options. + +### JWT token types + +To protect against token substitution and confused deputy attacks, **OpenIddict 3.0 uses the standard `typ` JWT header to convey the actual token type**. +This mechanism replaces the private `token_usage` claim used for the same purpose in previous versions of OpenIddict. + +As required by the [JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens draft](https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-04#section-2.1), +**access tokens produced by OpenIddict 3.0 are always issued with a `"typ": "at+jwt"` header** while identity tokens still use `"typ": "JWT"` for backward compatibility. +Other types of tokens – only accepted by OpenIddict's own endpoints – use private token types prefixed by `oi_`. + +### Disabling JWT access token encryption + +By default, **OpenIddict enforces encryption for all the token types it supports**. While this enforcement cannot be disabled for authorization codes, +refresh tokens and device codes for security reasons, it can be relaxed for access tokens when integration with third-party APIs/resource servers is desired. +Access token encryption can also be disabled if the resource servers receiving the access tokens don't fully support JSON Web Encryption. + +```csharp +services.AddOpenIddict() + .AddServer(options => + { + options.DisableAccessTokenEncryption(); + }); +``` + +## ASP.NET Core Data Protection + +OpenIddict 3.0 can also be configured to use [ASP.NET Core Data Protection](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/introduction) to create +Data Protection tokens instead of JWT tokens. ASP.NET Core Data Protection uses its own key ring to encrypt and protect tokens against tampering and is supported for all +types of tokens, except identity tokens, that are always JWT tokens. + +Unlike JWT, ASP.NET Core Data Protection tokens only support symmetric encryption and rely on a binary format developed by the ASP.NET team rather than on a standard like JWT. +While this prevents using such tokens in scenarios where interoperability is needed, opting for ASP.NET Core Data Protection rather than JWT has actually a few advantages: + - ASP.NET Core Data Protection tokens don't use a JSON representation and therefore are generally a bit shorter. + - ASP.NET Core Data Protection has been designed to achieve high throughput as it's natively used by ASP.NET Core for authentication cookies, + antiforgery tokens and session cookies. + +> [!WARNING] +> Despite its name, ASP.NET Core Data Protection is not tied to ASP.NET Core and can be used in any +> .NET Standard 2.0-compatible application, including legacy ASP.NET 4.x applications using `Microsoft.Owin`. +> +> To enable ASP.NET Core Data Protection support in the OpenIddict OWIN server and validation hosts, you need to +> manually reference the `OpenIddict.Server.DataProtection` and `OpenIddict.Validation.DataProtection` packages. + +### Switching to Data Protection tokens + +ASP.NET Core Data Protection support is provided by the `OpenIddict.Server.DataProtection` and `OpenIddict.Validation.DataProtection` packages. +These packages are referenced by the `OpenIddict.AspNetCore` metapackage and therefore don't have to be referenced explicitly. + +To enable ASP.NET Core Data Protection support, call `options.UseDataProtection()` in **both the server and validation options**: + +```csharp +services.AddOpenIddict() + .AddServer(options => + { + options.UseDataProtection(); + }) + + .AddValidation(options => + { + options.UseDataProtection(); + }); +``` + +> [!NOTE] +> Switching to ASP.NET Core Data Protection tokens doesn't prevent JWT tokens issued before Data Protection support was enabled from being validated: +> existing tokens can still be used alongside newly issued ASP.NET Core Data Protection tokens until they expire. When sending a refresh token request containing +> a JWT refresh token, the application will receive an ASP.NET Core Data Protection refresh token and the previous one will be automatically marked as redeemed. + +By default, enabling ASP.NET Core Data Protection support will automatically switch the token format from JWT to Data Protection for all tokens, except JWT tokens. +The OpenIddict/Data Protection integration can be configured to prefer JWT when creating new tokens, **which can be useful to use the ASP.NET Core Data Protection +format for specific token types only** (e.g for authorization codes and refresh tokens, but not for access tokens). + +```csharp +services.AddOpenIddict() + .AddServer(options => + { + options.UseDataProtection() + .PreferDefaultAccessTokenFormat() + .PreferDefaultAuthorizationCodeFormat() + .PreferDefaultDeviceCodeFormat() + .PreferDefaultRefreshTokenFormat() + .PreferDefaultUserCodeFormat(); + }); +``` + +> [!WARNING] +> When the authorization and API/resource servers are not part of the same application, ASP.NET Core Data Protection MUST be configured to use +> the same application name and share the same key ring to allow OpenIddict validation's handler to read ASP.NET Core Data Protection tokens +> generated by an authorization server located in another project. +> +> For more information, read [Configure ASP.NET Core Data Protection](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview). \ No newline at end of file