<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Refresh Token on Digi Hunch</title><link>https://static.digihunch.com/tag/refresh-token/</link><description>Recent content in Refresh Token on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Wed, 02 Apr 2025 09:55:49 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/refresh-token/index.xml" rel="self" type="application/rss+xml"/><item><title>OAuth 2.0 and OIDC 2 of 2</title><link>https://static.digihunch.com/2023/07/oauth-2-0-and-oidc-2-of-2/</link><pubDate>Thu, 13 Jul 2023 21:24:01 -0400</pubDate><guid>https://static.digihunch.com/2023/07/oauth-2-0-and-oidc-2-of-2/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-oidc-oauth-2.webp" alt="Featured image of post OAuth 2.0 and OIDC 2 of 2" /&gt;&lt;p class="wp-block-paragraph"&gt;I wrote a &lt;a href="https://static.digihunch.com/2020/03/oauth-and-openid-connect/"&gt;brief&lt;/a&gt; on this topic a while back. Now I need to configure OIDC in a few occasions I decide to dive deeper into the flows this time. As I stated in the last post, Nate Barbettini&amp;#8217;s &lt;a href="https://www.youtube.com/watch?v=996OiexHze0"&gt;presentation&lt;/a&gt; from 2017 was awesome and I viewed it again. Slides are available &lt;a href="https://speakerdeck.com/nbarbettini/oauth-and-openid-connect-in-plain-english"&gt;here&lt;/a&gt;. Another great reference is &lt;a href="https://www.deepnetwork.com/blog//2019/11/08/oauth2-oicd-pkce.html"&gt;this post&lt;/a&gt; from DeepNetwork Developer&amp;#8217;s blog.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="h-back-channel-and-front-channel"&gt;Back Channel and Front Channel&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To understand why there are several different flows, it is important to understand the difference between back channel and front end channel.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In web development, traditional architecture involves a frontend (e.g. Browser, or any client-side app) and backend server. The web frontend is written in HTML, CSS, JavaScript, etc. There are also web frameworks such as Django, Angular, to save developers time. Backend (server-side) is responsible for storing and organizing data to ensure frontend can function. There might be multiple backend servers, such as session cache, data store, API server, etc. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In a nutshell, server-to-server communication is back channel, and browser-to-server communication is front channel. From security perspective, we regard front-channel as less secure, because we have less control of the location of the front-end and browser is easy to tamper with.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="550" src="https://static.digihunch.com/wp-content/uploads/2023/07/oauth-channels.webp" alt="" class="wp-image-12934" srcset="https://static.digihunch.com/wp-content/uploads/2023/07/oauth-channels.webp 1024w, https://static.digihunch.com/wp-content/uploads/2023/07/oauth-channels-300x161.webp 300w, https://static.digihunch.com/wp-content/uploads/2023/07/oauth-channels-768x413.webp 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;figcaption class="wp-element-caption"&gt;Back Channel and Front Channel (source https://www.okta.com/blog/2019/04/oauth-when-things-go-wrong/)&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For traditional web applications with client-server architecture, when they communicate with third-party servers, they can initiate the communication from their backends, creating a back channel for better security posture. Single-page applications (SPAs) are applications without their own backends. When building an SPA, the front-end developer deals with frontend frameworks such as React, Angular or Next.js. When SPAs have to communicate with third-party APIs, they have to create a front channel. Also the API must support Cross-Origin Resource Sharing (CORS) for the browser to allow the cross-domain communication.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the web development world, there is also Native App (aka Mobile App). Native App to Server communication is also considered back channel as we consider the client-side (Mobile App) secure. Nate&amp;#8217;s talk makes the following recommendation for the flow (grant type) and I rephrase it as below:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-white-background-color has-background"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Architecture&lt;/th&gt;&lt;th&gt;Recommendation&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Traditional Web Application (client-server architecture)&lt;/td&gt;&lt;td&gt;There are both front and back channels. Use authorization code flow&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Single Page Application (SPA, e.g. JavaScript) with API backend&lt;/td&gt;&lt;td&gt;Front channel only. Use implicit flow &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Native mobile App&lt;/td&gt;&lt;td&gt;Use authorization code flow with PKCE&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Microservices and APIs (Machine-to-Machine)&lt;/td&gt;&lt;td&gt;Back-channel only. Use Client credentials flow&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The message, is that we should use Authorization Code Flow and use back channel, so long as the required component (backend) exists in the architecture. Note that the terminology for these types of applications may differ. For example, when you try to create an OIDC client for Amazon Cognito user pool, here&amp;#8217;s how it categorizes client capability (app type):&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Public client: A native, browser, or mobil-device app. Cognito API requests are made from user systems that are not trusted with a client secret.&lt;/li&gt;&#10;&lt;li&gt;Confidential client: A server-side application that can securely store a client secret. Cognito API requests are made from a central server.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Get used to different terms describing the same concept.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;OAuth 2.0 and OIDC flows&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The original problem that OAuth 2.0 (RFC6749) addresses is delegated authorization. In all OAuth flows, the authorization server issues an Access Token for the client to carry. The Access Token identifies the scope of resources that its carrier is authorized to access. However, third-party services do not always want to delegate authorization to the identity provider. They often just need identity information and want to perform authorization on their own. The OAuth 2.0 Access Token itself is all about permission and does not care about the identify of its carrier. It is not designed for authentication. OAuth 2.0 does not provide a standard way for Authorization Server to keep identity information of the principal. Many developers needs to address identity issue and they started to (mis)use the AccessToken to store identity information in custom fields, until OIDC came about.&lt;/p&gt;&#10;&lt;figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex"&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="543" height="335" data-id="12936" src="https://static.digihunch.com/wp-content/uploads/2025/04/oauth-access-token.webp" alt="" class="wp-image-12936" srcset="https://static.digihunch.com/wp-content/uploads/2025/04/oauth-access-token.webp 543w, https://static.digihunch.com/wp-content/uploads/2025/04/oauth-access-token-300x185.webp 300w" sizes="auto, (max-width: 543px) 100vw, 543px" /&gt;&lt;figcaption class="wp-element-caption"&gt;OAuth: Access Token only&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="686" height="516" data-id="12935" src="https://static.digihunch.com/wp-content/uploads/2025/04/oidc-identity-token.webp" alt="" class="wp-image-12935" srcset="https://static.digihunch.com/wp-content/uploads/2025/04/oidc-identity-token.webp 686w, https://static.digihunch.com/wp-content/uploads/2025/04/oidc-identity-token-300x226.webp 300w" sizes="auto, (max-width: 686px) 100vw, 686px" /&gt;&lt;figcaption class="wp-element-caption"&gt;OIDC: Access + Identity Token&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;OIDC is a thin layer (5%) on top of OAuth 2.0 and one important addition is the ID token. The resource server can, in addition to being asked to allow access, now can understand the identity of the principal requesting to access resources from the ID token. The OIDC layer also uses standard set of scopes and proposes a userinfo endpoint for client to get more details about user information. The authorization code flows in OIDC and OAuth2.0 are roughly the same except for the additions.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In terms of the flows supported, the OAuth flows are defined in &lt;a href="https://datatracker.ietf.org/doc/html/rfc6749"&gt;RFC6749&lt;/a&gt;, including the following grants:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Authorization Code grant&lt;/li&gt;&#10;&lt;li&gt;Implicit grant&lt;/li&gt;&#10;&lt;li&gt;Resource Owner Password Credentials grant&lt;/li&gt;&#10;&lt;li&gt;Client Credentials grant&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The classic grant type is Authorization Code. After verifying with user, the Authorization Server fires a call-back to the client to pass the authorization code. The client, then takes the authorization code, along with its client ID and client secret, to fire a request to Authorization server in exchange for Access Token. The implicit grant skips the Authorization Code step and the client gets the Access Token in a one-stop shop via callback over front channel, which is less secure. The other two grants are less often used.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the OIDC side, the &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html"&gt;specification document&lt;/a&gt; discusses three flows:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Authorization Code Flow (specification 3.1)&lt;/li&gt;&#10;&lt;li&gt;Implicit Flow (specification 3.2)&lt;/li&gt;&#10;&lt;li&gt;Hybrid Flow (specification 3.3)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The original OAuth2.0 flows should only be used in delegated authorization scenario. In most contexts, if we talk about ID token, and if our use case involves authentication, then we&amp;#8217;re talking about OIDC not just OAuth. Since Authorization Code Flow is the classic one, out of all these flows, in the next section we take a closer look at the Authorization Code Flow in OIDC.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Authorization Code Flow in OIDC&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We consider the Authorization Code Flow the baseline flow and others as variations of it owing to architectural limitations. When we mention OIDC we implicitly refers to the Authorization Code Flow unless the context suggests otherwise. Now let&amp;#8217;s zoom in on it:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="631px" viewBox="-0.5 -0.5 631 581" style="max-width:100%;max-height:581px;"&gt;&lt;defs&gt;&lt;style type="text/css"&gt;@import url(https://fonts.googleapis.com/css?family=Architects+Daughter);&amp;#xa;@import url(https://fonts.googleapis.com/css?family=Architects+Daughter);&amp;#xa;&lt;/style&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="0" y="0" width="630" height="580" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 628px; height: 1px; padding-top: 7px; margin-left: 1px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"&gt;OIDC Authorization Code Flow&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="315" y="19" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle" font-weight="bold"&gt;OIDC Authorization Code Flow&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="20" y="78.14" width="100" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 98px; margin-left: 21px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Resource Owner&lt;br /&gt;(User)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="70" y="102" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Resource Owner&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="180" y="78.14" width="100" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 98px; margin-left: 181px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Client App&lt;br /&gt;(front &amp;amp; backend)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="230" y="102" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Client App&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="340" y="78.14" width="100" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 98px; margin-left: 341px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Authorization Server&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="390" y="102" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Authorization Se&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 70 570 L 70 118.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/&gt;&lt;path d="M 230 570 L 230 118.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/&gt;&lt;path d="M 390 570 L 390 118.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/&gt;&lt;rect x="500" y="78.14" width="100" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 98px; margin-left: 501px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Resource Server&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="550" y="102" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Resource Server&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 550 570 L 550 118.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/&gt;&lt;path d="M 70 158.14 L 223.63 158.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 228.88 158.14 L 221.88 161.64 L 223.63 158.14 L 221.88 154.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 149px; margin-left: 151px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;1. launch client app&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="151" y="152" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;1. launch client app&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 230 178.14 L 383.63 178.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 388.88 178.14 L 381.88 181.64 L 383.63 178.14 L 381.88 174.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 171px; margin-left: 311px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;2. Token Request to /authorize&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="311" y="174" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;2. Token Request to /authorize&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 390 218.14 L 76.37 218.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 71.12 218.14 L 78.12 214.64 L 76.37 218.14 L 78.12 221.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 208px; margin-left: 180px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;3. 302 redirect to prompt user to log in&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="180" y="211" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;3. 302 redirect to prompt user to log in&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 70 248.14 L 383.63 248.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 388.88 248.14 L 381.88 251.64 L 383.63 248.14 L 381.88 244.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 237px; margin-left: 150px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;4. Authenticate and consent&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="150" y="240" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;4. Authenticate and consent&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 390 310 L 236.37 310" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 231.12 310 L 238.12 306.5 L 236.37 310 L 238.12 313.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 290px; margin-left: 261px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;6. Redirect browser to the callback URI&lt;br /&gt;, with Authorization Code as a parameter &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="261" y="294" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;6. Redirect browser to the callback URI&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 230 390 L 383.63 390" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 388.88 390 L 381.88 393.5 L 383.63 390 L 381.88 386.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 362px; margin-left: 311px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;7. Request (HTTP) for Tokens&lt;br /&gt;at /token, using Authorization &lt;br /&gt;Code, ClientID and Client Secret&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="311" y="366" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;7. Request (HTTP) for Tokens&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 390 410 L 420 410 L 420 450 L 396.37 450" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 391.12 450 L 398.12 446.5 L 396.37 450 L 398.12 453.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 403px; margin-left: 420px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;8.Validation&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="420" y="406" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;8.Validation&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 390 468.14 L 236.37 468.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 231.12 468.14 L 238.12 464.64 L 236.37 468.14 L 238.12 471.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 451px; margin-left: 311px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;9. Response (HTTP) with &lt;br /&gt;IDToken and AccessToken&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="311" y="454" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;9. Response (HTTP) with&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 207.5 30 L 252.5 30 L 252.5 75 L 207.5 75 Z" fill="#ffffff" stroke="none" pointer-events="all"/&gt;&lt;path d="M 212 55.85 L 219.22 55.85 L 219.22 54.21 L 212 54.21 Z M 212 50.79 L 220.66 50.79 L 220.66 49.16 L 212 49.16 Z M 212 45.74 L 222.11 45.74 L 222.11 44.1 L 212 44.1 Z M 238.79 54.21 L 227.48 54.21 L 228.52 50.07 L 239.82 50.07 Z M 227.24 48.43 L 225.39 55.85 L 240.07 55.85 L 241.92 48.43 Z M 241.71 63.33 C 241.68 63.48 241.54 63.59 241.39 63.59 L 221.35 63.59 C 221.22 63.59 221.14 63.52 221.1 63.47 C 221.06 63.42 221.01 63.33 221.03 63.2 L 224.75 45.7 L 245.45 45.7 Z M 225.92 41.41 L 245.96 41.41 C 246.09 41.41 246.17 41.48 246.21 41.53 C 246.25 41.58 246.3 41.67 246.27 41.8 L 245.8 44.06 L 225.09 44.06 L 225.6 41.67 C 225.63 41.52 225.77 41.41 225.92 41.41 Z M 247.48 40.5 C 247.11 40.04 246.55 39.77 245.96 39.77 L 225.92 39.77 C 225 39.77 224.19 40.43 224 41.33 L 219.43 62.86 C 219.31 63.44 219.45 64.04 219.83 64.5 C 220.2 64.96 220.76 65.23 221.35 65.23 L 241.39 65.23 C 242.31 65.23 243.12 64.57 243.31 63.67 L 247.88 42.14 C 248 41.56 247.86 40.96 247.48 40.5 Z" fill="#232f3e" stroke="none" pointer-events="all"/&gt;&lt;path d="M 60 67 C 60 55 60 49 70 49 C 63.33 49 63.33 37 70 37 C 76.67 37 76.67 49 70 49 C 80 49 80 55 80 67 Z" fill="#f5f5f5" stroke="#666666" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;path d="M 230 518.14 L 543.63 518.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 548.88 518.14 L 541.88 521.64 L 543.63 518.14 L 541.88 514.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 509px; margin-left: 391px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;10. Issue API Request with Tokens&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="391" y="512" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;10. Issue API Request with Tokens&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 550 548.14 L 236.37 548.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 231.12 548.14 L 238.12 544.64 L 236.37 548.14 L 238.12 551.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 539px; margin-left: 348px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;12. Receive API Response&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="348" y="542" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;12. Receive API Response&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 550 530 L 580 530 L 580 540 L 556.37 540" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 551.12 540 L 558.12 536.5 L 556.37 540 L 558.12 543.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 521px; margin-left: 590px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;11. Validation&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="590" y="524" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;11. Validation&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 105 435 C 105 429.48 109.48 425 115 425 L 200 425 C 205.52 425 210 420.52 210 415 C 210 420.52 214.48 425 220 425 L 305 425 C 310.52 425 315 429.48 315 435" fill="none" stroke="#999999" stroke-miterlimit="10" transform="rotate(270,210,425)" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 425px; margin-left: 198px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"&gt;backend&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="198" y="429" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end"&gt;back&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="470" y="202.5" width="60" height="30" fill="none" stroke="none" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 218px; margin-left: 471px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Authorization&lt;br /&gt;Endpoint&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="500" y="221" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Authorizat&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 414.75 240 C 414.75 234.48 419.23 230 424.75 230 L 451 230 C 456.52 230 461 225.52 461 220 C 461 225.52 465.48 230 471 230 L 497.25 230 C 502.77 230 507.25 234.48 507.25 240" fill="none" stroke="#999999" stroke-miterlimit="10" transform="rotate(90,461,230)" pointer-events="all"/&gt;&lt;rect x="461.25" y="370" width="60" height="30" fill="none" stroke="none" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 385px; margin-left: 462px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Token&lt;br /&gt;Endpoint&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="491" y="389" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Token&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 411 415 C 411 409.48 415.48 405 421 405 L 451 405 C 456.52 405 461 400.52 461 395 C 461 400.52 465.48 405 471 405 L 501 405 C 506.52 405 511 409.48 511 415" fill="none" stroke="#999999" stroke-miterlimit="10" transform="rotate(90,461,405)" pointer-events="all"/&gt;&lt;path d="M 536.89 70 C 535.63 70 535 69 535 68.21 L 535 37.58 C 535 36.62 535.74 35.79 536.76 35.79 L 558.22 35.79 C 558.93 35.79 560 36.37 560 37.63 L 560 68.13 C 560 69.2 559.19 70 558.19 70 Z" fill="#7d7c7c" stroke="none" pointer-events="all"/&gt;&lt;path d="M 560 66.66 L 560 68.13 C 560 69.2 559.19 70 558.19 70 L 536.89 70 C 535.63 70 535 69 535 68.21 L 535 66.72 C 535 67.61 535.72 68.47 536.8 68.47 L 558.13 68.47 C 559.07 68.47 560 67.75 560 66.66 Z" fill-opacity="0.3" fill="#000000" stroke="none" pointer-events="all"/&gt;&lt;rect x="535" y="35.79" width="0" height="0" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/&gt;&lt;path d="M 556.07 42.6 L 538.87 42.6 L 538.87 40.59 L 556.07 40.59 Z M 556.07 46.11 L 538.87 46.11 L 538.87 44.09 L 556.07 44.09 Z M 556.07 49.6 L 538.87 49.6 L 538.87 47.6 L 556.07 47.6 Z" fill="#ffffff" stroke="none" pointer-events="all"/&gt;&lt;rect x="369" y="31.89" width="42" height="42" fill="none" stroke="none" pointer-events="all"/&gt;&lt;path d="M 385.81 63.07 L 385.69 60.88 C 385.69 59.99 384.95 59.35 384.22 59.13 C 383.91 59.13 383.61 59.01 383.39 58.81 C 383.27 58.81 383.27 58.68 383.18 58.68 C 383.09 58.68 383.09 58.58 382.96 58.58 C 383.48 58.24 383.91 57.48 383.91 56.71 C 384 56.39 384 55.73 384 55.41 C 383.91 55.09 383.82 55.19 383.82 55.09 C 383.61 55.09 383.48 54.86 383.27 54.86 C 382.96 54.65 382.54 54.74 382.23 54.86 C 382.14 54.86 381.93 54.86 381.8 54.86 C 381.71 54.86 381.59 54.86 381.5 54.86 C 381.4 54.86 381.07 55.09 380.98 55.41 C 380.86 55.85 381.07 56.71 381.07 56.84 C 381.07 57.6 381.4 58.24 381.93 58.58 C 381.93 58.58 381.8 58.58 381.8 58.68 C 381.71 58.68 381.59 58.68 381.59 58.81 C 381.4 59.01 381.07 59.13 380.77 59.13 C 380.03 59.45 379.39 59.99 379.3 60.88 C 379.3 60.88 379.3 60.88 379.08 63.07 C 379.08 63.07 380.55 63.39 382.54 63.39 C 384.34 63.39 385.81 63.07 385.81 63.07 Z M 400.93 63.07 L 400.81 60.88 C 400.81 59.99 400.29 59.35 399.68 59.13 C 399.46 59.13 399.35 59.01 399.16 58.81 C 399.04 58.81 399.04 58.68 398.94 58.68 C 398.94 58.68 398.94 58.58 398.94 58.58 C 399.25 58.24 399.56 57.48 399.56 56.71 C 399.56 56.39 399.56 55.73 399.56 55.41 C 399.56 55.09 399.46 55.19 399.46 55.09 C 399.35 55.09 399.25 54.86 399.04 54.86 C 398.82 54.65 398.39 54.74 398.3 54.86 C 398.09 54.86 398.09 54.86 397.88 54.86 C 397.88 54.86 397.78 54.86 397.78 54.86 C 397.57 54.86 397.47 55.09 397.36 55.41 C 397.26 55.85 397.36 56.71 397.36 56.84 C 397.47 57.6 397.66 58.24 398 58.58 C 398 58.58 398 58.58 397.88 58.68 C 397.88 58.68 397.88 58.68 397.78 58.81 C 397.57 59.01 397.47 59.13 397.26 59.13 C 396.62 59.45 396.1 59.99 396.1 60.88 C 396.1 60.88 396.1 60.88 395.89 63.07 C 395.89 63.07 397.05 63.39 398.39 63.39 C 399.89 63.39 400.93 63.07 400.93 63.07 Z M 396.63 40.09 C 394.95 38.34 392.63 37.26 390.12 37.26 C 384.95 37.13 380.77 41.62 380.77 47.09 C 380.98 49.72 381.93 52.23 383.61 53.88 C 384.86 55.29 386.32 56.18 388 56.62 C 388.13 67.11 388.13 67.11 388.13 67.11 C 388 67.97 388.74 68.64 389.6 68.64 C 390.64 68.64 390.64 68.64 390.64 68.64 C 391.58 68.64 392.22 67.97 392.22 67.11 C 392.22 56.62 392.22 56.62 392.22 56.62 C 396.2 55.51 399.26 51.69 399.26 46.99 C 399.26 44.35 398.31 41.84 396.63 40.09 Z M 389.99 54.53 C 386.12 54.53 382.96 51.15 382.96 46.99 C 382.96 42.95 386.12 39.55 389.99 39.55 C 393.9 39.55 397.05 42.95 397.05 46.99 C 397.05 51.15 393.9 54.53 389.99 54.53 Z M 389.69 40.97 C 389.38 41.07 389.17 40.97 388.96 40.97 C 388.86 40.97 388.65 40.97 388.52 40.97 C 388.31 41.07 387.91 41.41 387.8 42.05 C 387.58 42.72 387.8 44.37 387.8 44.59 C 387.91 45.99 388.43 47.2 389.07 47.64 C 389.07 47.74 389.07 47.86 388.96 47.86 C 388.86 48.09 388.74 48.09 388.65 48.18 C 388.31 48.51 387.91 48.72 387.49 48.85 C 386.84 49.07 386.23 49.49 385.81 50.16 C 386.75 51.81 388.31 52.89 390.12 52.89 C 391.8 52.89 393.26 51.9 394.21 50.25 C 393.9 49.62 393.17 49.07 392.41 48.85 C 392.1 48.72 391.67 48.63 391.37 48.31 C 391.27 48.18 391.15 48.09 390.94 47.96 C 390.85 47.86 390.85 47.74 390.73 47.74 C 391.58 47.2 392.1 45.9 392.22 44.24 C 392.22 43.92 392.22 42.62 392.22 41.95 C 392.1 41.51 392.01 41.51 391.89 41.51 C 391.67 41.41 391.49 40.97 391.15 40.87 C 390.64 40.65 389.99 40.87 389.69 40.97 Z M 369 52.9 C 369 41.3 378.44 31.89 390 31.89 C 401.67 31.89 411 41.3 411 52.9 C 411 64.6 401.67 73.89 390 73.89 C 378.44 73.89 369 64.6 369 52.9 Z" fill="#28a8e0" stroke="none" pointer-events="all"/&gt;&lt;ellipse cx="390" cy="52.89" rx="20.58" ry="20.58" fill="#ffffff" stroke="none" pointer-events="all"/&gt;&lt;rect x="369" y="31.89" width="42" height="42" fill="none" stroke="none" pointer-events="all"/&gt;&lt;path d="M 385.81 63.07 L 385.69 60.88 C 385.69 59.99 384.95 59.35 384.22 59.13 C 383.91 59.13 383.61 59.01 383.39 58.81 C 383.27 58.81 383.27 58.68 383.18 58.68 C 383.09 58.68 383.09 58.58 382.96 58.58 C 383.48 58.24 383.91 57.48 383.91 56.71 C 384 56.39 384 55.73 384 55.41 C 383.91 55.09 383.82 55.19 383.82 55.09 C 383.61 55.09 383.48 54.86 383.27 54.86 C 382.96 54.65 382.54 54.74 382.23 54.86 C 382.14 54.86 381.93 54.86 381.8 54.86 C 381.71 54.86 381.59 54.86 381.5 54.86 C 381.4 54.86 381.07 55.09 380.98 55.41 C 380.86 55.85 381.07 56.71 381.07 56.84 C 381.07 57.6 381.4 58.24 381.93 58.58 C 381.93 58.58 381.8 58.58 381.8 58.68 C 381.71 58.68 381.59 58.68 381.59 58.81 C 381.4 59.01 381.07 59.13 380.77 59.13 C 380.03 59.45 379.39 59.99 379.3 60.88 C 379.3 60.88 379.3 60.88 379.08 63.07 C 379.08 63.07 380.55 63.39 382.54 63.39 C 384.34 63.39 385.81 63.07 385.81 63.07 Z M 400.93 63.07 L 400.81 60.88 C 400.81 59.99 400.29 59.35 399.68 59.13 C 399.46 59.13 399.35 59.01 399.16 58.81 C 399.04 58.81 399.04 58.68 398.94 58.68 C 398.94 58.68 398.94 58.58 398.94 58.58 C 399.25 58.24 399.56 57.48 399.56 56.71 C 399.56 56.39 399.56 55.73 399.56 55.41 C 399.56 55.09 399.46 55.19 399.46 55.09 C 399.35 55.09 399.25 54.86 399.04 54.86 C 398.82 54.65 398.39 54.74 398.3 54.86 C 398.09 54.86 398.09 54.86 397.88 54.86 C 397.88 54.86 397.78 54.86 397.78 54.86 C 397.57 54.86 397.47 55.09 397.36 55.41 C 397.26 55.85 397.36 56.71 397.36 56.84 C 397.47 57.6 397.66 58.24 398 58.58 C 398 58.58 398 58.58 397.88 58.68 C 397.88 58.68 397.88 58.68 397.78 58.81 C 397.57 59.01 397.47 59.13 397.26 59.13 C 396.62 59.45 396.1 59.99 396.1 60.88 C 396.1 60.88 396.1 60.88 395.89 63.07 C 395.89 63.07 397.05 63.39 398.39 63.39 C 399.89 63.39 400.93 63.07 400.93 63.07 Z M 396.63 40.09 C 394.95 38.34 392.63 37.26 390.12 37.26 C 384.95 37.13 380.77 41.62 380.77 47.09 C 380.98 49.72 381.93 52.23 383.61 53.88 C 384.86 55.29 386.32 56.18 388 56.62 C 388.13 67.11 388.13 67.11 388.13 67.11 C 388 67.97 388.74 68.64 389.6 68.64 C 390.64 68.64 390.64 68.64 390.64 68.64 C 391.58 68.64 392.22 67.97 392.22 67.11 C 392.22 56.62 392.22 56.62 392.22 56.62 C 396.2 55.51 399.26 51.69 399.26 46.99 C 399.26 44.35 398.31 41.84 396.63 40.09 Z M 389.99 54.53 C 386.12 54.53 382.96 51.15 382.96 46.99 C 382.96 42.95 386.12 39.55 389.99 39.55 C 393.9 39.55 397.05 42.95 397.05 46.99 C 397.05 51.15 393.9 54.53 389.99 54.53 Z M 389.69 40.97 C 389.38 41.07 389.17 40.97 388.96 40.97 C 388.86 40.97 388.65 40.97 388.52 40.97 C 388.31 41.07 387.91 41.41 387.8 42.05 C 387.58 42.72 387.8 44.37 387.8 44.59 C 387.91 45.99 388.43 47.2 389.07 47.64 C 389.07 47.74 389.07 47.86 388.96 47.86 C 388.86 48.09 388.74 48.09 388.65 48.18 C 388.31 48.51 387.91 48.72 387.49 48.85 C 386.84 49.07 386.23 49.49 385.81 50.16 C 386.75 51.81 388.31 52.89 390.12 52.89 C 391.8 52.89 393.26 51.9 394.21 50.25 C 393.9 49.62 393.17 49.07 392.41 48.85 C 392.1 48.72 391.67 48.63 391.37 48.31 C 391.27 48.18 391.15 48.09 390.94 47.96 C 390.85 47.86 390.85 47.74 390.73 47.74 C 391.58 47.2 392.1 45.9 392.22 44.24 C 392.22 43.92 392.22 42.62 392.22 41.95 C 392.1 41.51 392.01 41.51 391.89 41.51 C 391.67 41.41 391.49 40.97 391.15 40.87 C 390.64 40.65 389.99 40.87 389.69 40.97 Z M 369 52.9 C 369 41.3 378.44 31.89 390 31.89 C 401.67 31.89 411 41.3 411 52.9 C 411 64.6 401.67 73.89 390 73.89 C 378.44 73.89 369 64.6 369 52.9 Z" fill="#28a8e0" stroke="none" pointer-events="all"/&gt;&lt;path d="M 390 260 L 420 260 L 420 300 L 396.37 300" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 391.12 300 L 398.12 296.5 L 396.37 300 L 398.12 303.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 253px; margin-left: 420px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;5.Validation&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="420" y="256" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;5.Validation&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;switch&gt;&lt;g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/&gt;&lt;a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank" rel="noopener"&gt;&lt;text text-anchor="middle" font-size="10px" x="50%" y="100%"&gt;Text is not SVG &amp;#8211; cannot display&lt;/text&gt;&lt;/a&gt;&lt;/switch&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Here is the narrative from my own words:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;The user launches client application, which detects that user has not logged in, and redirect to log in page.&lt;/li&gt;&#10;&lt;li&gt;The client app sends an HTTP request for authorization code to the /authorize endpoint of Authorization server. This request consists of the following fields:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Response type: code, indicating it is requesting authorization code&lt;/li&gt;&#10;&lt;li&gt;Scope: openid, standard for oidc&lt;/li&gt;&#10;&lt;li&gt;RedirectURI: my.com/oidc-callback, Authorization Server will use this to call back with code.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;The authorization server redirects the user to a prompt for log-in&lt;/li&gt;&#10;&lt;li&gt;The user completes authentication and consent&lt;/li&gt;&#10;&lt;li&gt;The Authorization server validates user information within its identity provider&lt;/li&gt;&#10;&lt;li&gt;The Authorization server fires an HTTP request call-back at the Redirect URI (on the backend), with Authorization Code. &lt;/li&gt;&#10;&lt;li&gt;The client app issues an HTTP request for ID Token and Access Token to the /token endpoint of Authorization server. This request consists of:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Authorization Code (received from previous step)&lt;/li&gt;&#10;&lt;li&gt;Client ID&lt;/li&gt;&#10;&lt;li&gt;Client Secret&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;The Authorization server validates the information and process the request, and prepare the response with the following fields:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;ID Token: identifies the resource owner.&lt;/li&gt;&#10;&lt;li&gt;Access Token: identifies what the client app can access&lt;/li&gt;&#10;&lt;li&gt;Expiration&lt;/li&gt;&#10;&lt;li&gt;(Optional) Refresh Token&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;The client app receives the tokens above in the HTTP response from the /token endpoint&lt;/li&gt;&#10;&lt;li&gt;With the Tokens, the client app issues API requests to the resource server&lt;/li&gt;&#10;&lt;li&gt;The resource server independently validates the token&lt;/li&gt;&#10;&lt;li&gt;The resource server send API response back the the client app.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are also a few points of configurations. First, the Resource Server needs to trust the Authorization Server. The Authorization Server uses its private key to sign the JWT tokens and the Resource Server needs the public key to validates it. Second, the authorization server needs to know about the client app. We usually configure the Authorization Server upfront, to generate the client ID and secret. The Client app will keep them as part of its configuration. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;It is important to note that, when I use the term client app (OIDC calls it client), the word &amp;#8220;client&amp;#8221; is relative to the Authorization server. The client app itself consists of both frontend (browser) and backend (aka relying party). In this flow, the authorization code is not exposed to browser.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Other OIDC Flows&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now we can discuss some flows for other architectures.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Authorization Code flow has a close variation with the use of PKCE (Proof Key for Code Exchange). For native apps, &lt;a href="https://blog.postman.com/pkce-oauth-how-to/"&gt;postman&lt;/a&gt; and Okta recommend Authorization Code flow with PKCE. When client app first requests for authorization code, it also includes a challenge. After the callback, when it sends the authorization code back to authorization server in exchange for tokens, the request now adds a verifier. This way, even if the authorization code may not be securely saved, the authorization server can ensure it is the same client app that requests authorization code and that requests tokens.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;An SPA or JavaScript app does not have a way to a. store Authorization code and b. listen on a call-back URI. As a result, it makes sense for the SPA to just fetch the Tokens directly. This make the implicit flow. The spec doc refers to it as simplified authorization code flow. The grant type is &amp;#8220;implicit&amp;#8221; because there is no intermediate credentials issued. In this flow, the Authorization server does not authenticate its client. The tokens may be exposed to resource owner or other applications with access to resource owner&amp;#8217;s user-agent. This flow improve the responsiveness but we should be wary of the security implications.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="631px" viewBox="-0.5 -0.5 631 421" style="max-width:100%;max-height:421px;"&gt;&lt;defs&gt;&lt;style type="text/css"&gt;@import url(https://fonts.googleapis.com/css?family=Architects+Daughter);&amp;#xa;@import url(https://fonts.googleapis.com/css?family=Architects+Daughter);&amp;#xa;&lt;/style&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="0" y="0" width="630" height="420" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 628px; height: 1px; padding-top: 7px; margin-left: 1px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"&gt;OIDC Implicit Flow&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="315" y="19" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle" font-weight="bold"&gt;OIDC Implicit Flow&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="20" y="78.14" width="100" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 98px; margin-left: 21px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Resource Owner&lt;br /&gt;(User)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="70" y="102" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Resource Owner&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="180" y="78.14" width="100" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 98px; margin-left: 181px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;SPA in Browser&lt;br /&gt;(frontend)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="230" y="102" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;SPA in Browser&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="340" y="78.14" width="100" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 98px; margin-left: 341px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Authorization Server&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="390" y="102" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Authorization Se&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 70 410 L 70 118.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/&gt;&lt;path d="M 230 410 L 230 118.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/&gt;&lt;path d="M 390 410 L 390 118.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/&gt;&lt;rect x="500" y="78.14" width="100" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 98px; margin-left: 501px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Resource Server&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="550" y="102" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Resource Server&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 550 410 L 550 118.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/&gt;&lt;path d="M 70 158.14 L 223.63 158.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 228.88 158.14 L 221.88 161.64 L 223.63 158.14 L 221.88 154.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 149px; margin-left: 151px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;1. launch SPA&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="151" y="152" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;1. launch SPA&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 230 178.14 L 383.63 178.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 388.88 178.14 L 381.88 181.64 L 383.63 178.14 L 381.88 174.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 171px; margin-left: 312px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;2. Token request to /authorize&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="312" y="174" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;2. Token request to /authorize&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 390 218.14 L 76.37 218.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 71.12 218.14 L 78.12 214.64 L 76.37 218.14 L 78.12 221.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 211px; margin-left: 180px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;3. 302 redirect to prompt user to log in&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="180" y="214" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;3. 302 redirect to prompt user to log in&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 70 248.14 L 383.63 248.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 388.88 248.14 L 381.88 251.64 L 383.63 248.14 L 381.88 244.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 239px; margin-left: 160px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;4. Authenticate and consent&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="160" y="242" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;4. Authenticate and consent&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 391.25 260 L 421.25 260 L 421.25 300 L 397.62 300" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 392.37 300 L 399.37 296.5 L 397.62 300 L 399.37 303.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 281px; margin-left: 462px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;5.Validation&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="462" y="284" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;5.Validation&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 390 320 L 236.37 320" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 231.12 320 L 238.12 316.5 L 236.37 320 L 238.12 323.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 303px; margin-left: 311px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;6. Response (HTTP) with &lt;br /&gt;IDToken and AccessToken&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="311" y="306" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;6. Response (HTTP) with&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 207.5 30 L 252.5 30 L 252.5 75 L 207.5 75 Z" fill="#ffffff" stroke="none" pointer-events="all"/&gt;&lt;path d="M 212 55.85 L 219.22 55.85 L 219.22 54.21 L 212 54.21 Z M 212 50.79 L 220.66 50.79 L 220.66 49.16 L 212 49.16 Z M 212 45.74 L 222.11 45.74 L 222.11 44.1 L 212 44.1 Z M 238.79 54.21 L 227.48 54.21 L 228.52 50.07 L 239.82 50.07 Z M 227.24 48.43 L 225.39 55.85 L 240.07 55.85 L 241.92 48.43 Z M 241.71 63.33 C 241.68 63.48 241.54 63.59 241.39 63.59 L 221.35 63.59 C 221.22 63.59 221.14 63.52 221.1 63.47 C 221.06 63.42 221.01 63.33 221.03 63.2 L 224.75 45.7 L 245.45 45.7 Z M 225.92 41.41 L 245.96 41.41 C 246.09 41.41 246.17 41.48 246.21 41.53 C 246.25 41.58 246.3 41.67 246.27 41.8 L 245.8 44.06 L 225.09 44.06 L 225.6 41.67 C 225.63 41.52 225.77 41.41 225.92 41.41 Z M 247.48 40.5 C 247.11 40.04 246.55 39.77 245.96 39.77 L 225.92 39.77 C 225 39.77 224.19 40.43 224 41.33 L 219.43 62.86 C 219.31 63.44 219.45 64.04 219.83 64.5 C 220.2 64.96 220.76 65.23 221.35 65.23 L 241.39 65.23 C 242.31 65.23 243.12 64.57 243.31 63.67 L 247.88 42.14 C 248 41.56 247.86 40.96 247.48 40.5 Z" fill="#232f3e" stroke="none" pointer-events="all"/&gt;&lt;path d="M 60 67 C 60 55 60 49 70 49 C 63.33 49 63.33 37 70 37 C 76.67 37 76.67 49 70 49 C 80 49 80 55 80 67 Z" fill="#f5f5f5" stroke="#666666" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;path d="M 230 350 L 543.63 350" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 548.88 350 L 541.88 353.5 L 543.63 350 L 541.88 346.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 341px; margin-left: 391px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;7. Issue API Request with Tokens&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="391" y="344" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;7. Issue API Request with Tokens&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 550 390 L 236.37 390" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 231.12 390 L 238.12 386.5 L 236.37 390 L 238.12 393.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 381px; margin-left: 349px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;11. Receive API Response&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="349" y="384" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;11. Receive API Response&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 550 360 L 580 360 L 580 380 L 556.37 380" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/&gt;&lt;path d="M 551.12 380 L 558.12 376.5 L 556.37 380 L 558.12 383.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 352px; margin-left: 591px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;8. Validation&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="591" y="355" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;8. Validation&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 536.89 70 C 535.63 70 535 69 535 68.21 L 535 37.58 C 535 36.62 535.74 35.79 536.76 35.79 L 558.22 35.79 C 558.93 35.79 560 36.37 560 37.63 L 560 68.13 C 560 69.2 559.19 70 558.19 70 Z" fill="#7d7c7c" stroke="none" pointer-events="all"/&gt;&lt;path d="M 560 66.66 L 560 68.13 C 560 69.2 559.19 70 558.19 70 L 536.89 70 C 535.63 70 535 69 535 68.21 L 535 66.72 C 535 67.61 535.72 68.47 536.8 68.47 L 558.13 68.47 C 559.07 68.47 560 67.75 560 66.66 Z" fill-opacity="0.3" fill="#000000" stroke="none" pointer-events="all"/&gt;&lt;rect x="535" y="35.79" width="0" height="0" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/&gt;&lt;path d="M 556.07 42.6 L 538.87 42.6 L 538.87 40.59 L 556.07 40.59 Z M 556.07 46.11 L 538.87 46.11 L 538.87 44.09 L 556.07 44.09 Z M 556.07 49.6 L 538.87 49.6 L 538.87 47.6 L 556.07 47.6 Z" fill="#ffffff" stroke="none" pointer-events="all"/&gt;&lt;rect x="369" y="31.89" width="42" height="42" fill="none" stroke="none" pointer-events="all"/&gt;&lt;path d="M 385.81 63.07 L 385.69 60.88 C 385.69 59.99 384.95 59.35 384.22 59.13 C 383.91 59.13 383.61 59.01 383.39 58.81 C 383.27 58.81 383.27 58.68 383.18 58.68 C 383.09 58.68 383.09 58.58 382.96 58.58 C 383.48 58.24 383.91 57.48 383.91 56.71 C 384 56.39 384 55.73 384 55.41 C 383.91 55.09 383.82 55.19 383.82 55.09 C 383.61 55.09 383.48 54.86 383.27 54.86 C 382.96 54.65 382.54 54.74 382.23 54.86 C 382.14 54.86 381.93 54.86 381.8 54.86 C 381.71 54.86 381.59 54.86 381.5 54.86 C 381.4 54.86 381.07 55.09 380.98 55.41 C 380.86 55.85 381.07 56.71 381.07 56.84 C 381.07 57.6 381.4 58.24 381.93 58.58 C 381.93 58.58 381.8 58.58 381.8 58.68 C 381.71 58.68 381.59 58.68 381.59 58.81 C 381.4 59.01 381.07 59.13 380.77 59.13 C 380.03 59.45 379.39 59.99 379.3 60.88 C 379.3 60.88 379.3 60.88 379.08 63.07 C 379.08 63.07 380.55 63.39 382.54 63.39 C 384.34 63.39 385.81 63.07 385.81 63.07 Z M 400.93 63.07 L 400.81 60.88 C 400.81 59.99 400.29 59.35 399.68 59.13 C 399.46 59.13 399.35 59.01 399.16 58.81 C 399.04 58.81 399.04 58.68 398.94 58.68 C 398.94 58.68 398.94 58.58 398.94 58.58 C 399.25 58.24 399.56 57.48 399.56 56.71 C 399.56 56.39 399.56 55.73 399.56 55.41 C 399.56 55.09 399.46 55.19 399.46 55.09 C 399.35 55.09 399.25 54.86 399.04 54.86 C 398.82 54.65 398.39 54.74 398.3 54.86 C 398.09 54.86 398.09 54.86 397.88 54.86 C 397.88 54.86 397.78 54.86 397.78 54.86 C 397.57 54.86 397.47 55.09 397.36 55.41 C 397.26 55.85 397.36 56.71 397.36 56.84 C 397.47 57.6 397.66 58.24 398 58.58 C 398 58.58 398 58.58 397.88 58.68 C 397.88 58.68 397.88 58.68 397.78 58.81 C 397.57 59.01 397.47 59.13 397.26 59.13 C 396.62 59.45 396.1 59.99 396.1 60.88 C 396.1 60.88 396.1 60.88 395.89 63.07 C 395.89 63.07 397.05 63.39 398.39 63.39 C 399.89 63.39 400.93 63.07 400.93 63.07 Z M 396.63 40.09 C 394.95 38.34 392.63 37.26 390.12 37.26 C 384.95 37.13 380.77 41.62 380.77 47.09 C 380.98 49.72 381.93 52.23 383.61 53.88 C 384.86 55.29 386.32 56.18 388 56.62 C 388.13 67.11 388.13 67.11 388.13 67.11 C 388 67.97 388.74 68.64 389.6 68.64 C 390.64 68.64 390.64 68.64 390.64 68.64 C 391.58 68.64 392.22 67.97 392.22 67.11 C 392.22 56.62 392.22 56.62 392.22 56.62 C 396.2 55.51 399.26 51.69 399.26 46.99 C 399.26 44.35 398.31 41.84 396.63 40.09 Z M 389.99 54.53 C 386.12 54.53 382.96 51.15 382.96 46.99 C 382.96 42.95 386.12 39.55 389.99 39.55 C 393.9 39.55 397.05 42.95 397.05 46.99 C 397.05 51.15 393.9 54.53 389.99 54.53 Z M 389.69 40.97 C 389.38 41.07 389.17 40.97 388.96 40.97 C 388.86 40.97 388.65 40.97 388.52 40.97 C 388.31 41.07 387.91 41.41 387.8 42.05 C 387.58 42.72 387.8 44.37 387.8 44.59 C 387.91 45.99 388.43 47.2 389.07 47.64 C 389.07 47.74 389.07 47.86 388.96 47.86 C 388.86 48.09 388.74 48.09 388.65 48.18 C 388.31 48.51 387.91 48.72 387.49 48.85 C 386.84 49.07 386.23 49.49 385.81 50.16 C 386.75 51.81 388.31 52.89 390.12 52.89 C 391.8 52.89 393.26 51.9 394.21 50.25 C 393.9 49.62 393.17 49.07 392.41 48.85 C 392.1 48.72 391.67 48.63 391.37 48.31 C 391.27 48.18 391.15 48.09 390.94 47.96 C 390.85 47.86 390.85 47.74 390.73 47.74 C 391.58 47.2 392.1 45.9 392.22 44.24 C 392.22 43.92 392.22 42.62 392.22 41.95 C 392.1 41.51 392.01 41.51 391.89 41.51 C 391.67 41.41 391.49 40.97 391.15 40.87 C 390.64 40.65 389.99 40.87 389.69 40.97 Z M 369 52.9 C 369 41.3 378.44 31.89 390 31.89 C 401.67 31.89 411 41.3 411 52.9 C 411 64.6 401.67 73.89 390 73.89 C 378.44 73.89 369 64.6 369 52.9 Z" fill="#28a8e0" stroke="none" pointer-events="all"/&gt;&lt;ellipse cx="390" cy="52.89" rx="20.58" ry="20.58" fill="#ffffff" stroke="none" pointer-events="all"/&gt;&lt;rect x="369" y="31.89" width="42" height="42" fill="none" stroke="none" pointer-events="all"/&gt;&lt;path d="M 385.81 63.07 L 385.69 60.88 C 385.69 59.99 384.95 59.35 384.22 59.13 C 383.91 59.13 383.61 59.01 383.39 58.81 C 383.27 58.81 383.27 58.68 383.18 58.68 C 383.09 58.68 383.09 58.58 382.96 58.58 C 383.48 58.24 383.91 57.48 383.91 56.71 C 384 56.39 384 55.73 384 55.41 C 383.91 55.09 383.82 55.19 383.82 55.09 C 383.61 55.09 383.48 54.86 383.27 54.86 C 382.96 54.65 382.54 54.74 382.23 54.86 C 382.14 54.86 381.93 54.86 381.8 54.86 C 381.71 54.86 381.59 54.86 381.5 54.86 C 381.4 54.86 381.07 55.09 380.98 55.41 C 380.86 55.85 381.07 56.71 381.07 56.84 C 381.07 57.6 381.4 58.24 381.93 58.58 C 381.93 58.58 381.8 58.58 381.8 58.68 C 381.71 58.68 381.59 58.68 381.59 58.81 C 381.4 59.01 381.07 59.13 380.77 59.13 C 380.03 59.45 379.39 59.99 379.3 60.88 C 379.3 60.88 379.3 60.88 379.08 63.07 C 379.08 63.07 380.55 63.39 382.54 63.39 C 384.34 63.39 385.81 63.07 385.81 63.07 Z M 400.93 63.07 L 400.81 60.88 C 400.81 59.99 400.29 59.35 399.68 59.13 C 399.46 59.13 399.35 59.01 399.16 58.81 C 399.04 58.81 399.04 58.68 398.94 58.68 C 398.94 58.68 398.94 58.58 398.94 58.58 C 399.25 58.24 399.56 57.48 399.56 56.71 C 399.56 56.39 399.56 55.73 399.56 55.41 C 399.56 55.09 399.46 55.19 399.46 55.09 C 399.35 55.09 399.25 54.86 399.04 54.86 C 398.82 54.65 398.39 54.74 398.3 54.86 C 398.09 54.86 398.09 54.86 397.88 54.86 C 397.88 54.86 397.78 54.86 397.78 54.86 C 397.57 54.86 397.47 55.09 397.36 55.41 C 397.26 55.85 397.36 56.71 397.36 56.84 C 397.47 57.6 397.66 58.24 398 58.58 C 398 58.58 398 58.58 397.88 58.68 C 397.88 58.68 397.88 58.68 397.78 58.81 C 397.57 59.01 397.47 59.13 397.26 59.13 C 396.62 59.45 396.1 59.99 396.1 60.88 C 396.1 60.88 396.1 60.88 395.89 63.07 C 395.89 63.07 397.05 63.39 398.39 63.39 C 399.89 63.39 400.93 63.07 400.93 63.07 Z M 396.63 40.09 C 394.95 38.34 392.63 37.26 390.12 37.26 C 384.95 37.13 380.77 41.62 380.77 47.09 C 380.98 49.72 381.93 52.23 383.61 53.88 C 384.86 55.29 386.32 56.18 388 56.62 C 388.13 67.11 388.13 67.11 388.13 67.11 C 388 67.97 388.74 68.64 389.6 68.64 C 390.64 68.64 390.64 68.64 390.64 68.64 C 391.58 68.64 392.22 67.97 392.22 67.11 C 392.22 56.62 392.22 56.62 392.22 56.62 C 396.2 55.51 399.26 51.69 399.26 46.99 C 399.26 44.35 398.31 41.84 396.63 40.09 Z M 389.99 54.53 C 386.12 54.53 382.96 51.15 382.96 46.99 C 382.96 42.95 386.12 39.55 389.99 39.55 C 393.9 39.55 397.05 42.95 397.05 46.99 C 397.05 51.15 393.9 54.53 389.99 54.53 Z M 389.69 40.97 C 389.38 41.07 389.17 40.97 388.96 40.97 C 388.86 40.97 388.65 40.97 388.52 40.97 C 388.31 41.07 387.91 41.41 387.8 42.05 C 387.58 42.72 387.8 44.37 387.8 44.59 C 387.91 45.99 388.43 47.2 389.07 47.64 C 389.07 47.74 389.07 47.86 388.96 47.86 C 388.86 48.09 388.74 48.09 388.65 48.18 C 388.31 48.51 387.91 48.72 387.49 48.85 C 386.84 49.07 386.23 49.49 385.81 50.16 C 386.75 51.81 388.31 52.89 390.12 52.89 C 391.8 52.89 393.26 51.9 394.21 50.25 C 393.9 49.62 393.17 49.07 392.41 48.85 C 392.1 48.72 391.67 48.63 391.37 48.31 C 391.27 48.18 391.15 48.09 390.94 47.96 C 390.85 47.86 390.85 47.74 390.73 47.74 C 391.58 47.2 392.1 45.9 392.22 44.24 C 392.22 43.92 392.22 42.62 392.22 41.95 C 392.1 41.51 392.01 41.51 391.89 41.51 C 391.67 41.41 391.49 40.97 391.15 40.87 C 390.64 40.65 389.99 40.87 389.69 40.97 Z M 369 52.9 C 369 41.3 378.44 31.89 390 31.89 C 401.67 31.89 411 41.3 411 52.9 C 411 64.6 401.67 73.89 390 73.89 C 378.44 73.89 369 64.6 369 52.9 Z" fill="#28a8e0" stroke="none" pointer-events="all"/&gt;&lt;/g&gt;&lt;switch&gt;&lt;g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/&gt;&lt;a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank" rel="noopener"&gt;&lt;text text-anchor="middle" font-size="10px" x="50%" y="100%"&gt;Text is not SVG &amp;#8211; cannot display&lt;/text&gt;&lt;/a&gt;&lt;/switch&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As stated above, for SPAs (or in-browser JavaScript), we have to choice but the Implicit Flow because the client app is front-end only and we do not consider it able to securely store credentials. Client apps that can securely store client credentials may benefit from &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth"&gt;Hybrid Flow.&lt;/a&gt; In the hybrid flow, when the authorization server fires callback, the callback includes a single-use authorization code, along with ID token, access token, or both, depending on the provided response_type. Then the client app sends it back to authorization server, along with client credentials, in exchange for a second ID token and access token. The &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowSteps"&gt;specification&lt;/a&gt; has a good table that compares the three flows:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="255" src="https://static.digihunch.com/wp-content/uploads/2023/07/flow-table.webp" alt="" class="wp-image-12937" srcset="https://static.digihunch.com/wp-content/uploads/2023/07/flow-table.webp 1024w, https://static.digihunch.com/wp-content/uploads/2023/07/flow-table-300x75.webp 300w, https://static.digihunch.com/wp-content/uploads/2023/07/flow-table-768x191.webp 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Apart from the three flows, there are also some &amp;#8220;unofficial&amp;#8221; OIDC flows, that are not discussed in the specification. For example, Auth0 adopted some original OAuth2.0 grants in conformance to OIDC, including &lt;a href="https://auth0.com/docs/authenticate/login/oidc-conformant-authentication/oidc-adoption-client-credentials-flow"&gt;Client Credentials Flow with OIDC&lt;/a&gt; and &lt;a href="https://auth0.com/docs/authenticate/login/oidc-conformant-authentication/oidc-adoption-rop-flow"&gt;Resource Owner Password Flow with OIDC&lt;/a&gt;. The client credentials flow is for machine-to-machine identity and is not concerned with user identity.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Identify the Flow&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A challenge that I faced is to make sense of the Authorization Code Flow in real life. I realized that the components (Client App, Authorization Server and Resource Server) in Authorization Code Flow are conceptual. In real life we do not always find a counterpart that perfectly match their features. When we try to introduce OIDC for authentication, we often need to build our own solution, with additional tools.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Take the client app for example. We would need one or several components in real life to perform the followings in order to qualify as a Client App in the sense of Authorization Code Flow, it needs to:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;know the authorization endpoint and construct the HTTP request for Authorization code;&lt;/li&gt;&#10;&lt;li&gt;stand up an HTTP service (relying party) to listen to call back, and parse the Authorization Code;&lt;/li&gt;&#10;&lt;li&gt;securely store Authorization code, and have access to client ID and client secret;&lt;/li&gt;&#10;&lt;li&gt;construct a request for tokens using client ID, secret and authorization Code received;&lt;/li&gt;&#10;&lt;li&gt;parse the tokens from the response from Token endpoint&lt;/li&gt;&#10;&lt;li&gt;to pass the tokens along&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When developers builds an application with OIDC integration capability, they&amp;#8217;d have to implement all these using the library of their programming language. In addition to application&amp;#8217;s own server, the OIDC module will need its own backend capable of doing all the activities above. The alternative option is to introduce a OIDC capable client proxy service.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As for the Resource Server, it needs to have a trust on the Authorization Server, so that it can cryptographically validate the tokens that the Authorization Server has issued using the well-known public key.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the Authorization Server side, as we discussed. It needs to provision client ID and client secret that itself can later recognize when client app connects to it. It also needs to have both authorization endpoint and token endpoint. Often times, the authorization server contains identity store and we&amp;#8217;d like to call it the identity provider, but that is not always the case. A company may have a home grown identity store that does not support OIDC. In that case, to qualify as an OIDC Authorization server, they need a server proxy.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Open ID Connect Specifications&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Despite the different implementation by different vendors, we often need to resort to the official standard documentation. &lt;a href="https://openid.net/developers/specs/"&gt;This &lt;/a&gt;Open ID connect page lists all the specification if you expand &amp;#8220;OpenID Connect specification&amp;#8221; under Final Specifications. The most commonly used ones are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;OpenID Connect Core specification [&lt;strong&gt;OpenID.Core.Errata2&lt;/strong&gt;], which covers the foundation and three login flows (Authorization Code, Implicit and Hybrid). This was developed early and the current version [OpenID.Core.Errata2] is from Dec 2023 but the two previous versions [OpenID.Core.Errata1] and [OpenID.Core.Final] had been around since 2014;&lt;/li&gt;&#10;&lt;li&gt;Open ID Connect Session Management [&lt;strong&gt;OpenID.Session&lt;/strong&gt;], another core document that stipulates how to manage sessions, finalized in Sept 2022;&lt;/li&gt;&#10;&lt;li&gt;Open ID Connect Discovery 1.0 [&lt;strong&gt;OpenID.Discovery&lt;/strong&gt;], which stipulates the hosting OIDC discovery document, finalized in Dec 2023;&lt;/li&gt;&#10;&lt;li&gt;Open ID RP-Initiated Logout [&lt;strong&gt;OpenID.RPInitiated&lt;/strong&gt;], one of the logout flow specification, drafted in 2020 and finalized in Sep 2022;&lt;/li&gt;&#10;&lt;li&gt;Open ID Front-Channel Logout [&lt;strong&gt;OpenID.FrontChannel&lt;/strong&gt;], one of the logout flow specification, drafted from March 2016 and finalized in Oct 2022;&lt;/li&gt;&#10;&lt;li&gt;Open ID Back-Channel Logout [&lt;strong&gt;OpenID.BackChannel&lt;/strong&gt;], one of the logout flow specification, drafted in 2016 and finalized in Sep 2022;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Do read the specification when you&amp;#8217;re configuring integration. It is worth noting that apart from the Core specification which has been finalized for a decade, most of the other specifications did not finalize until late 2022. Therefore, it is important for integrators to validate the compliance state of the components in the implementation.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;OIDC Proxy&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As a result, with regard to OIDC, there are two categories of proxies: OIDC client proxy and OIDC server proxy. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For example, in my previous &lt;a href="https://static.digihunch.com/2022/02/istio-external-authorization/"&gt;post&lt;/a&gt;, I explained how to configure external authorization via OIDC in Istio. Looking at the diagram, it uses OAuth2 proxy to integrate with GCP as the authorization server. In this use case, GCP is natively OIDC capable, the the Hello Word App isn&amp;#8217;t. Therefore, the OAuth2-proxy that we introduced is an OIDC client proxy. &lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="584" height="373" src="https://static.digihunch.com/wp-content/uploads/2023/07/oauthproxy.png" alt="" class="wp-image-9277" srcset="https://static.digihunch.com/wp-content/uploads/2023/07/oauthproxy.png 584w, https://static.digihunch.com/wp-content/uploads/2023/07/oauthproxy-300x192.png 300w" sizes="auto, (max-width: 584px) 100vw, 584px" /&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For a corporate with Active Directory, the identity store only supports LDAP protocol. In order to quality the identity store as an OIDC Authorization Server, we would need a server-side proxy such as the LDAP &lt;a href="https://dexidp.io/docs/connectors/"&gt;connector in Dex&lt;/a&gt;, with the Active Directory as authentication source. The diagram of dex is a good summary of its role:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full is-resized"&gt;&lt;img loading="lazy" decoding="async" width="760" height="460" src="https://static.digihunch.com/wp-content/uploads/2023/07/dex.png" alt="" class="wp-image-9255" style="width:461px;height:279px" srcset="https://static.digihunch.com/wp-content/uploads/2023/07/dex.png 760w, https://static.digihunch.com/wp-content/uploads/2023/07/dex-300x182.png 300w" sizes="auto, (max-width: 760px) 100vw, 760px" /&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In some scenarios, we refer to this role as identity broker. Dex is an identity broker. Another important project to know is KeyCloak, which is sponsored by Red Hat and now a CNCF project. Although you can configure KeyCloak as an identity broker, it is much more than a broker. KeyCloadk is a full-fledged identity and access management solution on its own. It can act as the entire Authorization server. The diagram in &lt;a href="https://developers.redhat.com/blog/2019/12/11/keycloak-core-concepts-of-open-source-identity-and-access-management#"&gt;this&lt;/a&gt; blog post summarizes its features well. It is for teams that wants to build their home grown identity store. Think of KeyCloak as a self-managed open-source alternative to IAM solutions such as Okta or Auth0.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Amazon Cognito user pool plays a similar role. A user pool serves as an identity store to an app. The integration (no matter which flow and how Cognito calls them) is supposed to be &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client#allowed_oauth_flows"&gt;OIDC&lt;/a&gt; compliant. However, as of date, the integration with Cognito user pool isn&amp;#8217;t. For example, the &lt;a href="https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html"&gt;logout endpoint&lt;/a&gt; requires client_id parameter where as the &lt;a href="https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout"&gt;RP initiated logout specification&lt;/a&gt; has it optional. On the other hand, it can &lt;a href="https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-identity-federation.html"&gt;federate&lt;/a&gt; its own identity pool with a third party via standard protocol including &lt;a href="https://docs.aws.amazon.com/cognito/latest/developerguide/federation-endpoints.html"&gt;OIDC&lt;/a&gt;.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="782" height="201" src="https://static.digihunch.com/wp-content/uploads/2023/07/cognito.png" alt="" class="wp-image-9550" srcset="https://static.digihunch.com/wp-content/uploads/2023/07/cognito.png 782w, https://static.digihunch.com/wp-content/uploads/2023/07/cognito-300x77.png 300w, https://static.digihunch.com/wp-content/uploads/2023/07/cognito-768x197.png 768w" sizes="auto, (max-width: 782px) 100vw, 782px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In any use case where we need to bring OIDC integration, we need to start with the flow recommendation for each architecture, then we examine the existing component against the flow diagram. From there, we can identify the missing pieces and determine where and how we should configure the proxy.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Summary&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The OIDC topic confuses me big time every time I need to configure identity store. With this post, I was hoping to elaborate on the Authorization Code Flow for OIDC. See OpenID &lt;a href="https://openid.net/certification/"&gt;certification&lt;/a&gt; for a list of providers. Further I discussed the two categories of proxies in the OIDC picture. Hopefully, when the OIDC topic comes back again, I will be able to quickly match which is which, and identify the missing piece to build a solution.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2023/06/kubernetes-paas-and-red-hat-openshift/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Kubernetes Platform as a Service and Red Hat OpenShift&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2023/07/authenticate-kube-apiserver-via-oidc/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Authentication to kube-apiserver via OIDC&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>OAuth 2.0 and OIDC 1 of 2</title><link>https://static.digihunch.com/2020/03/oauth-and-openid-connect/</link><pubDate>Sat, 14 Mar 2020 21:10:00 -0400</pubDate><guid>https://static.digihunch.com/2020/03/oauth-and-openid-connect/</guid><description>&lt;p class="wp-block-paragraph"&gt;OAuth 2.0 and OpenID Connect (OIDC 1.0) are different but highly related protocols and they are often confused. When we talk about IAM (identity and access management), we should first distinguish between Authentication (AuthN) and Authorization (AuthZ):&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;AutheNtication (AuthN, aka Identity Management) is about validating user&amp;#8217;s identity by verifying that the user trying to connect is actually who it claims itself to be;&lt;/li&gt;&#10;&lt;li&gt;AuthoriZation (AuthZ, aka Access Management) refers to granting or denying access to specific resources based on the requesting user&amp;#8217;s identity. It is usually performed after a user is identified through authentication. The most common approach is Role-Based Access Control (RBAC).&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In a nutshell, OAuth 2.0 deals with authorization. OIDC is a layer later developed on top of OAuth 2.0, to deal with authentication. This post is greatly influenced by a &lt;a href="https://www.youtube.com/watch?v=996OiexHze0"&gt;presentation&lt;/a&gt; (1 hour) delivered by Nate Barbettini from Okta, with the slides available &lt;a href="https://speakerdeck.com/nbarbettini/oauth-and-openid-connect-in-plain-english"&gt;here&lt;/a&gt;. There is also an abridged and illustrated video (16 min) by Okta available &lt;a href="https://www.youtube.com/watch?v=t18YB3xDfXI"&gt;here&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="oauth-2-0"&gt;OAuth 2.0&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;OAuth was originally developed by Twitter and Google in 2006 as an open standard for API authorization. &lt;strong&gt;OAuth 2.0&lt;/strong&gt; is published in 2012. It allows user to &lt;span style="text-decoration: underline;"&gt;delegate authorization&lt;/span&gt;. The original scenario is a user signed up to a new application and allows it to automatically import her Gmail contact. The technical problem to solve is: how can a user (Resource Owner) let an app (Client) to access his contact list stored in Google server (Resource Server)? The proposal is that it redirects user to Google Account page (Authorization Server) for user to log in. Then Google Account issues token to the application (Client) with user&amp;#8217;s approval. Note that the user did NOT log in to the application itself with her Google account. From the application&amp;#8217;s standpoint, the user had been authenticated already, and was simply importing contact after logging in. The roles involved in OAuth 2.0 are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Resource: the contact list of the user&lt;/li&gt;&#10;&lt;li&gt;Resource owner: the user&lt;/li&gt;&#10;&lt;li&gt;Client: the application&lt;/li&gt;&#10;&lt;li&gt;Resource Server: contact.google.com&lt;/li&gt;&#10;&lt;li&gt;Authorization Server: accounts.google.com&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The diagram below illustrates the interactions:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://assets.digitalocean.com/articles/oauth/auth_code_flow.png" alt="Authorization Code Flow"/&gt;&lt;figcaption class="wp-element-caption"&gt;OAuth 2.0 Authorization Code Flow&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2"&gt;This&lt;/a&gt; page has further details for each step. Note that at step 3 to 5 may seem unnecessary because Auth Server could have send Access Token Grant to Application via User-Agent at step 3, which could have eliminate the need for step 4 and 5. In fact this design is to avoid sending critical information (Access Token Grant) to User-Agent (browser) which is considered in secure. In other words, it avoids front channel (User-agent to auth server) and prefers back channel (Client to Auth server) for security. This is the difference between Authorization code flow and the implicit flow.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With OAuth 2.0, there are a number of flows:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Authorization code (front channel and back channel)&lt;/li&gt;&#10;&lt;li&gt;Implicit (front channel only, token returned to user agent directly)&lt;/li&gt;&#10;&lt;li&gt;Resource owner password credentials (back channel only)&lt;/li&gt;&#10;&lt;li&gt;Client credentials (back channel only)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In Authorization Code Flow, the Application (client) needs a one-time registration with the Auth Server and is given a client ID and client secret, which are sent to Auth Server at step 4 along with Access Token Request, to prove the identity of the client application.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that OAuth 2.0 is an inherently insecure protocol since it does not support signature, encryption, channel binding or client verification. The protocol relies entirely on the underlying transport layer security (TLS) to provide confidentiality and integrity.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Also note that throughout the process (Authorization Code Flow as an example), the Client application eventually is granted access to user&amp;#8217;s data. However, it does not know anything about the user itself. Neither the authorization code grant, nor the access token grant is &lt;span style="text-decoration: underline;"&gt;obligated&lt;/span&gt; to present information about the user itself. Therefore, OAuth 2.0 is designed strictly for permission purpose without the intent to address identity issue. In the flow, the auth server does the authentication (for the purpose of granting access to resources, but none of the authentication. A user logs in to client application as Bob, when he requests to imports contact, he is redirected to account.google.com and there he could put in the credential of Alice and therefore load Alice&amp;#8217;s Google contacts into Bob&amp;#8217;s App account!&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="pseudo-authentication-with-oauth-2-0"&gt;Pseudo-authentication with OAuth 2.0&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In many real life OAuth 2.0 implementations, at step 3, the Auth server chooses to include a field about the user&amp;#8217;s identity. This makes user&amp;#8217;s identity visible to the client, and the client is therefore able to confirm user&amp;#8217;s identity in its own code. This also allows client application to use OAuth 2.0 as an authentication method, which is referred to as pseudo-authentication. The access token acts as a kind of &amp;#8220;valet key&amp;#8221; that the application can include with its request to the auth server, as a proof that it has user&amp;#8217;s permission to access the resources (or APIs).&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Because the identity provider (auth server) typically (but not always) authenticates the user as part of the process of granting an OAuth access token, it&amp;#8217;s tempting to view a successful OAuth access token request as an authentication method itself. However, because OAuth was not designed with this use case in mind, making this assumption can lead to major security flaws.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Nate&amp;#8217;s presentation outlined some scenarios where OAuth 2.0 is applied up to 2012, and which ones are misuses:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Simple login &amp;#8211; pseudo authentication with OAuth 2.0&lt;/li&gt;&#10;&lt;li&gt;Single sign-on across sites &amp;#8211; pseudo authentication with OAuth 2.0&lt;/li&gt;&#10;&lt;li&gt;Mobile app login &amp;#8211; pseudo authentication with OAuth 2.0&lt;/li&gt;&#10;&lt;li&gt;Delegated authorization &amp;#8211; the only intended use case for OAuth 2.0&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To address the authentication issue properly, and in a standard approach, we need OpenID Connect.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="openid-connect-oidc"&gt;OpenID Connect (OIDC) &lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;OpenID Connect is an open standard for authentication, promoted by the non-profit OpenID Foundation. It allows user to be authenticated using a third-party service called identity providers. User may choose to use their preferred OpenID Connect providers to log in to websites that accept the OpenID Connect authentication scheme. For example, a user uses her Facebook to login to an online application.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;OpenID Connect is an extension to OAuth 2.0 with a just few additions:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;In addition to access token, an ID token is returned by the authorization server;&lt;/li&gt;&#10;&lt;li&gt;Userinfo end point is provided in case Id token is not sufficient and more user information is needed;&lt;/li&gt;&#10;&lt;li&gt;&amp;#8220;openid&amp;#8221; is passed as a parameter in the Scope during the initial call to the authorization server;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Therefore OpenID Connect is considered an identity layer on top of OAuth 2.0. Many application supports OpenID Connect such as &lt;a href="https://nifi.apache.org/"&gt;Apache Nifi&lt;/a&gt;. OIDC is comparable with SAML in the sense that both provide SSO feature (federated identity). Here is a comparison table:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&#10;&lt;table id="tablepress-6" class="tablepress tablepress-id-6"&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="row-1"&gt;&#10;&#9;&lt;td class="column-1"&gt;&lt;/td&gt;&lt;th class="column-2"&gt;OpenID Connect&lt;/th&gt;&lt;th class="column-3"&gt;SAML&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody class="row-striping row-hover"&gt;&#10;&lt;tr class="row-2"&gt;&#10;&#9;&lt;td class="column-1"&gt;Main Purpose&lt;/td&gt;&lt;td class="column-2"&gt;SSO for consumer/mobile applications&lt;/td&gt;&lt;td class="column-3"&gt;SSO for enterprise applications&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-3"&gt;&#10;&#9;&lt;td class="column-1"&gt;Load&lt;/td&gt;&lt;td class="column-2"&gt;Relatively light weight&lt;/td&gt;&lt;td class="column-3"&gt;Heavy weight due to the size of XML messages &lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-4"&gt;&#10;&#9;&lt;td class="column-1"&gt;Use case&lt;/td&gt;&lt;td class="column-2"&gt;Satisfies both authentication and authorization use cases, often combined with OAuth 2.0&lt;/td&gt;&lt;td class="column-3"&gt;Generally not used for API security&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-5"&gt;&#10;&#9;&lt;td class="column-1"&gt;Transport&lt;/td&gt;&lt;td class="column-2"&gt;HTTP GET and HTTP POST&lt;/td&gt;&lt;td class="column-3"&gt;HTTP Redirect (GET) binding, SAML SOAP binding, HTTP POST binding, et&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-6"&gt;&#10;&#9;&lt;td class="column-1"&gt;&lt;/td&gt;&lt;td class="column-2"&gt;&lt;/td&gt;&lt;td class="column-3"&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://medium.com/@awskarthik82/simple-guide-to-saml-vs-oidc-33a3349189c6"&gt;Here &lt;/a&gt;are more details about their differences. In general SAML is more common in the enterprise world for SSO and it has been around for a while. When developing new applications for enterprise it is advised to consider OIDC first.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;OIDC also has authorization code flow, with the additional fields on top of its counterpart in OAuth 2.0. The authorization server returns both access and ID tokens, wrapped in a data structure named JWT (JSON Web Token). The JWT includes a signature field, allowing the client application to verify it with authorization server&amp;#8217;s public key. Nate&amp;#8217;s presentation proposes the following flows for each application type:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Web application with server backend: authorization code flow&lt;/li&gt;&#10;&lt;li&gt;Native mobile app: authorization code flow with PKCE&lt;/li&gt;&#10;&lt;li&gt;Java Script app (SPA) with API backend: implicit flow&lt;/li&gt;&#10;&lt;li&gt;Microservices and APIs: client credential flow&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In addition, &lt;a href="https://developer.okta.com/docs/concepts/oauth-openid/"&gt;this&lt;/a&gt; page from Okta developer has a good summary of how to select flow type (grant) based on each use case.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="summary"&gt;Summary&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;OpenID Connect is an authentication protocol for the purpose of validating user&amp;#8217;s identity. OAuth 2.0 is an authorization protocol. You should use OAuth 2.0 for granting access to your API, or access to user data in other systems. If you need to log user in, or make your accounts available in other systems, you need OIDC.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The &lt;a href="https://static.digihunch.com/2023/07/oauth-2-0-and-oidc-2-of-2/"&gt;next post&lt;/a&gt; about OAuth and OIDC was posted in 2023.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;br&gt; &lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/03/saml-security-assertion-markup-language/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Security Assertion Markup Language (SAML)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/03/authentication-mechanisms-under-simple-authentication-and-security-layer-sasl/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;SASL Authentication Mechanisms&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>