Files
openiddict-documentation/guides/choosing-the-right-flow.html

259 lines
17 KiB
HTML
Raw Normal View History

2022-01-07 17:11:48 +00:00
<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
2023-05-02 19:58:39 +00:00
2021-05-19 15:30:14 +00:00
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
2021-05-19 15:38:49 +00:00
<title>Choosing the right flow </title>
2021-05-19 15:30:14 +00:00
<meta name="viewport" content="width=device-width">
2021-05-19 15:38:49 +00:00
<meta name="title" content="Choosing the right flow ">
2023-05-02 19:58:39 +00:00
<meta name="generator" content="docfx 2.56.7.0">
2021-05-19 15:30:14 +00:00
<link rel="shortcut icon" href="../images/favicon.ico">
2022-01-07 17:11:48 +00:00
<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">
2021-05-19 15:30:14 +00:00
<link rel="stylesheet" href="../styles/main.css">
<meta property="docfx:navrel" content="../toc.html">
<meta property="docfx:tocrel" content="toc.html">
2023-05-02 19:58:39 +00:00
2022-01-07 17:11:48 +00:00
</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>
2023-05-02 19:58:39 +00:00
2022-01-07 17:11:48 +00:00
<a class="brand" href="../index.html">
2022-01-07 17:58:08 +00:00
<img src="../images/logo.png" alt="OpenIddict" class="logomark">
<span class="brand-title">OpenIddict</span>
2022-01-07 17:11:48 +00:00
</a>
</div>
<div class="body-content">
<div id="blackout" class="blackout" onclick="toggleMenu()"></div>
<nav id="sidebar" role="navigation">
<div class="sidebar">
2023-05-02 19:58:39 +00:00
2022-01-07 17:11:48 +00:00
<div>
2023-05-02 19:58:39 +00:00
2022-01-07 17:11:48 +00:00
<a class="brand" href="../index.html">
2022-01-07 17:58:08 +00:00
<img src="../images/logo.png" alt="OpenIddict" class="logomark">
<span class="brand-title">OpenIddict</span>
2022-01-07 17:11:48 +00:00
</a>
<div id="navbar">
2023-05-02 19:58:39 +00:00
2022-01-07 17:11:48 +00:00
</div>
2023-05-02 19:58:39 +00:00
2022-01-07 17:11:48 +00:00
</div>
<div class="sidebar-item-separator"></div>
2023-05-02 19:58:39 +00:00
2022-01-07 17:11:48 +00:00
<div id="sidetoggle">
<div id="sidetoc"></div>
</div>
</div>
<div class="footer">
2023-05-02 19:58:39 +00:00
<span>Generated by <strong>DocFX</strong></span>
2022-01-07 17:11:48 +00:00
</div>
</nav>
<main class="main-panel">
<div role="main" class="hide-when-search">
2023-05-02 19:58:39 +00:00
2022-01-07 17:11:48 +00:00
<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="">
2021-05-19 15:38:49 +00:00
<h1 id="choosing-the-right-flow">Choosing the right flow</h1>
2021-05-19 15:30:14 +00:00
<p>OpenIddict offers built-in support for all the standard flows defined by the
<a href="https://tools.ietf.org/html/rfc6749">OAuth 2.0</a> and <a href="https://openid.net/specs/openid-connect-core-1_0.html">OpenID Connect</a> core specifications:
<a href="https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth">the authorization code flow</a>,
<a href="https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth">the implicit flow</a>,
<a href="https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth">the hybrid flow</a> (which is basically a mix between the first two flows),
<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>
2023-05-02 19:58:39 +00:00
when implementing your own authorization server ; so here&#39;s a quick overview of the different OAuth 2.0/OpenID Connect flows:</p>
2021-05-19 15:30:14 +00:00
<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,
2023-05-02 19:58:39 +00:00
its own client credentials) and gets back an access token it can use to retrieve the user&#39;s resources.</p>
2021-05-19 15:30:14 +00:00
<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&amp;username=johndoe&amp;password=A3ddj3w
2023-05-02 19:58:39 +00:00
</code></pre><pre><code class="lang-http">HTTP/1.1 200 OK
2021-05-19 15:30:14 +00:00
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
&quot;access_token&quot;:&quot;2YotnFZFEjr1zCsicMWpAA&quot;,
&quot;token_type&quot;:&quot;bearer&quot;,
&quot;expires_in&quot;:3600
}
2023-05-02 19:58:39 +00:00
</code></pre><div class="CAUTION"><h5>Caution</h5><p>This flow is <strong>not recommended by the OAuth 2.0 specification</strong> as it&#39;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&#39;t be fully trusted by the authorization server</strong>.</p>
<p>While popular and trivial to implement (as it doesn&#39;t involve any redirection or consent form and unlike interactive flows, doesn&#39;t require implementing
2023-04-29 15:54:59 +00:00
cross-site request forgery (XSRF) countermeasures to prevent session fixation attacks), <strong>its use in new applications is not recommended</strong>. Instead,
2023-05-02 19:58:39 +00:00
users are encouraged to use the authorization code flow, that doesn&#39;t expose passwords to client applications and is not limited to password authentication.</p>
</div>
2021-05-19 15:30:14 +00:00
<!-- more -->
<hr>
<h3 id="client-credentials-grant-recommended-for-machine-to-machine-communication">Client credentials grant (recommended for machine-to-machine communication)</h3>
2023-05-02 19:58:39 +00:00
<p>The client credentials grant is almost identical to the resource owner password credentials grant, except it&#39;s been specifically designed for <strong>client-to-server scenarios</strong>
2021-05-19 15:30:14 +00:00
(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
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&amp;client_id=s6BhdRkqt3&amp;client_secret=gX1fBat3bV
2023-05-02 19:58:39 +00:00
</code></pre><pre><code class="lang-http">HTTP/1.1 200 OK
2021-05-19 15:30:14 +00:00
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
&quot;access_token&quot;:&quot;2YotnFZFEjr1zCsicMWpAA&quot;,
&quot;token_type&quot;:&quot;bearer&quot;,
&quot;expires_in&quot;:3600
}
2023-05-02 19:58:39 +00:00
</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
2021-05-19 15:30:14 +00:00
<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>
2023-05-02 19:58:39 +00:00
<p>This means that <strong>you CAN&#39;T use the client credentials grant with public applications</strong> like browser,
2021-05-19 15:30:14 +00:00
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>
2023-05-02 19:58:39 +00:00
<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&#39;s
2021-05-19 15:30:14 +00:00
<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>
<p><img src="choosing-the-right-flow/authorization-code-flow.png" alt="Authorization code flow"></p>
<ul>
<li><strong>Step 1: the authorization request</strong></li>
</ul>
<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>
2023-05-02 19:58:39 +00:00
<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&#39;re using, POST requests might also be supported to allow you to send large authorization requests.
2021-05-19 15:30:14 +00:00
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&amp;client_id=s6BhdRkqt3&amp;state=af0ifjsldkj&amp;redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
2023-05-02 19:58:39 +00:00
</code></pre><pre><code class="lang-http">GET /connect/authorize?response_type=code&amp;client_id=s6BhdRkqt3&amp;state=af0ifjsldkj&amp;redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
2021-05-19 15:30:14 +00:00
Host: server.example.com
2023-05-02 19:58:39 +00:00
</code></pre><p>The way the identity provider handles the authorization request is implementation-specific but in most cases, a consent form
2021-05-19 15:30:14 +00:00
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&amp;state=af0ifjsldkj
2023-05-02 19:58:39 +00:00
</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&#39;t match.
2021-05-19 15:30:14 +00:00
<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>
2023-05-02 19:58:39 +00:00
<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>
2021-05-19 15:30:14 +00:00
<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
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&amp;code=SplxlOBeZQQYbYS6WxSbIA&amp;redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb&amp;client_id=s6BhdRkqt3&amp;client_secret=gX1fBat3bV&amp;scope=openid
2023-05-02 19:58:39 +00:00
</code></pre><pre><code class="lang-http">HTTP/1.1 200 OK
2021-05-19 15:30:14 +00:00
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
&quot;access_token&quot;:&quot;2YotnFZFEjr1zCsicMWpAA&quot;,
&quot;token_type&quot;:&quot;bearer&quot;,
&quot;expires_in&quot;:3600
}
2023-05-02 19:58:39 +00:00
</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
2021-05-19 15:30:14 +00:00
that will be returned by the authorization endpoint to the original authorization request. This mechanism is known as
2023-05-02 19:58:39 +00:00
<a href="../configuration/proof-key-for-code-exchange.html">Proof Key for Code Exchange</a> and is fully supported by OpenIddict. </p>
2021-05-19 15:30:14 +00:00
</div>
<hr>
<h3 id="implicit-flow-not-recommended-for-new-applications">Implicit flow (not recommended for new applications)</h3>
2023-05-02 19:58:39 +00:00
<p>The implicit flow is similar to the authorization code flow, <strong>except there&#39;s no token request/response step</strong>: the access token is directly returned
2021-05-19 15:30:14 +00:00
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&amp;client_id=s6BhdRkqt3&amp;redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb&amp;scope=openid&amp;state=af0ifjsldkj&amp;nonce=n-0S6_WzA2Mj HTTP/1.1
Host: server.example.com
2023-05-02 19:58:39 +00:00
</code></pre><pre><code class="lang-http">HTTP/1.1 302 Found
2021-05-19 15:30:14 +00:00
Location: https://client.example.org/cb#access_token=SlAV32hkKG&amp;token_type=bearer&amp;expires_in=3600&amp;state=af0ifjsldkj
2023-05-02 19:58:39 +00:00
</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&#39;t support
2021-05-19 15:30:14 +00:00
<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>
2023-05-02 19:58:39 +00:00
<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&#39;t match.
2021-05-19 15:30:14 +00:00
<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>
With OpenID Connect, this can be done by using <code>response_type=id_token token</code> and checking the <code>aud</code> claim
of the JWT identity token, that must correspond or contain the <code>client_id</code> of the client application.</p>
</div>
2022-01-07 17:11:48 +00:00
</article>
</div>
</main>
</div>
2023-05-02 19:58:39 +00:00
<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>
2022-01-07 17:11:48 +00:00
</body>
</html>