mirror of
https://gitee.com/dcren/openiddict-documentation.git
synced 2025-07-19 07:44:50 +08:00
118 lines
6.0 KiB
Markdown
118 lines
6.0 KiB
Markdown
![]() |
# Authorization storage
|
||
|
|
||
|
To keep track of logical chains of tokens and user consents, OpenIddict supports storing authorizations
|
||
|
(also known as "grants" in some OpenID Connect implementations) in the database.
|
||
|
|
||
|
## Types of authorizations
|
||
|
|
||
|
Authorizations can be of two types: permanent and ad-hoc.
|
||
|
|
||
|
### Permanent authorizations
|
||
|
|
||
|
**Permanent authorizations are developer-defined authorizations** created using the `IOpenIddictAuthorizationManager.CreateAsync()` API
|
||
|
and explicitly attached to a `ClaimsPrincipal` using the OpenIddict-specific `principal.SetAuthorizationId()` extension method.
|
||
|
|
||
|
Such authorizations are typically used to remember user consents and avoid displaying a consent view for each authorization request.
|
||
|
For that, a "consent type" can be defined per-application, as in the following example:
|
||
|
|
||
|
```csharp
|
||
|
// Retrieve the application details from the database.
|
||
|
var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
|
||
|
throw new InvalidOperationException("The application cannot be found.");
|
||
|
|
||
|
// Retrieve the permanent authorizations associated with the user and the application.
|
||
|
var authorizations = await _authorizationManager.FindAsync(
|
||
|
subject: await _userManager.GetUserIdAsync(user),
|
||
|
client : await _applicationManager.GetIdAsync(application),
|
||
|
status : Statuses.Valid,
|
||
|
type : AuthorizationTypes.Permanent,
|
||
|
scopes : request.GetScopes()).ToListAsync();
|
||
|
|
||
|
switch (await _applicationManager.GetConsentTypeAsync(application))
|
||
|
{
|
||
|
// If the consent is external (e.g when authorizations are granted by a sysadmin),
|
||
|
// immediately return an error if no authorization can be found in the database.
|
||
|
case ConsentTypes.External when !authorizations.Any():
|
||
|
return Forbid(
|
||
|
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
|
||
|
properties: new AuthenticationProperties(new Dictionary<string, string>
|
||
|
{
|
||
|
[OpenIddictServerAspNetCoreConstants.Properties.Error] =
|
||
|
Errors.ConsentRequired,
|
||
|
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
|
||
|
"The logged in user is not allowed to access this client application."
|
||
|
}));
|
||
|
|
||
|
// If the consent is implicit or if an authorization was found,
|
||
|
// return an authorization response without displaying the consent form.
|
||
|
case ConsentTypes.Implicit:
|
||
|
case ConsentTypes.External when authorizations.Any():
|
||
|
case ConsentTypes.Explicit when authorizations.Any() &&
|
||
|
!request.HasPrompt(Prompts.Consent):
|
||
|
var principal = await _signInManager.CreateUserPrincipalAsync(user);
|
||
|
|
||
|
// Note: in this sample, the granted scopes match the requested scope
|
||
|
// but you may want to allow the user to uncheck specific scopes.
|
||
|
// For that, simply restrict the list of scopes before calling SetScopes.
|
||
|
principal.SetScopes(request.GetScopes());
|
||
|
principal.SetResources(await _scopeManager.ListResourcesAsync(
|
||
|
principal.GetScopes()).ToListAsync());
|
||
|
|
||
|
// Automatically create a permanent authorization to avoid requiring explicit consent
|
||
|
// for future authorization or token requests containing the same scopes.
|
||
|
var authorization = authorizations.LastOrDefault();
|
||
|
if (authorization is null)
|
||
|
{
|
||
|
authorization = await _authorizationManager.CreateAsync(
|
||
|
principal: principal,
|
||
|
subject : await _userManager.GetUserIdAsync(user),
|
||
|
client : await _applicationManager.GetIdAsync(application),
|
||
|
type : AuthorizationTypes.Permanent,
|
||
|
scopes : principal.GetScopes());
|
||
|
}
|
||
|
|
||
|
principal.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization));
|
||
|
|
||
|
foreach (var claim in principal.Claims)
|
||
|
{
|
||
|
claim.SetDestinations(GetDestinations(claim, principal));
|
||
|
}
|
||
|
|
||
|
return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
|
||
|
|
||
|
// At this point, no authorization was found in the database and an error must be returned
|
||
|
// if the client application specified prompt=none in the authorization request.
|
||
|
case ConsentTypes.Explicit when request.HasPrompt(Prompts.None):
|
||
|
case ConsentTypes.Systematic when request.HasPrompt(Prompts.None):
|
||
|
return Forbid(
|
||
|
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
|
||
|
properties: new AuthenticationProperties(new Dictionary<string, string>
|
||
|
{
|
||
|
[OpenIddictServerAspNetCoreConstants.Properties.Error] =
|
||
|
Errors.ConsentRequired,
|
||
|
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
|
||
|
"Interactive user consent is required."
|
||
|
}));
|
||
|
|
||
|
// In every other case, render the consent form.
|
||
|
default: return View(new AuthorizeViewModel
|
||
|
{
|
||
|
ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application),
|
||
|
Scope = request.Scope
|
||
|
});
|
||
|
}
|
||
|
```
|
||
|
|
||
|
### Ad-hoc authorizations
|
||
|
|
||
|
**Ad-hoc authorizations are automatically created by OpenIddict when a chain of tokens needs to be tracked for security reasons**,
|
||
|
but no explicit permanent authorization was attached by the developer to the `ClaimsPrincipal` used for the sign-in operation.
|
||
|
|
||
|
Such authorizations are typically created in the authorization code flow to link all the tokens associated with the original authorization code,
|
||
|
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]
|
||
|
> 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.
|