mirror of
https://gitee.com/dcren/openiddict-documentation.git
synced 2025-07-15 23:13:34 +08:00
236 lines
12 KiB
HTML
236 lines
12 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>What's OpenIddict? </title>
|
|
<meta name="viewport" content="width=device-width">
|
|
<meta name="title" content="What's OpenIddict? ">
|
|
<meta name="generator" content="docfx 2.56.7.0">
|
|
|
|
<link rel="shortcut icon" href="../images/favicon.ico">
|
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/night-owl.min.css">
|
|
<link rel="stylesheet" href="../styles/colors.css">
|
|
<link rel="stylesheet" href="../styles/discord.css">
|
|
<link rel="stylesheet" href="../styles/main.css">
|
|
<meta property="docfx:navrel" content="../toc.html">
|
|
<meta property="docfx:tocrel" content="toc.html">
|
|
|
|
|
|
|
|
</head>
|
|
|
|
<body>
|
|
<div class="top-navbar">
|
|
|
|
<a href="javascript:void(0);" class="burger-icon" onclick="toggleMenu()">
|
|
<svg name="Hamburger" style="vertical-align: middle;" width="24" height="24" viewbox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M20 6H4V9H20V6ZM4 10.999H20V13.999H4V10.999ZM4 15.999H20V18.999H4V15.999Z"></path></svg>
|
|
</a>
|
|
|
|
|
|
<a class="brand" href="../index.html">
|
|
<img src="../images/logo.png" alt="OpenIddict" class="logomark">
|
|
<span class="brand-title">OpenIddict</span>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="body-content">
|
|
|
|
<div id="blackout" class="blackout" onclick="toggleMenu()"></div>
|
|
|
|
<nav id="sidebar" role="navigation">
|
|
|
|
<div class="sidebar">
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<a class="brand" href="../index.html">
|
|
<img src="../images/logo.png" alt="OpenIddict" class="logomark">
|
|
<span class="brand-title">OpenIddict</span>
|
|
</a>
|
|
<div id="navbar">
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<div class="sidebar-item-separator"></div>
|
|
|
|
|
|
<div id="sidetoggle">
|
|
<div id="sidetoc"></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="footer">
|
|
|
|
<span>Generated by <strong>DocFX</strong></span>
|
|
</div>
|
|
</nav>
|
|
|
|
<main class="main-panel">
|
|
|
|
<div role="main" class="hide-when-search">
|
|
|
|
|
|
<div class="subnav navbar navbar-default">
|
|
<div class="container hide-when-search" id="breadcrumb">
|
|
<ul class="breadcrumb">
|
|
<li></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<article class="content wrap" id="_content" data-uid="">
|
|
<h2 id="whats-openiddict">What's OpenIddict?</h2>
|
|
|
|
<p>OpenIddict is <strong>an open source and versatile framework for building standard-compliant OAuth 2.0/OpenID Connect servers</strong>
|
|
in any ASP.NET Core 2.1 (and higher) and legacy ASP.NET 4.6.1 (and higher) applications.</p>
|
|
<p>OpenIddict was born in late 2015 and was initially based on <a href="https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server">AspNet.Security.OpenIdConnect.Server</a>
|
|
(codenamed ASOS), a low-level OpenID Connect server middleware inspired by the OAuth 2.0 authorization server middleware developed by Microsoft for the OWIN project
|
|
and the first OpenID Connect server ever created for ASP.NET Core.</p>
|
|
<p>In 2020, ASOS was merged into OpenIddict 3.0 to form a unified stack under the OpenIddict umbrella, while still offering an easy-to-use approach for new users
|
|
and a low-level experience for advanced users thanks to a "degraded mode" that allows using OpenIddict in a stateless way (i.e without a backing database).</p>
|
|
<p>As part of this process, native support for <code>Microsoft.Owin</code> was added to OpenIddict 3.0 to allow using it in legacy ASP.NET 4.6.1 (and higher) applications,
|
|
making it an excellent candidate for replacing <code>OAuthAuthorizationServerMiddleware</code> and <code>OAuthBearerAuthenticationMiddleware</code> without having to migrate to ASP.NET Core.</p>
|
|
<h2 id="core-concepts">Core concepts</h2>
|
|
<h3 id="user-authentication">User authentication</h3>
|
|
<p>Unlike other solutions, <strong>OpenIddict exclusively focuses on the OAuth 2.0/OpenID Connect protocol aspects of the authorization process</strong>
|
|
and leaves user authentication up to the implementer: OpenIddict can be natively used with any form of user authentication like password, token,
|
|
federated or Integration Windows Authentication. While convenient, using a membership stack like ASP.NET Core Identity is not required.</p>
|
|
<p>Integration with OpenIddict is typically done by enabling the pass-through mode to handle requests in a controller action
|
|
or in a minimal API handler or, for more complex scenarios, by directly using its advanced events model.</p>
|
|
<h3 id="pass-through-mode">Pass-through mode</h3>
|
|
<p>As with <code>OAuthAuthorizationServerMiddleware</code>, OpenIddict allows handling authorization, logout and token requests in custom controller actions or any other
|
|
middleware able to hook into the ASP.NET Core or OWIN request processing pipeline. In this case, OpenIddict will always validate incoming requests first
|
|
(e.g by ensuring the mandatory parameters are present and valid) before allowing the rest of the pipeline to be invoked: should any validation error occur,
|
|
OpenIddict will automatically reject the request before it reaches user-defined controller actions or custom middleware.</p>
|
|
<pre><code class="lang-csharp">builder.Services.AddOpenIddict()
|
|
.AddServer(options =>
|
|
{
|
|
// Enable the authorization and token endpoints.
|
|
options.SetAuthorizationEndpointUris("/authorize")
|
|
.SetTokenEndpointUris("/token");
|
|
|
|
// Enable the authorization code flow.
|
|
options.AllowAuthorizationCodeFlow();
|
|
|
|
// Register the signing and encryption credentials.
|
|
options.AddDevelopmentEncryptionCertificate()
|
|
.AddDevelopmentSigningCertificate();
|
|
|
|
// Register the ASP.NET Core host and configure the authorization endpoint
|
|
// to allow the /authorize minimal API handler to handle authorization requests
|
|
// after being validated by the built-in OpenIddict server event handlers.
|
|
//
|
|
// Token requests will be handled by OpenIddict itself by reusing the identity
|
|
// created by the /authorize handler and stored in the authorization codes.
|
|
options.UseAspNetCore()
|
|
.EnableAuthorizationEndpointPassthrough();
|
|
});
|
|
</code></pre><pre><code class="lang-csharp">app.MapGet("/authorize", async (HttpContext context) =>
|
|
{
|
|
// Resolve the claims stored in the principal created after the Steam authentication dance.
|
|
// If the principal cannot be found, trigger a new challenge to redirect the user to Steam.
|
|
var principal = (await context.AuthenticateAsync(SteamAuthenticationDefaults.AuthenticationScheme))?.Principal;
|
|
if (principal is null)
|
|
{
|
|
return Results.Challenge(properties: null, new[] { SteamAuthenticationDefaults.AuthenticationScheme });
|
|
}
|
|
|
|
var identifier = principal.FindFirst(ClaimTypes.NameIdentifier)!.Value;
|
|
|
|
// Create a new identity and import a few select claims from the Steam principal.
|
|
var identity = new ClaimsIdentity(TokenValidationParameters.DefaultAuthenticationType);
|
|
identity.AddClaim(new Claim(Claims.Subject, identifier));
|
|
identity.AddClaim(new Claim(Claims.Name, identifier).SetDestinations(Destinations.AccessToken));
|
|
|
|
return Results.SignIn(new ClaimsPrincipal(identity), properties: null, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
|
|
});
|
|
</code></pre><h3 id="events-model">Events model</h3>
|
|
<p>OpenIddict implements a powerful event-based model for its server and validation stacks: each part of the request processing logic is implemented as an event handler
|
|
that can be removed, moved to a different position in the pipeline or replaced by a custom handler to override the default logic used by OpenIddict:</p>
|
|
<pre><code class="lang-csharp">/// <summary>
|
|
/// Contains the logic responsible of rejecting authorization requests that don't specify a valid prompt parameter.
|
|
/// </summary>
|
|
public class ValidatePromptParameter : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
|
|
{
|
|
/// <summary>
|
|
/// Gets the default descriptor definition assigned to this handler.
|
|
/// </summary>
|
|
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
|
|
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
|
|
.UseSingletonHandler<ValidatePromptParameter>()
|
|
.SetOrder(ValidateNonceParameter.Descriptor.Order + 1_000)
|
|
.SetType(OpenIddictServerHandlerType.BuiltIn)
|
|
.Build();
|
|
|
|
/// <inheritdoc/>
|
|
public ValueTask HandleAsync(ValidateAuthorizationRequestContext context)
|
|
{
|
|
if (context is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(context));
|
|
}
|
|
|
|
// Reject requests specifying prompt=none with consent/login or select_account.
|
|
if (context.Request.HasPrompt(Prompts.None) && (context.Request.HasPrompt(Prompts.Consent) ||
|
|
context.Request.HasPrompt(Prompts.Login) ||
|
|
context.Request.HasPrompt(Prompts.SelectAccount)))
|
|
{
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6040));
|
|
|
|
context.Reject(
|
|
error: Errors.InvalidRequest,
|
|
description: SR.FormatID2052(Parameters.Prompt),
|
|
uri: SR.FormatID8000(SR.ID2052));
|
|
|
|
return default;
|
|
}
|
|
|
|
return default;
|
|
}
|
|
}
|
|
</code></pre><p>In OpenIddict itself, event handlers are typically defined as dedicated classes but they can also be registered using delegates:</p>
|
|
<pre><code class="lang-csharp">services.AddOpenIddict()
|
|
.AddServer(options =>
|
|
{
|
|
options.AddEventHandler<HandleConfigurationRequestContext>(builder =>
|
|
builder.UseInlineHandler(context =>
|
|
{
|
|
// Attach custom metadata to the configuration document.
|
|
context.Metadata["custom_metadata"] = 42;
|
|
|
|
return default;
|
|
}));
|
|
});
|
|
</code></pre></article>
|
|
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
|
|
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
|
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
|
|
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js"></script>
|
|
<script type="text/javascript" src="../styles/jquery.twbsPagination.js"></script>
|
|
<script type="text/javascript" src="../styles/url.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/anchor-js/anchor.min.js"></script>
|
|
<script type="text/javascript" src="../styles/docfx.js"></script>
|
|
<script type="text/javascript" src="../styles/main.js"></script>
|
|
|
|
</body>
|
|
|
|
</html>
|