mirror of
https://gitee.com/dcren/openiddict-documentation.git
synced 2025-09-22 20:13:32 +08:00
Update the documentation pages
This commit is contained in:
@@ -2,15 +2,15 @@
|
||||
<!--[if IE]><![endif]-->
|
||||
<html>
|
||||
|
||||
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Choosing the right flow </title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta name="title" content="Choosing the right flow ">
|
||||
<meta name="generator" content="docfx 2.56.7.0">
|
||||
|
||||
<meta name="generator" content="docfx ">
|
||||
|
||||
<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">
|
||||
@@ -19,9 +19,9 @@
|
||||
<link rel="stylesheet" href="../styles/main.css">
|
||||
<meta property="docfx:navrel" content="../toc.html">
|
||||
<meta property="docfx:tocrel" content="toc.html">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -31,7 +31,7 @@
|
||||
<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>
|
||||
@@ -46,25 +46,25 @@
|
||||
|
||||
<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>
|
||||
@@ -72,8 +72,8 @@
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
<div role="main" class="hide-when-search">
|
||||
|
||||
|
||||
|
||||
<div class="subnav navbar navbar-default">
|
||||
<div class="container hide-when-search" id="breadcrumb">
|
||||
<ul class="breadcrumb">
|
||||
@@ -101,21 +101,22 @@
|
||||
<a href="https://tools.ietf.org/html/rfc6749#section-4.3">the resource owner password credentials grant</a> and
|
||||
<a href="https://tools.ietf.org/html/rfc6749#section-4.4">the client credentials grant</a>.</p>
|
||||
<p>While not specific to OpenIddict, choosing the best flow(s) for your application is an <strong>important prerequisite</strong>
|
||||
when implementing your own authorization server ; so here's a quick overview of the different OAuth 2.0/OpenID Connect flows:</p>
|
||||
when implementing your own authorization server ; so here's a quick overview of the different OAuth 2.0/OpenID Connect flows:</p>
|
||||
<hr>
|
||||
<h2 id="non-interactive-flows">Non-interactive flows</h2>
|
||||
<h3 id="resource-owner-password-credentials-flow-not-recommended-for-new-applications">Resource owner password credentials flow (not recommended for new applications)</h3>
|
||||
<p>Directly inspired by <a href="https://en.wikipedia.org/wiki/Basic_access_authentication">basic authentication</a>, the resource owner password credentials grant
|
||||
(abbreviated <em>ROPC</em>) is conceptually <strong>the simplest OAuth 2.0 flow</strong>: the client application asks the user his username/password, sends a token request
|
||||
to the authorization server with the user credentials (and depending on the client authentication policy defined by the authorization server,
|
||||
its own client credentials) and gets back an access token it can use to retrieve the user's resources.</p>
|
||||
its own client credentials) and gets back an access token it can use to retrieve the user's resources.</p>
|
||||
<p><img src="choosing-the-right-flow/resource-owner-password-flow.png" alt="Resource owner password credentials flow"></p>
|
||||
<pre><code class="lang-http">POST /connect/token HTTP/1.1
|
||||
Host: server.example.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
grant_type=password&username=johndoe&password=A3ddj3w
|
||||
</code></pre><pre><code class="lang-http">HTTP/1.1 200 OK
|
||||
</code></pre>
|
||||
<pre><code class="lang-http">HTTP/1.1 200 OK
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
Cache-Control: no-store
|
||||
Pragma: no-cache
|
||||
@@ -125,16 +126,21 @@ Pragma: no-cache
|
||||
"token_type":"bearer",
|
||||
"expires_in":3600
|
||||
}
|
||||
</code></pre><div class="CAUTION"><h5>Caution</h5><p>This flow is <strong>not recommended by the OAuth 2.0 specification</strong> as it's the only grant type where <strong>the user password is directly exposed to the client application</strong>,
|
||||
which breaks the principle of least privilege and <strong>makes it unsuitable for third-party client applications that can't be fully trusted by the authorization server</strong>.</p>
|
||||
<p>While popular and trivial to implement (as it doesn't involve any redirection or consent form and unlike interactive flows, doesn't require implementing
|
||||
cross-site request forgery (XSRF) countermeasures to prevent session fixation attacks), <strong>its use in new applications is not recommended</strong>. Instead,
|
||||
users are encouraged to use the authorization code flow, that doesn't expose passwords to client applications and is not limited to password authentication.</p>
|
||||
</code></pre>
|
||||
<div class="CAUTION">
|
||||
<h5>Caution</h5>
|
||||
<p>This flow is <strong>not recommended by the OAuth 2.0 specification</strong> as it's the only grant type where <strong>the user password is directly exposed to the client application</strong>,
|
||||
which breaks the principle of least privilege and <strong>makes it unsuitable for third-party client applications that can't be fully trusted by the authorization server</strong>.</p>
|
||||
</div>
|
||||
<blockquote>
|
||||
<p>While popular and trivial to implement (as it doesn't involve any redirection or consent form and unlike interactive flows, doesn't require implementing
|
||||
cross-site request forgery (XSRF) countermeasures to prevent session fixation attacks), <strong>its use in new applications is not recommended</strong>. Instead,
|
||||
users are encouraged to use the authorization code flow, that doesn't expose passwords to client applications and is not limited to password authentication.</p>
|
||||
</blockquote>
|
||||
<!-- more -->
|
||||
<hr>
|
||||
<h3 id="client-credentials-grant-recommended-for-machine-to-machine-communication">Client credentials grant (recommended for machine-to-machine communication)</h3>
|
||||
<p>The client credentials grant is almost identical to the resource owner password credentials grant, except it's been specifically designed for <strong>client-to-server scenarios</strong>
|
||||
<p>The client credentials grant is almost identical to the resource owner password credentials grant, except it's been specifically designed for <strong>client-to-server scenarios</strong>
|
||||
(no user is involved in this flow): the client application sends a token request containing its credentials and gets back an access token it can use to query its own resources.</p>
|
||||
<p><img src="choosing-the-right-flow/client-credentials-flow.png" alt="Client credentials flow"></p>
|
||||
<pre><code class="lang-http">POST /connect/token HTTP/1.1
|
||||
@@ -142,7 +148,8 @@ Host: server.example.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
grant_type=client_credentials&client_id=s6BhdRkqt3&client_secret=gX1fBat3bV
|
||||
</code></pre><pre><code class="lang-http">HTTP/1.1 200 OK
|
||||
</code></pre>
|
||||
<pre><code class="lang-http">HTTP/1.1 200 OK
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
Cache-Control: no-store
|
||||
Pragma: no-cache
|
||||
@@ -152,15 +159,18 @@ Pragma: no-cache
|
||||
"token_type":"bearer",
|
||||
"expires_in":3600
|
||||
}
|
||||
</code></pre><div class="NOTE"><h5>Note</h5><p>Unlike the resource owner password credentials grant, <strong>client authentication is not optional</strong> when using the client credentials grant and
|
||||
</code></pre>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>Unlike the resource owner password credentials grant, <strong>client authentication is not optional</strong> when using the client credentials grant and
|
||||
<strong>OpenIddict will always reject unauthenticated token requests</strong>, <a href="https://tools.ietf.org/html/rfc6749#section-4.4.2">as required by the OAuth 2.0 specification</a>.</p>
|
||||
<p>This means that <strong>you CAN'T use the client credentials grant with public applications</strong> like browser,
|
||||
<p>This means that <strong>you CAN'T use the client credentials grant with public applications</strong> like browser,
|
||||
mobile or desktop applications, as they are not able to keep their credentials secret.</p>
|
||||
</div>
|
||||
<hr>
|
||||
<h2 id="interactive-flows">Interactive flows</h2>
|
||||
<h3 id="authorization-code-flow-recommended-for-new-applications">Authorization code flow (recommended for new applications)</h3>
|
||||
<p>While the authorization code flow is probably the most complicated flow (as it involves both <strong>user-agent redirections and backchannel communication</strong>), it's
|
||||
<p>While the authorization code flow is probably the most complicated flow (as it involves both <strong>user-agent redirections and backchannel communication</strong>), it's
|
||||
<strong>the recommended flow for any scenario involving end users, whether they log in using a password, a PIN, a smart card or even an external provider</strong>.
|
||||
In return for its complexity, this flow has a great advantage when used in server-side applications: the <code>access_token</code> cannot be intercepted by the user agent.</p>
|
||||
<p>There are basically 2 steps in the authorization code flow: the authorization request/response and the token request/response.</p>
|
||||
@@ -171,30 +181,39 @@ In return for its complexity, this flow has a great advantage when used in serve
|
||||
<p>In this flow, the client application always initiates the authentication process by generating an authorization request including
|
||||
the mandatory <code>response_type=code</code> parameter, its <code>client_id</code>, its <code>redirect_uri</code> and optionally, a <code>scope</code> and a <code>state</code> parameter
|
||||
<a href="https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest">that allows flowing custom data and helps mitigate XSRF attacks</a>.</p>
|
||||
<div class="NOTE"><h5>Note</h5><p>In most cases, the client application will simply return a 302 response with a <code>Location</code> header to redirect the user agent to the authorization endpoint,
|
||||
but depending on the OpenID Connect client you're using, POST requests might also be supported to allow you to send large authorization requests.
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>In most cases, the client application will simply return a 302 response with a <code>Location</code> header to redirect the user agent to the authorization endpoint,
|
||||
but depending on the OpenID Connect client you're using, POST requests might also be supported to allow you to send large authorization requests.
|
||||
This feature <a href="https://github.com/aspnet/Security/pull/392">is usually implemented using an auto-post HTML form</a>.</p>
|
||||
</div>
|
||||
<pre><code class="lang-http">HTTP/1.1 302 Found
|
||||
Location: https://server.example.com/authorize?response_type=code&client_id=s6BhdRkqt3&state=af0ifjsldkj&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
|
||||
</code></pre><pre><code class="lang-http">GET /connect/authorize?response_type=code&client_id=s6BhdRkqt3&state=af0ifjsldkj&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
|
||||
</code></pre>
|
||||
<pre><code class="lang-http">GET /connect/authorize?response_type=code&client_id=s6BhdRkqt3&state=af0ifjsldkj&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
|
||||
Host: server.example.com
|
||||
</code></pre><p>The way the identity provider handles the authorization request is implementation-specific but in most cases, a consent form
|
||||
</code></pre>
|
||||
<p>The way the identity provider handles the authorization request is implementation-specific but in most cases, a consent form
|
||||
is displayed to ask the user if he or she agrees to share his/her personal data with the client application.</p>
|
||||
<p><img src="choosing-the-right-flow/consent-form.png" alt="Consent form"></p>
|
||||
<p>When the consent is given, the user agent is redirected back to the client application with <strong>a unique and short-lived token</strong>
|
||||
named <em>authorization code</em> that the client will be able to exchange with an access token by sending a token request.</p>
|
||||
<pre><code class="lang-http">HTTP/1.1 302 Found
|
||||
Location: https://client.example.org/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj
|
||||
</code></pre><div class="WARNING"><h5>Warning</h5><p>To prevent XSRF/session fixation attacks, <strong>the client application MUST ensure that the <code>state</code> parameter returned by the identity provider
|
||||
corresponds to the original <code>state</code></strong> and stop processing the authorization response if the two values don't match.
|
||||
</code></pre>
|
||||
<div class="WARNING">
|
||||
<h5>Warning</h5>
|
||||
<p>To prevent XSRF/session fixation attacks, <strong>the client application MUST ensure that the <code>state</code> parameter returned by the identity provider
|
||||
corresponds to the original <code>state</code></strong> and stop processing the authorization response if the two values don't match.
|
||||
<a href="https://tools.ietf.org/html/rfc6749#section-10.12">This is usually done by generating a non-guessable string and a corresponding correlation cookie</a>.</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li><strong>Step 2: the token request</strong></li>
|
||||
</ul>
|
||||
<p>When the client application gets back an authorization code, it must immediately reedem it for an access token by sending a <code>grant_type=authorization_code</code> token request.</p>
|
||||
<div class="NOTE"><h5>Note</h5><p>To help the identity provider <a href="https://tools.ietf.org/html/rfc6819#section-4.4.1.7">mitigate counterfeit clients attacks</a>, the original <code>redirect_uri</code> must also be sent.</p>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>To help the identity provider <a href="https://tools.ietf.org/html/rfc6819#section-4.4.1.7">mitigate counterfeit clients attacks</a>, the original <code>redirect_uri</code> must also be sent.</p>
|
||||
<p>If the client application is a confidential application (i.e an application that has been assigned client credentials), authentication is required.</p>
|
||||
</div>
|
||||
<pre><code class="lang-http">POST /connect/token HTTP/1.1
|
||||
@@ -202,7 +221,8 @@ Host: server.example.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb&client_id=s6BhdRkqt3&client_secret=gX1fBat3bV&scope=openid
|
||||
</code></pre><pre><code class="lang-http">HTTP/1.1 200 OK
|
||||
</code></pre>
|
||||
<pre><code class="lang-http">HTTP/1.1 200 OK
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
Cache-Control: no-store
|
||||
Pragma: no-cache
|
||||
@@ -212,24 +232,33 @@ Pragma: no-cache
|
||||
"token_type":"bearer",
|
||||
"expires_in":3600
|
||||
}
|
||||
</code></pre><div class="NOTE"><h5>Note</h5><p>To increase security, additional parameters such as <code>code_challenge</code> and <code>code_challenge_method</code> can be specified to bind the authorization code
|
||||
</code></pre>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>To increase security, additional parameters such as <code>code_challenge</code> and <code>code_challenge_method</code> can be specified to bind the authorization code
|
||||
that will be returned by the authorization endpoint to the original authorization request. This mechanism is known as
|
||||
<a href="../configuration/proof-key-for-code-exchange.html">Proof Key for Code Exchange</a> and is fully supported by OpenIddict. </p>
|
||||
<a href="../configuration/proof-key-for-code-exchange.html">Proof Key for Code Exchange</a> and is fully supported by OpenIddict.</p>
|
||||
</div>
|
||||
<hr>
|
||||
<h3 id="implicit-flow-not-recommended-for-new-applications">Implicit flow (not recommended for new applications)</h3>
|
||||
<p>The implicit flow is similar to the authorization code flow, <strong>except there's no token request/response step</strong>: the access token is directly returned
|
||||
<p>The implicit flow is similar to the authorization code flow, <strong>except there's no token request/response step</strong>: the access token is directly returned
|
||||
to the client application as part of the authorization response in the URI fragment (or in the request form when using <code>response_mode=form_post</code>).</p>
|
||||
<p><img src="choosing-the-right-flow/implicit-flow.png" alt="Implicit flow"></p>
|
||||
<pre><code class="lang-http">GET /connect/authorize?response_type=token&client_id=s6BhdRkqt3&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb&scope=openid&state=af0ifjsldkj&nonce=n-0S6_WzA2Mj HTTP/1.1
|
||||
Host: server.example.com
|
||||
</code></pre><pre><code class="lang-http">HTTP/1.1 302 Found
|
||||
</code></pre>
|
||||
<pre><code class="lang-http">HTTP/1.1 302 Found
|
||||
Location: https://client.example.org/cb#access_token=SlAV32hkKG&token_type=bearer&expires_in=3600&state=af0ifjsldkj
|
||||
</code></pre><div class="CAUTION"><h5>Caution</h5><p>Initially designed for browser applications, this flow is inherently less secure than the authorization code flow and doesn't support
|
||||
</code></pre>
|
||||
<div class="CAUTION">
|
||||
<h5>Caution</h5>
|
||||
<p>Initially designed for browser applications, this flow is inherently less secure than the authorization code flow and doesn't support
|
||||
<a href="https://tools.ietf.org/html/rfc7636">Proof Key for Code Exchange</a>. As such, using it in new applications is not recommended.</p>
|
||||
</div>
|
||||
<div class="WARNING"><h5>Warning</h5><p>To prevent XSRF/session fixation attacks, <strong>the client application MUST ensure that the <code>state</code> parameter returned by the identity provider
|
||||
corresponds to the original <code>state</code></strong> and stop processing the authorization response if the two values don't match.
|
||||
<div class="WARNING">
|
||||
<h5>Warning</h5>
|
||||
<p>To prevent XSRF/session fixation attacks, <strong>the client application MUST ensure that the <code>state</code> parameter returned by the identity provider
|
||||
corresponds to the original <code>state</code></strong> and stop processing the authorization response if the two values don't match.
|
||||
<a href="https://tools.ietf.org/html/rfc6749#section-10.12">This is usually done by generating a non-guessable string and a corresponding value stored in the local storage</a>.</p>
|
||||
<p>When using the implicit flow, <strong>the client application MUST also ensure that the access token was not issued
|
||||
to another application to prevent <a href="https://stackoverflow.com/a/17439317/542757">confused deputy attacks</a>.</strong>
|
||||
@@ -242,16 +271,16 @@ of the JWT identity token, that must correspond or contain the <code>client_id</
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
|
@@ -2,15 +2,15 @@
|
||||
<!--[if IE]><![endif]-->
|
||||
<html>
|
||||
|
||||
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Contributing a new Web provider </title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta name="title" content="Contributing a new Web provider ">
|
||||
<meta name="generator" content="docfx 2.56.7.0">
|
||||
|
||||
<meta name="generator" content="docfx ">
|
||||
|
||||
<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">
|
||||
@@ -19,9 +19,9 @@
|
||||
<link rel="stylesheet" href="../styles/main.css">
|
||||
<meta property="docfx:navrel" content="../toc.html">
|
||||
<meta property="docfx:tocrel" content="toc.html">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -31,7 +31,7 @@
|
||||
<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>
|
||||
@@ -46,25 +46,25 @@
|
||||
|
||||
<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>
|
||||
@@ -72,8 +72,8 @@
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
<div role="main" class="hide-when-search">
|
||||
|
||||
|
||||
|
||||
<div class="subnav navbar navbar-default">
|
||||
<div class="container hide-when-search" id="breadcrumb">
|
||||
<ul class="breadcrumb">
|
||||
@@ -110,7 +110,7 @@ and OWIN/ASP.NET 4.x applications, but also in Windows and Linux desktop applica
|
||||
with the configuration needed to properly generate them. By eliminating all the plumbing code, the OpenIddict web providers are much easier to maintain and update.</p>
|
||||
</li>
|
||||
<li><p>To guarantee interoperability and make the best security choices, <strong>the OpenIddict client heavily relies on server configuration metadata</strong>, which differs from
|
||||
the approach used by the ASP.NET Core OAuth 2.0 base handler, that doesn't support the OpenID Connect discovery and OAuth 2.0 authorization server metadata specifications.</p>
|
||||
the approach used by the ASP.NET Core OAuth 2.0 base handler, that doesn't support the OpenID Connect discovery and OAuth 2.0 authorization server metadata specifications.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Due to these differences, <strong>contributing a new provider to the OpenIddict stack is quite different from adding an aspnet-contrib provider</strong>:</p>
|
||||
@@ -118,14 +118,17 @@ the approach used by the ASP.NET Core OAuth 2.0 base handler, that doesn't s
|
||||
<p>To add a new OpenIddict web provider, <strong>the first step is to add a new <code><Provider></code> node</strong> to the <a href="https://github.com/openiddict/openiddict-core/blob/dev/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml">OpenIddictClientWebIntegrationProviders.xml</a> file. For instance:</p>
|
||||
<pre><code class="lang-xml"><Provider Name="Zendesk" Documentation="https://developer.zendesk.com/documentation/live-chat/getting-started/auth/">
|
||||
</Provider>
|
||||
</code></pre><p>If available, a link to the official documentation MUST be added. If multiple languages are available, the following order SHOULD be used:</p>
|
||||
</code></pre>
|
||||
<p>If available, a link to the official documentation MUST be added. If multiple languages are available, the following order SHOULD be used:</p>
|
||||
<ul>
|
||||
<li>English</li>
|
||||
<li>French</li>
|
||||
<li>Spanish</li>
|
||||
<li>Any other language</li>
|
||||
</ul>
|
||||
<div class="WARNING"><h5>Warning</h5><p>The added provider MUST be placed in the XML file such that the alphabetical order is respected.</p>
|
||||
<div class="WARNING">
|
||||
<h5>Warning</h5>
|
||||
<p>The added provider MUST be placed in the XML file such that the alphabetical order is respected.</p>
|
||||
</div>
|
||||
<h2 id="add-an-environment-node-per-supported-environment">Add an <code><Environment></code> node per supported environment</h2>
|
||||
<p><strong>The second step is to determine whether the service offers multiple environments</strong> (e.g Production, Testing or Development).</p>
|
||||
@@ -137,18 +140,22 @@ the approach used by the ASP.NET Core OAuth 2.0 base handler, that doesn't s
|
||||
|
||||
<Environment Name="Development" />
|
||||
</Provider>
|
||||
</code></pre><div class="WARNING"><h5>Warning</h5><p>When specifying multiple environments, the production environment MUST always appear first.</p>
|
||||
</code></pre>
|
||||
<div class="WARNING">
|
||||
<h5>Warning</h5>
|
||||
<p>When specifying multiple environments, the production environment MUST always appear first.</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li>If the provider doesn't support multiple environment, a single <code><Environment></code> MUST be added (the <code>Name</code> attribute SHOULD be omitted):</li>
|
||||
<li>If the provider doesn't support multiple environment, a single <code><Environment></code> MUST be added (the <code>Name</code> attribute SHOULD be omitted):</li>
|
||||
</ul>
|
||||
<pre><code class="lang-xml"><Provider Name="Google">
|
||||
<Environment />
|
||||
</Provider>
|
||||
</code></pre><h2 id="add-the-appropriate-configuration-for-each-environment">Add the appropriate configuration for each environment</h2>
|
||||
</code></pre>
|
||||
<h2 id="add-the-appropriate-configuration-for-each-environment">Add the appropriate configuration for each environment</h2>
|
||||
<p><strong>The third step is the most complicated one: adding the appropriate configuration for each of the added environments</strong>.</p>
|
||||
<p>For that, you MUST first determine whether the environment supports OpenID Connect discovery or OAuth 2.0 authorization server metadata.
|
||||
In some cases, this information will be mentioned in the official documentation, but it's not always true. By convention, the server metadata
|
||||
In some cases, this information will be mentioned in the official documentation, but it's not always true. By convention, the server metadata
|
||||
is typically served from <code>https://provider/.well-known/openid-configuration</code>: if you get a valid JSON document from this endpoint, the server
|
||||
supports OpenID Connect/OAuth 2.0 server metadata.</p>
|
||||
<ul>
|
||||
@@ -159,8 +166,9 @@ so the correct issuer to use is <code>https://accounts.google.com/</code>:</li>
|
||||
<pre><code class="lang-xml"><Provider Name="Google">
|
||||
<Environment Issuer="https://accounts.google.com/" />
|
||||
</Provider>
|
||||
</code></pre><ul>
|
||||
<li>If the server doesn't support OpenID Connect/OAuth 2.0 server metadata, you MUST add an <code>Issuer</code> attribute (corresponding to either
|
||||
</code></pre>
|
||||
<ul>
|
||||
<li>If the server doesn't support OpenID Connect/OAuth 2.0 server metadata, you MUST add an <code>Issuer</code> attribute (corresponding to either
|
||||
the value given in the documentation or the base address of the server) <strong>and</strong> a <code><Configuration></code> node with the static configuration needed by
|
||||
the OpenIddict client to communicate with the remote authorization server. For instance:</li>
|
||||
</ul>
|
||||
@@ -174,7 +182,10 @@ the OpenIddict client to communicate with the remote authorization server. For i
|
||||
</Configuration>
|
||||
</Environment>
|
||||
</Provider>
|
||||
</code></pre><div class="NOTE"><h5>Note</h5><p>If the provider doesn't support <code>grant_type=refresh_token</code> and only supports the authorization code flow
|
||||
</code></pre>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>If the provider doesn't support <code>grant_type=refresh_token</code> and only supports the authorization code flow
|
||||
(typically with non-expiring access tokens), the <code><GrantType></code> nodes MUST be removed for clarity,
|
||||
as the authorization code flow is always considered supported by default if no <code><GrantType></code> is present:</p>
|
||||
<pre><code class="lang-xml"><Provider Name="Reddit">
|
||||
@@ -184,8 +195,11 @@ as the authorization code flow is always considered supported by default if no <
|
||||
UserinfoEndpoint="https://oauth.reddit.com/api/v1/me" />
|
||||
</Environment>
|
||||
</Provider>
|
||||
</code></pre></div>
|
||||
<div class="CAUTION"><h5>Caution</h5><p>If the provider doesn't support server metadata but is known to support Proof Key for Code Exchange (PKCE), a <code><CodeChallengeMethod></code> node MUST
|
||||
</code></pre>
|
||||
</div>
|
||||
<div class="CAUTION">
|
||||
<h5>Caution</h5>
|
||||
<p>If the provider doesn't support server metadata but is known to support Proof Key for Code Exchange (PKCE), a <code><CodeChallengeMethod></code> node MUST
|
||||
be added under <code><Configuration></code> to ensure the OpenIddict client will send appropriate <code>code_challenge</code>/<code>code_challenge_method</code> parameters:</p>
|
||||
<pre><code class="lang-xml"><Provider Name="Fitbit">
|
||||
<Environment Issuer="https://www.fitbit.com/">
|
||||
@@ -196,8 +210,11 @@ be added under <code><Configuration></code> to ensure the OpenIddict clien
|
||||
</Configuration>
|
||||
</Environment>
|
||||
</Provider>
|
||||
</code></pre></div>
|
||||
<div class="NOTE"><h5>Note</h5><p>Some providers use a multitenant configuration that relies on a subdomain, a custom domain or a virtual path to discriminate tenant instances.
|
||||
</code></pre>
|
||||
</div>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>Some providers use a multitenant configuration that relies on a subdomain, a custom domain or a virtual path to discriminate tenant instances.
|
||||
If the provider you want to support requires adding a dynamic part in one of its URIs, a <code><Setting></code> node MUST be added under <code><Provider></code> to
|
||||
store the tenant name. Once added, the URIs can include a placeholder of the same name:</p>
|
||||
<pre><code class="lang-xml"><Provider Name="Zendesk">
|
||||
@@ -216,7 +233,8 @@ store the tenant name. Once added, the URIs can include a placeholder of the sam
|
||||
<Setting PropertyName="Tenant" ParameterName="tenant" Type="String" Required="true"
|
||||
Description="The tenant used to identify the Zendesk instance" />
|
||||
</Provider>
|
||||
</code></pre></div>
|
||||
</code></pre>
|
||||
</div>
|
||||
<h2 id="test-the-generated-provider">Test the generated provider</h2>
|
||||
<p>If the targeted service is fully standard-compliant, no additional configuration should be required at this point.
|
||||
To confirm it, build the solution and add the new provider to the <code>OpenIddict.Sandbox.AspNetCore.Client</code> sandbox:</p>
|
||||
@@ -232,7 +250,8 @@ options.UseWebProviders()
|
||||
options.SetClientSecret("VcohOgBp-6yQCurngo4GAyKeZh0D6SUCCSjJgEo1uRzJarjIUS");
|
||||
options.SetRedirectUri("callback/login/[provider name]");
|
||||
});
|
||||
</code></pre><ul>
|
||||
</code></pre>
|
||||
<ul>
|
||||
<li>Update <code>AuthenticationController.cs</code> to allow triggering challenges pointing to the new provider:</li>
|
||||
</ul>
|
||||
<pre><code class="lang-csharp">// Note: OpenIddict always validates the specified provider name when handling the challenge operation,
|
||||
@@ -243,21 +262,25 @@ if (!string.Equals(provider, "Local", StringComparison.Ordinal) &&
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
</code></pre><ul>
|
||||
</code></pre>
|
||||
<ul>
|
||||
<li>Update <code>Index.cshtml</code> under <code>Views\Home</code> to include a login button for the new provider:</li>
|
||||
</ul>
|
||||
<pre><code class="lang-html"><button class="btn btn-lg btn-success" type="submit" name="provider" value="[provider name]">
|
||||
Sign in using [provider name]
|
||||
</button>
|
||||
</code></pre><div class="NOTE"><h5>Note</h5><p>Unless you agree to share your sandbox credentials with the OpenIddict developers, the changes
|
||||
made to the sandbox project don't need to be committed and included in your pull request.</p>
|
||||
</code></pre>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>Unless you agree to share your sandbox credentials with the OpenIddict developers, the changes
|
||||
made to the sandbox project don't need to be committed and included in your pull request.</p>
|
||||
</div>
|
||||
<h2 id="if-necessary-add-the-necessary-workarounds-for-the-provider-to-work-correctly">If necessary, add the necessary workarounds for the provider to work correctly</h2>
|
||||
<p>If an error occurs during the authentication process, the provider MAY require one or multiple workarounds for the integration to work correctly:</p>
|
||||
<ul>
|
||||
<li>The provider MAY require sending the client credentials as part of the <code>Authorization</code> header using basic authentication (i.e <code>client_secret_basic</code>).
|
||||
Providers that implement OpenID Connect discovery or OAuth 2.0 authorization server metadata will typically return the client authentication methods they support.
|
||||
If the provider doesn't expose its metadata, the supported methods MUST be added manually to the static configuration using one or multiple <code><TokenEndpointAuthMethod></code>:</li>
|
||||
If the provider doesn't expose its metadata, the supported methods MUST be added manually to the static configuration using one or multiple <code><TokenEndpointAuthMethod></code>:</li>
|
||||
</ul>
|
||||
<pre><code class="lang-xml"><Provider Name="Twitter">
|
||||
<Environment Issuer="https://twitter.com/">
|
||||
@@ -270,7 +293,8 @@ If the provider doesn't expose its metadata, the supported methods MUST be a
|
||||
</Configuration>
|
||||
</Environment>
|
||||
</Provider>
|
||||
</code></pre><ul>
|
||||
</code></pre>
|
||||
<ul>
|
||||
<li>The provider MAY require sending one or multiple default or required scopes. If so, the default/required scopes MUST be added to the <code><Environment></code> node:</li>
|
||||
</ul>
|
||||
<pre><code class="lang-xml"><Provider Name="Twitter" Documentation="https://developer.twitter.com/en/docs/authentication/oauth-2-0/authorization-code">
|
||||
@@ -293,9 +317,10 @@ If the provider doesn't expose its metadata, the supported methods MUST be a
|
||||
<Scope Name="users.read" Default="true" Required="true" />
|
||||
</Environment>
|
||||
</Provider>
|
||||
</code></pre><ul>
|
||||
</code></pre>
|
||||
<ul>
|
||||
<li>The provider MAY require sending the scopes using a different separator than the standard one. While the OAuth 2.0 specification requires using a space
|
||||
to separate multiple scopes, some providers require using a different separator (typically, a comma). If the provider you're adding requires such a hack,
|
||||
to separate multiple scopes, some providers require using a different separator (typically, a comma). If the provider you're adding requires such a hack,
|
||||
update the <code>FormatNonStandardScopeParameter</code> event handler present in
|
||||
<a href="https://github.com/openiddict/openiddict-core/blob/dev/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs">OpenIddictClientWebIntegrationHandlers.cs</a> to use the correct separator required by the provider.</li>
|
||||
</ul>
|
||||
@@ -336,12 +361,15 @@ public class FormatNonStandardScopeParameter : IOpenIddictClientHandler<Proce
|
||||
return default;
|
||||
}
|
||||
}
|
||||
</code></pre><div class="NOTE"><h5>Note</h5><p>If the provider still doesn't work, it's unfortunately very likely more complex workarounds will be required.
|
||||
If you're not familiar with the OpenIddict events model, open a ticket in the
|
||||
</code></pre>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>If the provider still doesn't work, it's unfortunately very likely more complex workarounds will be required.
|
||||
If you're not familiar with the OpenIddict events model, open a ticket in the
|
||||
<a href="https://github.com/openiddict/openiddict-core/issues"><code>openiddict-core</code></a> repository to get help.</p>
|
||||
</div>
|
||||
<h2 id="send-a-pull-request-against-the-openiddict-core-repository">Send a pull request against the <code>openiddict-core</code> repository</h2>
|
||||
<p>Once you've been able to confirm that your provider works correctly, all you need to do is send a PR so that it can be added to the
|
||||
<p>Once you've been able to confirm that your provider works correctly, all you need to do is send a PR so that it can be added to the
|
||||
<a href="https://github.com/openiddict/openiddict-core/issues"><code>openiddict-repo</code></a> and ship with the already supported providers as part of the next update.</p>
|
||||
</article>
|
||||
|
||||
@@ -349,16 +377,16 @@ If you're not familiar with the OpenIddict events model, open a ticket in th
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
|
@@ -2,15 +2,15 @@
|
||||
<!--[if IE]><![endif]-->
|
||||
<html>
|
||||
|
||||
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Getting started </title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta name="title" content="Getting started ">
|
||||
<meta name="generator" content="docfx 2.56.7.0">
|
||||
|
||||
<meta name="generator" content="docfx ">
|
||||
|
||||
<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">
|
||||
@@ -19,9 +19,9 @@
|
||||
<link rel="stylesheet" href="../styles/main.css">
|
||||
<meta property="docfx:navrel" content="../toc.html">
|
||||
<meta property="docfx:tocrel" content="toc.html">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -31,7 +31,7 @@
|
||||
<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>
|
||||
@@ -46,25 +46,25 @@
|
||||
|
||||
<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>
|
||||
@@ -72,8 +72,8 @@
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
<div role="main" class="hide-when-search">
|
||||
|
||||
|
||||
|
||||
<div class="subnav navbar navbar-default">
|
||||
<div class="container hide-when-search" id="breadcrumb">
|
||||
<ul class="breadcrumb">
|
||||
@@ -94,19 +94,20 @@
|
||||
<h1 id="getting-started">Getting started</h1>
|
||||
|
||||
<p><strong>To implement a custom OpenID Connect server using OpenIddict, the simplest option is to clone one of the official samples</strong> from the <a href="https://github.com/openiddict/openiddict-samples">openiddict-samples repository</a>.</p>
|
||||
<p>If you don't want to start from one of the recommended samples, you'll need to:</p>
|
||||
<p>If you don't want to start from one of the recommended samples, you'll need to:</p>
|
||||
<ul>
|
||||
<li><p><strong>Install the <a href="https://www.microsoft.com/net/download">.NET Core 3.1 (or later) tooling</a></strong>.</p>
|
||||
</li>
|
||||
<li><p><strong>Have an existing project or create a new one</strong>: when creating a new project using Visual Studio's default ASP.NET Core template,
|
||||
<li><p><strong>Have an existing project or create a new one</strong>: when creating a new project using Visual Studio's default ASP.NET Core template,
|
||||
using <strong>individual user accounts authentication</strong> is strongly recommended as it automatically includes the default ASP.NET Core Identity UI, based on Razor Pages.</p>
|
||||
</li>
|
||||
<li><p><strong>Update your <code>.csproj</code> file</strong> to reference the latest <code>OpenIddict</code> packages:</p>
|
||||
<pre><code class="lang-xml"><PackageReference Include="OpenIddict.AspNetCore" Version="4.2.0" />
|
||||
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="4.2.0" />
|
||||
</code></pre></li>
|
||||
<pre><code class="lang-xml"><PackageReference Include="OpenIddict.AspNetCore" Version="4.3.0" />
|
||||
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="4.3.0" />
|
||||
</code></pre>
|
||||
</li>
|
||||
<li><p><strong>Configure the OpenIddict core, server and validation services</strong> in <code>Startup.ConfigureServices</code>.
|
||||
Here's an example for the client credentials grant, used in machine-to-machine scenarios:</p>
|
||||
Here's an example for the client credentials grant, used in machine-to-machine scenarios:</p>
|
||||
<pre><code class="lang-csharp">public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllersWithViews();
|
||||
@@ -164,7 +165,8 @@ Here's an example for the client credentials grant, used in machine-to-machi
|
||||
// Note: in a real world application, this step should be part of a setup script.
|
||||
services.AddHostedService<Worker>();
|
||||
}
|
||||
</code></pre></li>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li><p><strong>Make sure the ASP.NET Core authentication middleware is correctly registered at the right place</strong>:</p>
|
||||
<pre><code class="lang-csharp">public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
@@ -181,7 +183,8 @@ Here's an example for the client credentials grant, used in machine-to-machi
|
||||
options.MapDefaultControllerRoute();
|
||||
});
|
||||
}
|
||||
</code></pre></li>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li><p><strong>Update your Entity Framework Core context registration to register the OpenIddict entities</strong>:</p>
|
||||
<pre><code class="lang-csharp">services.AddDbContext<ApplicationDbContext>(options =>
|
||||
{
|
||||
@@ -192,13 +195,16 @@ Here's an example for the client credentials grant, used in machine-to-machi
|
||||
// Note: use the generic overload if you need to replace the default OpenIddict entities.
|
||||
options.UseOpenIddict();
|
||||
});
|
||||
</code></pre><div class="NOTE"><h5>Note</h5><p>By default, the OpenIddict Entity Framework Core integration uses <code>string</code> as the default type for primary keys.
|
||||
</code></pre>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>By default, the OpenIddict Entity Framework Core integration uses <code>string</code> as the default type for primary keys.
|
||||
To use a different type, read <a href="../integrations/entity-framework-core.html#use-a-custom-primary-key-type">Entity Framework Core integration : Use a custom primary key type</a>.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li><p><strong>Create your own authorization controller:</strong>
|
||||
Implementing a custom authorization controller is required to allow OpenIddict to create tokens based on the identities and claims you provide.
|
||||
Here's an example for the client credentials grant:</p>
|
||||
Here's an example for the client credentials grant:</p>
|
||||
<pre><code class="lang-csharp">public class AuthorizationController : Controller
|
||||
{
|
||||
private readonly IOpenIddictApplicationManager _applicationManager;
|
||||
@@ -216,7 +222,7 @@ Here's an example for the client credentials grant:</p>
|
||||
}
|
||||
|
||||
// Note: the client credentials are automatically validated by OpenIddict:
|
||||
// if client_id or client_secret are invalid, this action won't be invoked.
|
||||
// if client_id or client_secret are invalid, this action won't be invoked.
|
||||
|
||||
var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
|
||||
throw new InvalidOperationException("The application cannot be found.");
|
||||
@@ -243,7 +249,8 @@ Here's an example for the client credentials grant:</p>
|
||||
return SignIn(new ClaimsPrincipal(identity), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
|
||||
}
|
||||
}
|
||||
</code></pre></li>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li><p><strong>Register your client application</strong> (e.g from an <code>IHostedService</code> implementation):</p>
|
||||
<pre><code class="lang-csharp">public class Worker : IHostedService
|
||||
{
|
||||
@@ -279,25 +286,27 @@ Here's an example for the client credentials grant:</p>
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
</code></pre><p>Before running the application, make sure the database is updated with OpenIddict tables by running <code>Add-Migration</code> and <code>Update-Database</code>.</p>
|
||||
|
||||
</code></pre>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Before running the application, make sure the database is updated with OpenIddict tables by running <code>Add-Migration</code> and <code>Update-Database</code>.</p>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
|
@@ -2,15 +2,15 @@
|
||||
<!--[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>
|
||||
<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">
|
||||
|
||||
<meta name="title" content="What's OpenIddict? ">
|
||||
<meta name="generator" content="docfx ">
|
||||
|
||||
<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">
|
||||
@@ -19,9 +19,9 @@
|
||||
<link rel="stylesheet" href="../styles/main.css">
|
||||
<meta property="docfx:navrel" content="../toc.html">
|
||||
<meta property="docfx:tocrel" content="toc.html">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -31,7 +31,7 @@
|
||||
<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>
|
||||
@@ -46,25 +46,25 @@
|
||||
|
||||
<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>
|
||||
@@ -72,8 +72,8 @@
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
<div role="main" class="hide-when-search">
|
||||
|
||||
|
||||
|
||||
<div class="subnav navbar navbar-default">
|
||||
<div class="container hide-when-search" id="breadcrumb">
|
||||
<ul class="breadcrumb">
|
||||
@@ -91,7 +91,7 @@
|
||||
</div>
|
||||
|
||||
<article class="content wrap" id="_content" data-uid="">
|
||||
<h2 id="whats-openiddict">What's OpenIddict?</h2>
|
||||
<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>
|
||||
@@ -137,7 +137,8 @@ OpenIddict will automatically reject the request before it reaches user-defined
|
||||
options.UseAspNetCore()
|
||||
.EnableAuthorizationEndpointPassthrough();
|
||||
});
|
||||
</code></pre><pre><code class="lang-csharp">app.MapGet("/authorize", async (HttpContext context) =>
|
||||
</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.
|
||||
@@ -156,11 +157,12 @@ OpenIddict will automatically reject the request before it reaches user-defined
|
||||
|
||||
return Results.SignIn(new ClaimsPrincipal(identity), properties: null, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
|
||||
});
|
||||
</code></pre><h3 id="events-model">Events model</h3>
|
||||
</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.
|
||||
/// Contains the logic responsible of rejecting authorization requests that don't specify a valid prompt parameter.
|
||||
/// </summary>
|
||||
public class ValidatePromptParameter : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
|
||||
{
|
||||
@@ -200,7 +202,8 @@ public class ValidatePromptParameter : IOpenIddictServerHandler<ValidateAutho
|
||||
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>
|
||||
</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 =>
|
||||
{
|
||||
@@ -213,22 +216,23 @@ public class ValidatePromptParameter : IOpenIddictServerHandler<ValidateAutho
|
||||
return default;
|
||||
}));
|
||||
});
|
||||
</code></pre></article>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
|
@@ -2,15 +2,15 @@
|
||||
<!--[if IE]><![endif]-->
|
||||
<html>
|
||||
|
||||
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Migrate to OpenIddict 3.0 </title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta name="title" content="Migrate to OpenIddict 3.0 ">
|
||||
<meta name="generator" content="docfx 2.56.7.0">
|
||||
|
||||
<meta name="generator" content="docfx ">
|
||||
|
||||
<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">
|
||||
@@ -19,9 +19,9 @@
|
||||
<link rel="stylesheet" href="../../styles/main.css">
|
||||
<meta property="docfx:navrel" content="../../toc.html">
|
||||
<meta property="docfx:tocrel" content="../toc.html">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -31,7 +31,7 @@
|
||||
<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>
|
||||
@@ -46,25 +46,25 @@
|
||||
|
||||
<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>
|
||||
@@ -72,8 +72,8 @@
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
<div role="main" class="hide-when-search">
|
||||
|
||||
|
||||
|
||||
<div class="subnav navbar navbar-default">
|
||||
<div class="container hide-when-search" id="breadcrumb">
|
||||
<ul class="breadcrumb">
|
||||
@@ -93,9 +93,11 @@
|
||||
<article class="content wrap" id="_content" data-uid="">
|
||||
<h1 id="migrate-to-openiddict-30">Migrate to OpenIddict 3.0</h1>
|
||||
|
||||
<h2 id="whats-new">What's new?</h2>
|
||||
<h2 id="whats-new">What's new?</h2>
|
||||
<p>The announcement listing the changes introduced in this milestone can be found <a href="https://kevinchalet.com/2020/12/23/openiddict-3-0-general-availability/">here</a>.</p>
|
||||
<div class="IMPORTANT"><h5>Important</h5><p><strong>Migrating to OpenIddict 3.0 requires making changes to your database</strong>: existing properties have been reworked and new ones have been added to support the new features.</p>
|
||||
<div class="IMPORTANT">
|
||||
<h5>Important</h5>
|
||||
<p><strong>Migrating to OpenIddict 3.0 requires making changes to your database</strong>: existing properties have been reworked and new ones have been added to support the new features.</p>
|
||||
</div>
|
||||
<h2 id="update-your-packages-references">Update your packages references</h2>
|
||||
<p>For that, update your <code>.csproj</code> file to reference the <code>OpenIddict.AspNetCore</code> 3.x metapackage:</p>
|
||||
@@ -103,9 +105,10 @@
|
||||
<PackageReference Include="OpenIddict.AspNetCore" Version="3.1.1" />
|
||||
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="3.1.1" />
|
||||
</ItemGroup>
|
||||
</code></pre><h2 id="ensure-your-application-doesnt-reference-legacyunsupported-packages">Ensure your application doesn't reference legacy/unsupported packages</h2>
|
||||
</code></pre>
|
||||
<h2 id="ensure-your-application-doesnt-reference-legacyunsupported-packages">Ensure your application doesn't reference legacy/unsupported packages</h2>
|
||||
<p>As part of the AspNet.Security.OpenIdConnect.Server/OpenIddict merge, the ASOS packages and 2 OpenIddict packages have been marked as legacy
|
||||
and are no longer supported. Make sure your application (or intermediate libraries) don't reference any of these packages:</p>
|
||||
and are no longer supported. Make sure your application (or intermediate libraries) don't reference any of these packages:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -160,7 +163,9 @@ and are no longer supported. Make sure your application (or intermediate librari
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="IMPORTANT"><h5>Important</h5><p>If your application references the <code>OpenIdConnectConstants</code> class, update it to use <code>OpenIddictConstants</code> instead.</p>
|
||||
<div class="IMPORTANT">
|
||||
<h5>Important</h5>
|
||||
<p>If your application references the <code>OpenIdConnectConstants</code> class, update it to use <code>OpenIddictConstants</code> instead.</p>
|
||||
</div>
|
||||
<h2 id="update-the-references-to-the-entity-framework-coreentity-framework-6mongodb-models">Update the references to the Entity Framework Core/Entity Framework 6/MongoDB models</h2>
|
||||
<p>If your application references the <code>OpenIddictApplication</code>, <code>OpenIddictAuthorization</code>, <code>OpenIddictScope</code> or <code>OpenIddictToken</code> models,
|
||||
@@ -212,8 +217,9 @@ update these reference to use their new names:</p>
|
||||
{
|
||||
options.UseAspNetCore();
|
||||
});
|
||||
</code></pre><h2 id="enable-the-authorization-logout-and-token-endpoints-pass-through-mode">Enable the authorization, logout and token endpoints pass-through mode</h2>
|
||||
<p>Unless you're using OpenIddict's events model to handle authorization, logout and token requests, you'll need to enable
|
||||
</code></pre>
|
||||
<h2 id="enable-the-authorization-logout-and-token-endpoints-pass-through-mode">Enable the authorization, logout and token endpoints pass-through mode</h2>
|
||||
<p>Unless you're using OpenIddict's events model to handle authorization, logout and token requests, you'll need to enable
|
||||
the pass-through mode for these endpoints, so that requests can reach your authorization controller as in the previous versions:</p>
|
||||
<pre><code class="lang-csharp">services.AddOpenIddict()
|
||||
.AddServer(options =>
|
||||
@@ -223,7 +229,8 @@ the pass-through mode for these endpoints, so that requests can reach your autho
|
||||
.EnableLogoutEndpointPassthrough()
|
||||
.EnableTokenEndpointPassthrough();
|
||||
});
|
||||
</code></pre><h2 id="enable-aspnet-core-data-protection-support-to-ensure-existing-tokens-can-still-be-validated">Enable ASP.NET Core Data Protection support to ensure existing tokens can still be validated</h2>
|
||||
</code></pre>
|
||||
<h2 id="enable-aspnet-core-data-protection-support-to-ensure-existing-tokens-can-still-be-validated">Enable ASP.NET Core Data Protection support to ensure existing tokens can still be validated</h2>
|
||||
<p>For that, call <code>options.UseDataProtection()</code> in both the server and validation options:</p>
|
||||
<pre><code class="lang-csharp">services.AddOpenIddict()
|
||||
.AddServer(options =>
|
||||
@@ -234,9 +241,10 @@ the pass-through mode for these endpoints, so that requests can reach your autho
|
||||
{
|
||||
options.UseDataProtection();
|
||||
});
|
||||
</code></pre><h2 id="use-the-new-request-caching-apis-if-applicable">Use the new request caching APIs, if applicable</h2>
|
||||
</code></pre>
|
||||
<h2 id="use-the-new-request-caching-apis-if-applicable">Use the new request caching APIs, if applicable</h2>
|
||||
<p>In 3.0, the <code>OpenIddictServerBuilder.EnableRequestCaching()</code> API - that enabled request caching for both authorization and logout request -
|
||||
was replaced by 2 separate methods. If your application depends on request caching, don't forget to enable it when migrating to 3.0:</p>
|
||||
was replaced by 2 separate methods. If your application depends on request caching, don't forget to enable it when migrating to 3.0:</p>
|
||||
<pre><code class="lang-csharp">services.AddOpenIddict()
|
||||
.AddServer(options =>
|
||||
{
|
||||
@@ -244,7 +252,8 @@ was replaced by 2 separate methods. If your application depends on request cachi
|
||||
.EnableAuthorizationRequestCaching()
|
||||
.EnableLogoutRequestCaching();
|
||||
});
|
||||
</code></pre><h2 id="replace-jsonnet-by-systemtextjson">Replace JSON.NET by <code>System.Text.Json</code></h2>
|
||||
</code></pre>
|
||||
<h2 id="replace-jsonnet-by-systemtextjson">Replace JSON.NET by <code>System.Text.Json</code></h2>
|
||||
<p>If you use JSON.NET to serialize or deserialize <code>OpenIdConnectMessage</code>, <code>OpenIdConnectRequest</code> or <code>OpenIdConnectResponse</code> instances,
|
||||
consider moving to <code>System.Text.Json</code> when migrating to OpenIddict 3.0, as 3.0 no longer includes a built-in JSON.NET <code>JsonConverter</code> for their
|
||||
equivalent in 3.0 (i.e <code>OpenIddictMessage</code>, <code>OpenIddictRequest</code> and <code>OpenIddictResponse</code>).</p>
|
||||
@@ -277,7 +286,9 @@ If you have calls like <code>ticket.SetScopes()</code> or <code>ticket.SetResour
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="NOTE"><h5>Note</h5><p>In 3.0, the OpenIddict server ASP.NET Core handler supports authenticating userinfo requests. As such, if you use the pass-through mode
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>In 3.0, the OpenIddict server ASP.NET Core handler supports authenticating userinfo requests. As such, if you use the pass-through mode
|
||||
to handle userinfo requests in your own userinfo MVC action, consider using <code>OpenIddictServerAspNetCoreDefaults.AuthenticationScheme</code>
|
||||
instead of <code>OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme</code> for your userinfo endpoint to avoid validating access tokens twice.</p>
|
||||
</div>
|
||||
@@ -293,7 +304,8 @@ still work after migrating, consider using the <code>principal.HasScope()</code>
|
||||
builder.RequireAssertion(context => context.User.HasScope("api1"));
|
||||
});
|
||||
});
|
||||
</code></pre><p>Alternatively, you can use the check the presence of the private OpenIddict <code>oi_scp</code> claims that use the same format as in 2.x (i.e one claim per scope value):</p>
|
||||
</code></pre>
|
||||
<p>Alternatively, you can use the check the presence of the private OpenIddict <code>oi_scp</code> claims that use the same format as in 2.x (i.e one claim per scope value):</p>
|
||||
<pre><code class="lang-csharp">services.AddAuthorization(options =>
|
||||
{
|
||||
options.AddPolicy("MyPolicy", builder =>
|
||||
@@ -302,8 +314,11 @@ still work after migrating, consider using the <code>principal.HasScope()</code>
|
||||
builder.RequireClaim(Claims.Private.Scope, "api1");
|
||||
});
|
||||
});
|
||||
</code></pre><div class="CAUTION"><h5>Caution</h5><p>These 2 options only work with the OpenIddict validation handler as the <code>oi_scp</code> claims are not populated by the JWT bearer handler developped by Microsoft.
|
||||
If you can't migrate to the OpenIddict validation handler, consider splitting the standard <code>scope</code> claim manually to determine whether it contains a specific value.</p>
|
||||
</code></pre>
|
||||
<div class="CAUTION">
|
||||
<h5>Caution</h5>
|
||||
<p>These 2 options only work with the OpenIddict validation handler as the <code>oi_scp</code> claims are not populated by the JWT bearer handler developped by Microsoft.
|
||||
If you can't migrate to the OpenIddict validation handler, consider splitting the standard <code>scope</code> claim manually to determine whether it contains a specific value.</p>
|
||||
</div>
|
||||
<h2 id="add-and-apply-migrations-if-necessary">Add and apply migrations, if necessary</h2>
|
||||
<p>If your application uses Entity Framework Core or Entity Framework 6, add a migration to react to the schema changes listed below and apply it.</p>
|
||||
@@ -396,9 +411,12 @@ and the hybrid flow MUST be explicitly opted in. If you use the hybrid flow, mak
|
||||
{
|
||||
options.AllowHybridFlow();
|
||||
});
|
||||
</code></pre><h2 id="update-your-applications-to-grant-them-the-appropriate-response-type-permissions">Update your applications to grant them the appropriate response type permissions</h2>
|
||||
</code></pre>
|
||||
<h2 id="update-your-applications-to-grant-them-the-appropriate-response-type-permissions">Update your applications to grant them the appropriate response type permissions</h2>
|
||||
<p>New response type permissions - enforced by default - <a href="/configuration/application-permissions.html#response-type-permissions">have been introduced in 3.0</a>.</p>
|
||||
<div class="NOTE"><h5>Note</h5><p>If you have many applications to migrate, you can use <a href="https://github.com/openiddict/openiddict-core/issues/1138#issuecomment-713681158">this script</a>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>If you have many applications to migrate, you can use <a href="https://github.com/openiddict/openiddict-core/issues/1138#issuecomment-713681158">this script</a>
|
||||
to infer appropriate response type permissions using the already granted grant types.</p>
|
||||
</div>
|
||||
</article>
|
||||
@@ -407,16 +425,16 @@ to infer appropriate response type permissions using the already granted grant t
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
|
@@ -2,15 +2,15 @@
|
||||
<!--[if IE]><![endif]-->
|
||||
<html>
|
||||
|
||||
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Migrate to OpenIddict 4.0 </title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta name="title" content="Migrate to OpenIddict 4.0 ">
|
||||
<meta name="generator" content="docfx 2.56.7.0">
|
||||
|
||||
<meta name="generator" content="docfx ">
|
||||
|
||||
<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">
|
||||
@@ -19,9 +19,9 @@
|
||||
<link rel="stylesheet" href="../../styles/main.css">
|
||||
<meta property="docfx:navrel" content="../../toc.html">
|
||||
<meta property="docfx:tocrel" content="../toc.html">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -31,7 +31,7 @@
|
||||
<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>
|
||||
@@ -46,25 +46,25 @@
|
||||
|
||||
<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>
|
||||
@@ -72,8 +72,8 @@
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
|
||||
<span>Generated by <strong>DocFX</strong></span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
<div role="main" class="hide-when-search">
|
||||
|
||||
|
||||
|
||||
<div class="subnav navbar navbar-default">
|
||||
<div class="container hide-when-search" id="breadcrumb">
|
||||
<ul class="breadcrumb">
|
||||
@@ -93,9 +93,11 @@
|
||||
<article class="content wrap" id="_content" data-uid="">
|
||||
<h1 id="migrate-to-openiddict-40">Migrate to OpenIddict 4.0</h1>
|
||||
|
||||
<h2 id="whats-new">What's new?</h2>
|
||||
<h2 id="whats-new">What's new?</h2>
|
||||
<p>The most important changes introduced in 4.0 can be found <a href="https://github.com/openiddict/openiddict-core/releases">here</a>.</p>
|
||||
<div class="NOTE"><h5>Note</h5><p><strong>Unless you're using MongoDB, migrating to OpenIddict 4.0 doesn't require making changes to your database</strong>.</p>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p><strong>Unless you're using MongoDB, migrating to OpenIddict 4.0 doesn't require making changes to your database</strong>.</p>
|
||||
</div>
|
||||
<h2 id="update-your-packages-references">Update your packages references</h2>
|
||||
<p>For that, update your <code>.csproj</code> file to reference the <code>OpenIddict</code> 4.x packages. For instance:</p>
|
||||
@@ -108,7 +110,10 @@
|
||||
<PackageReference Include="OpenIddict.AspNetCore" Version="4.0.0" />
|
||||
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="4.0.0" />
|
||||
</ItemGroup>
|
||||
</code></pre><div class="NOTE"><h5>Note</h5><p>Migrating to ASP.NET Core 7.0 is not required, as OpenIddict 4.0 is still natively compatible with ASP.NET Core 2.1 (.NET Framework-only),
|
||||
</code></pre>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>Migrating to ASP.NET Core 7.0 is not required, as OpenIddict 4.0 is still natively compatible with ASP.NET Core 2.1 (.NET Framework-only),
|
||||
ASP.NET Core 3.1 and ASP.NET Core 6.0. Moving to a newer .NET runtime or ASP.NET Core can be done separately for a simpler/decoupled upgrade:</p>
|
||||
<table>
|
||||
<thead>
|
||||
@@ -194,7 +199,8 @@ read <a href="https://github.com/openiddict/openiddict-core/issues/1613">Breakin
|
||||
.SetUserinfoEndpointUris("connect/userinfo")
|
||||
.SetVerificationEndpointUris("connect/verify");
|
||||
});
|
||||
</code></pre><h2 id="remove-calls-to-addclaims-that-specify-a-list-of-destinations">Remove calls to <code>AddClaim(s)</code> that specify a list of destinations:</h2>
|
||||
</code></pre>
|
||||
<h2 id="remove-calls-to-addclaims-that-specify-a-list-of-destinations">Remove calls to <code>AddClaim(s)</code> that specify a list of destinations:</h2>
|
||||
<p>As explained in <a href="https://kevinchalet.com/2022/06/22/openiddict-4-0-preview1-is-out/">OpenIddict 4.0 preview1 is out</a>,
|
||||
the <code>AddClaim(s)</code> extensions that accepted a <code>destinations</code> parameter have been removed in 4.0.</p>
|
||||
<p>Instead, developers are encouraged to use the new one-shot <code>SetDestinations()</code> extension for <code>ClaimsIdentity</code>
|
||||
@@ -222,7 +228,8 @@ identity.SetDestinations(static claim => claim.Type switch
|
||||
// Otherwise, only store the claim in the access tokens.
|
||||
_ => new[] { Destinations.AccessToken }
|
||||
});
|
||||
</code></pre><h2 id="if-applicable-update-your-openiddict-mongodb-authorizations">If applicable, update your OpenIddict MongoDB authorizations</h2>
|
||||
</code></pre>
|
||||
<h2 id="if-applicable-update-your-openiddict-mongodb-authorizations">If applicable, update your OpenIddict MongoDB authorizations</h2>
|
||||
<p>To match the casing used by the other properties, the name used in the BSON representation of the <code>OpenIddictMongoDbAuthorization.CreationDate</code>
|
||||
property was fixed to use camel case (i.e <code>creation_name</code> instead of <code>CreationDate</code>). To ensure the existing authorizations are correctly
|
||||
updated to use the new name, the following script can be used to update all the existing authorizations at once very efficiently:</p>
|
||||
@@ -247,7 +254,8 @@ var authorizations = database.GetCollection<BsonDocument>(options.Authoriz
|
||||
await authorizations.UpdateManyAsync(
|
||||
filter: Builders<BsonDocument>.Filter.Empty,
|
||||
update: Builders<BsonDocument>.Update.Rename("CreationDate", "creation_date"));
|
||||
</code></pre><h2 id="if-applicable-replace-references-to-portablebouncycastle-by-bouncycastlecryptography">If applicable, replace references to <code>Portable.BouncyCastle</code> by <code>BouncyCastle.Cryptography</code></h2>
|
||||
</code></pre>
|
||||
<h2 id="if-applicable-replace-references-to-portablebouncycastle-by-bouncycastlecryptography">If applicable, replace references to <code>Portable.BouncyCastle</code> by <code>BouncyCastle.Cryptography</code></h2>
|
||||
<p>While previous versions of OpenIddict used the unofficial <a href="https://www.nuget.org/packages/Portable.BouncyCastle"><code>Portable.BouncyCastle</code></a>
|
||||
package maintained by <a href="https://github.com/clairernovotny">Claire Novotny</a> (which was the best .NET Standard-compatible option at the time),
|
||||
OpenIddict 4.0 was updated to use the official package, <a href="https://www.nuget.org/packages/BouncyCastle.Cryptography">BouncyCastle.Cryptography</a>,
|
||||
@@ -266,7 +274,8 @@ ValueTask<TResult> GetAsync<TState, TResult>(
|
||||
ValueTask<TResult?> GetAsync<TState, TResult>(
|
||||
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query,
|
||||
TState state, CancellationToken cancellationToken);
|
||||
</code></pre><p>While not required, it is recommended to also update implementations of <code>IOpenIddictApplicationStore</code> to use the updated parameter names
|
||||
</code></pre>
|
||||
<p>While not required, it is recommended to also update implementations of <code>IOpenIddictApplicationStore</code> to use the updated parameter names
|
||||
for <code>FindByPostLogoutRedirectUriAsync()</code>, <code>FindByRedirectUriAsync()</code>, <code>SetPostLogoutRedirectUrisAsync()</code> and <code>SetRedirectUrisAsync()</code>:</p>
|
||||
<pre><code class="lang-csharp">// OpenIddict 3.x:
|
||||
IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken);
|
||||
@@ -279,7 +288,8 @@ IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(string uri
|
||||
IAsyncEnumerable<TApplication> FindByRedirectUriAsync(string uri, CancellationToken cancellationToken);
|
||||
ValueTask SetPostLogoutRedirectUrisAsync(TApplication application, ImmutableArray<string> uris, CancellationToken cancellationToken);
|
||||
ValueTask SetRedirectUrisAsync(TApplication application, ImmutableArray<string> uris, CancellationToken cancellationToken);
|
||||
</code></pre><h2 id="consider-migrating-to-the-new-openiddict-client-optional">Consider migrating to the new OpenIddict client (optional)</h2>
|
||||
</code></pre>
|
||||
<h2 id="consider-migrating-to-the-new-openiddict-client-optional">Consider migrating to the new OpenIddict client (optional)</h2>
|
||||
<p>OpenIddict 4.0 introduces a new client stack that is natively compatible with all supported versions of ASP.NET Core (2.1
|
||||
on .NET Framework, 3.1, 6.0 and 7.0) and <code>Microsoft.Owin</code> 4.2 (which means it can also be used on ASP.NET 4.6.1 and higher).</p>
|
||||
<p>For more information, read <a href="https://kevinchalet.com/2022/12/23/openiddict-4-0-general-availability/">OpenIddict 4.0 general availability</a>.</p>
|
||||
@@ -289,16 +299,16 @@ on .NET Framework, 3.1, 6.0 and 7.0) and <code>Microsoft.Owin</code> 4.2 (which
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
|
@@ -3,53 +3,53 @@
|
||||
<div>
|
||||
<div class="sidetoc">
|
||||
<div class="toc" id="toc">
|
||||
|
||||
|
||||
<ul class="nav level1">
|
||||
<li>
|
||||
<a href="index.html" class="sidebar-item" name="" title="Introduction">Introduction</a>
|
||||
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<a href="contributing-a-new-web-provider.html" class="sidebar-item" name="" title="Contributing a new Web provider">Contributing a new Web provider</a>
|
||||
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<a href="getting-started.html" class="sidebar-item" name="" title="Getting started">Getting started</a>
|
||||
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<a href="choosing-the-right-flow.html" class="sidebar-item" name="" title="Choosing the right flow">Choosing the right flow</a>
|
||||
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<span class="expand-stub"></span>
|
||||
<a class="sidebar-item" name="" title="Migration guides">Migration guides</a>
|
||||
|
||||
|
||||
|
||||
|
||||
<ul class="nav level2">
|
||||
<li>
|
||||
<a href="migration/20-to-30.html" class="sidebar-item" name="" title="Migration from 2.0 to 3.0">Migration from 2.0 to 3.0</a>
|
||||
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<a href="migration/30-to-40.html" class="sidebar-item" name="" title="Migration from 3.0 to 4.0">Migration from 3.0 to 4.0</a>
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<span class="expand-stub"></span>
|
||||
<a class="sidebar-item" name="" title="External resources">External resources</a>
|
||||
|
||||
|
||||
|
||||
|
||||
<ul class="nav level2">
|
||||
<li>
|
||||
<a href="https://tools.ietf.org/html/rfc6749" class="sidebar-item" name="" title="OAuth 2.0 specification">OAuth 2.0 specification</a>
|
||||
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://openid.net/specs/openid-connect-core-1_0.html" class="sidebar-item" name="" title="OpenID Connect specification">OpenID Connect specification</a>
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
Reference in New Issue
Block a user