openiddict-documentation/configuration/authorization-storage.html
2021-01-25 17:47:01 +00:00

216 lines
10 KiB
HTML

<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Authorization storage </title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="Authorization storage ">
<meta name="generator" content="docfx 2.56.6.0">
<link rel="shortcut icon" href="../images/favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.css">
<link rel="stylesheet" href="../styles/docfx.css">
<link rel="stylesheet" href="../styles/main.css">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<meta property="docfx:navrel" content="../toc.html">
<meta property="docfx:tocrel" content="toc.html">
</head> <body data-spy="scroll" data-target="#affix" data-offset="120">
<div id="wrapper">
<header>
<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../images/logo.png" alt="">
</a> </div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>
<div class="subnav navbar navbar-default">
<div class="container hide-when-search" id="breadcrumb">
<ul class="breadcrumb">
<li></li>
</ul>
</div>
</div>
</header>
<div role="main" class="container body-content hide-when-search">
<div class="sidenav hide-when-search">
<a class="btn toc-toggle collapse" data-toggle="collapse" href="#sidetoggle" aria-expanded="false" aria-controls="sidetoggle">Show / Hide Table of Contents</a>
<div class="sidetoggle collapse" id="sidetoggle">
<div id="sidetoc"></div>
</div>
</div>
<div class="article row grid-right">
<div class="col-md-10">
<article class="content wrap" id="_content" data-uid="">
<h1 id="authorization-storage">Authorization storage</h1>
<p>To keep track of logical chains of tokens and user consents, OpenIddict supports storing authorizations
(also known as &quot;grants&quot; in some OpenID Connect implementations) in the database.</p>
<h2 id="types-of-authorizations">Types of authorizations</h2>
<p>Authorizations can be of two types: permanent and ad-hoc.</p>
<h3 id="permanent-authorizations">Permanent authorizations</h3>
<p><strong>Permanent authorizations are developer-defined authorizations</strong> created using the <code>IOpenIddictAuthorizationManager.CreateAsync()</code> API
and explicitly attached to a <code>ClaimsPrincipal</code> using the OpenIddict-specific <code>principal.SetAuthorizationId()</code> extension method.</p>
<p>Such authorizations are typically used to remember user consents and avoid displaying a consent view for each authorization request.
For that, a &quot;consent type&quot; can be defined per-application, as in the following example:</p>
<pre><code class="lang-csharp">// Retrieve the application details from the database.
var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
throw new InvalidOperationException(&quot;The application cannot be found.&quot;);
// 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&lt;string, string&gt;
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] =
Errors.ConsentRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
&quot;The logged in user is not allowed to access this client application.&quot;
}));
// 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() &amp;&amp;
!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&lt;string, string&gt;
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] =
Errors.ConsentRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
&quot;Interactive user consent is required.&quot;
}));
// In every other case, render the consent form.
default: return View(new AuthorizeViewModel
{
ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application),
Scope = request.Scope
});
}
</code></pre><h3 id="ad-hoc-authorizations">Ad-hoc authorizations</h3>
<p><strong>Ad-hoc authorizations are automatically created by OpenIddict when a chain of tokens needs to be tracked for security reasons</strong>,
but no explicit permanent authorization was attached by the developer to the <code>ClaimsPrincipal</code> used for the sign-in operation.</p>
<p>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.</p>
<blockquote><p>[!INFO]
When using the <a href="https://www.nuget.org/packages/OpenIddict.Quartz/">OpenIddict.Quartz</a> 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.</p>
</blockquote>
</article>
</div>
<div class="hidden-sm col-md-2" role="complementary">
<div class="sideaffix">
<div class="contribution">
<ul class="nav">
<li>
<a href="https://github.com/openiddict/openiddict-documentation/blob/dev/configuration/authorization-storage.md/#L1" class="contribution-link">Improve this Doc</a>
</li>
</ul>
</div>
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
<h5>In This Article</h5>
<div></div>
</nav>
</div>
</div>
</div>
</div>
<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>
<span>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
</div>
<script type="text/javascript" src="../styles/docfx.vendor.js"></script>
<script type="text/javascript" src="../styles/docfx.js"></script>
<script type="text/javascript" src="../styles/main.js"></script>
</body>
</html>