diff --git a/configuration/authorization-storage.md b/configuration/authorization-storage.md index 2a067d9..84a2713 100644 --- a/configuration/authorization-storage.md +++ b/configuration/authorization-storage.md @@ -112,7 +112,39 @@ Such authorizations are typically created in the authorization code flow to link so that they can be automatically revoked if the authorization code was redeemed multiple times (which may indicate a token leakage). In the same vein, ad-hoc authorizations are also created when a refresh token is returned during a resource owner password credentials grant request. -> [!INFO] +> [!NOTE] > When using the [OpenIddict.Quartz](https://www.nuget.org/packages/OpenIddict.Quartz/) integration, ad-hoc authorizations are automatically > removed from the database after a short period of time (14 days by default). Unlike ad-hoc authorizations, permanent authorizations -> never removed from the database. \ No newline at end of file +> are never removed from the database. + +## Enabling authorization entry validation at the API level + +**For performance reasons, OpenIddict 3.0 doesn't check, by default, the status of an authorization entry when receiving an API request**: access tokens are considered +valid even if the attached authorization was revoked. For scenarios that require immediate authorization revocation, the OpenIddict validation handler can be configured +to enforce authorization entry validation for each API request: + +> [!NOTE] +> Enabling authorization entry validation requires that the OpenIddict validation handler have a direct access to the server database where authorizations are stored, which makes it +> better suited for APIs located in the same application as the authorization server. For external applications, consider using introspection instead of local validation. +> +> In both cases, additional latency – caused by the additional DB request and the HTTP call for introspection – is expected. + +```csharp +services.AddOpenIddict() + .AddValidation(options => + { + options.EnableAuthorizationEntryValidation(); + }); +``` + +## Disabling authorization storage + +While STRONGLY discouraged, authorization storage can be disabled in the server options: + +```csharp +services.AddOpenIddict() + .AddServer(options => + { + options.DisableAuthorizationStorage(); + }); +``` \ No newline at end of file diff --git a/configuration/toc.yml b/configuration/toc.yml index a2e9af9..ae712c8 100644 --- a/configuration/toc.yml +++ b/configuration/toc.yml @@ -4,8 +4,11 @@ - name: Application permissions href: application-permissions.md +- name: Authorization storage + href: authorization-storage.md + - name: Token formats href: token-formats.md -- name: Authorization storage - href: authorization-storage.md \ No newline at end of file +- name: Token storage + href: token-storage.md \ No newline at end of file diff --git a/configuration/token-formats.md b/configuration/token-formats.md index 6614971..49d9020 100644 --- a/configuration/token-formats.md +++ b/configuration/token-formats.md @@ -1,5 +1,11 @@ # Token formats +> [!NOTE] +> In OpenIddict 3.0, being able to revoke a token is not tied to the token format and doesn't require enabling reference tokens: +> regular JWT or ASP.NET Core Data Protection tokens can be revoked as long as token storage is not explicitly disabled by the developer +> +> For more information about reference tokens, read [Token storage](token-storage.md). + ## 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) diff --git a/configuration/token-storage.md b/configuration/token-storage.md new file mode 100644 index 0000000..8c4ccdc --- /dev/null +++ b/configuration/token-storage.md @@ -0,0 +1,71 @@ +# Token storage + +To keep track of all the tokens produced by its server services, OpenIddict 3.0 creates a token entry in the database for each generated token. +A token entry contains metadata like the subject of the token, the client identifier of the application it was issued to or its creation and expiration dates. + +By default, the token payload – generated using either the +[Azure Active Directory IdentityModel Extensions for .NET library](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/) for JWT tokens or +[ASP.NET Core Data Protection](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/introduction) for Data Protection tokens – is never stored in the database, +except for authorization codes (that are short-lived), device and user codes (exclusively used in the device code flow). + +Such tokens – called reference tokens – are not returned as-is to the caller: instead, their payload is stored in the database entry and a crypto-secure random 256-bit identifier +– called reference identifier – is returned as a base64url-encoded string and serves as the "final" token used by the client application when communicating with OpenIddict's endpoints +or with resource servers (if reference access tokens are enabled in the server options). + +> [!NOTE] +> In OpenIddict 3.0, being able to revoke a token is not tied to the token format and doesn't require enabling reference tokens: +> regular JWT or ASP.NET Core Data Protection tokens can be revoked as long as token storage is not explicitly disabled by the developer. + +## Enabling reference access and/or refresh tokens + +Reference access and refresh tokens can be manually enabled in the server options for developers who prefer returning +shorter access and/or refresh tokens or need to deal with limits that would prevent sending large tokens over the wire. + +> [!CAUTION] +> When enabling reference access and/or refresh tokens support, it is STRONGLY recommended to either: +> - Use the ASP.NET Core Data Protection format for access and refresh tokens, as they benefit from additional security measures that would prevent them from being sent as-is if +> they were stolen from the database. For more information on how to enable ASP.NET Core Data Protection, read [Token formats](token-formats.md). +> - Enable column encryption/data at rest encryption to protect the `Payload` column of token entries. + +```csharp +services.AddOpenIddict() + .AddServer(options => + { + options.UseReferenceAccessTokens() + .UseReferenceRefreshTokens(); + }); +``` + +## Enabling token entry validation at the API level + +**For performance reasons, OpenIddict 3.0 doesn't check, by default, the status of a token entry when receiving an API request**: access tokens are considered valid until they expire. +For scenarios that require immediate access token revocation, the OpenIddict validation handler can be configured to enforce token entry validation for each API request: + +> [!NOTE] +> Enabling token entry validation requires that the OpenIddict validation handler have a direct access to the server database where tokens are stored, which makes it +> better suited for APIs located in the same application as the authorization server. For external applications, consider using introspection instead of local validation. +> +> In both cases, additional latency – caused by the additional DB request and the HTTP call for introspection – is expected. + +```csharp +services.AddOpenIddict() + .AddValidation(options => + { + options.EnableTokenEntryValidation(); + }); +``` + +## Disabling token storage + +While STRONGLY discouraged, token storage can be disabled in the server options: + +```csharp +services.AddOpenIddict() + .AddServer(options => + { + options.DisableTokenStorage(); + }); +``` + +> [!WARNING] +> Disabling token storage prevents reference access or refresh tokens support from being enabled, as this requires storing the tokens in the database. \ No newline at end of file