<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ali Khalili</title>
    <description>The latest articles on DEV Community by Ali Khalili (@alikhalili).</description>
    <link>https://dev.to/alikhalili</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F625551%2Fe654c335-d38e-4886-a83a-cdfb2c17e99d.jpeg</url>
      <title>DEV Community: Ali Khalili</title>
      <link>https://dev.to/alikhalili</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alikhalili"/>
    <language>en</language>
    <item>
      <title>OAuth 2.0 Authorization code grant with Postman, Part 2</title>
      <dc:creator>Ali Khalili</dc:creator>
      <pubDate>Mon, 14 Feb 2022 10:38:17 +0000</pubDate>
      <link>https://dev.to/oneadvanced/oauth-20-authorization-code-grant-with-postman-part-2-7aa</link>
      <guid>https://dev.to/oneadvanced/oauth-20-authorization-code-grant-with-postman-part-2-7aa</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/oneadvanced/oauth-20-authorization-code-grant-with-postman-part-1-5238"&gt;first part&lt;/a&gt;, we have shown how the &lt;strong&gt;OAuth 2.0 Authorization code&lt;/strong&gt; grant works when using &lt;strong&gt;Keycloak&lt;/strong&gt; and &lt;strong&gt;Postman&lt;/strong&gt;. Authorization code flow is the most common secure &lt;strong&gt;OAuth 2.0&lt;/strong&gt; flow. In the sixth step of that process, the client should provide client credentials in a base64 encoding format for requesting an access token. Unfortunately, for public clients like a mobile app or a single-page app, keeping client credentials secrets safe is impossible. There is no way for public clients to guarantee the security of the client credentials, which is used for requesting an access token. In addition, for the mobile app there is another threat. Malicious applications on the user's device can capture the redirect URL to receive an authorization code from the authorization server to then exchange for their own access token.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirement
&lt;/h2&gt;

&lt;p&gt;For the following steps in this blog post on your local machine, you need to have the &lt;strong&gt;Keycloak&lt;/strong&gt; server running, a &lt;strong&gt;Keycloak&lt;/strong&gt; realm, and at least one user created. You also need to have the &lt;strong&gt;Postman&lt;/strong&gt; on your local machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Securing code exchange with PKCE
&lt;/h2&gt;

&lt;p&gt;Given the above issues, &lt;strong&gt;OAuth 2.0&lt;/strong&gt; provides a more secure authorization flow to a better secure mobile apps or other types of public clients.&lt;br&gt;
From the &lt;a href="https://oauth.net/2/pkce/" rel="noopener noreferrer"&gt;RFC 7636: Proof Key for Code Exchange&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ &lt;strong&gt;PKCE&lt;/strong&gt; (RFC 7636) is an extension to the Authorization Code flow to prevent CSRF and authorization code injection attacks. &lt;strong&gt;PKCE&lt;/strong&gt; is not a replacement for a client secret, and &lt;strong&gt;PKCE&lt;/strong&gt; is recommended even if a client is using a client secret.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The way &lt;strong&gt;PKCE&lt;/strong&gt;, pronounced “pixy”, works is quite simple. Before the client redirects the user to the authorization server endpoint for initializing a new authorization code flow, it generates another random value, known as the &lt;code&gt;code verifier&lt;/code&gt;. The client also stores this new random value locally. Rather than sending this value directly to the authorization server, the client first should compute the hash value of the &lt;code&gt;code verifier&lt;/code&gt; to create a &lt;code&gt;code challenge&lt;/code&gt; using the &lt;strong&gt;SHA-256&lt;/strong&gt; hash function. Then the client adds the &lt;code&gt;code challenge&lt;/code&gt; as part of the authorization request using the following additional parameters:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

code_challenge
      REQUIRED.
      Code challenge.

code_challenge_method
      OPTIONAL.
      Defaults to "plain" if not present in the request. 
      Code verifier transformation method is "S256" or "plain".


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Later, when the client calls the authorization server token endpoint to exchange the authorization code for an access token, it sends the original &lt;code&gt;code verifier&lt;/code&gt; (unhashed) in the request. The authorization server will check that the &lt;strong&gt;SHA-256&lt;/strong&gt; hash of the &lt;code&gt;code verifier&lt;/code&gt; matches the code challenge that is received in the authorization request.&lt;/p&gt;

&lt;p&gt;If an attacker intercepts both the redirect to the authorization server and the response authorization code, it cannot use the authorization code because it can not compute the correct &lt;code&gt;code verifier&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization code flow with PKCE
&lt;/h2&gt;


&lt;p&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.svc.oneadvanced.com%2Fengineering-blogs%2Foauth2-authorization-grant-with-postman%2Fauthorization_flow_pkce.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.svc.oneadvanced.com%2Fengineering-blogs%2Foauth2-authorization-grant-with-postman%2Fauthorization_flow_pkce.jpg" alt="A diagram to visualize the authorization code flow with PKCE that is explained in the steps below."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;For the first step, we need to fill all needed &lt;strong&gt;OAuth 2.0&lt;/strong&gt; configuration options, then click on Get New Access Token in the &lt;strong&gt;Postman&lt;/strong&gt; Authorization tab.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auth URL: &lt;code&gt;{server}/auth/realms/{realm}/protocol/openid-connect/auth&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Access Token URL: &lt;code&gt;{server}/auth/realms/{realm}/protocol/openid-connect/token&lt;/code&gt;
&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.svc.oneadvanced.com%2Fengineering-blogs%2Foauth2-authorization-grant-with-postman%2Fauthorization_flow_pkce_s_1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.svc.oneadvanced.com%2Fengineering-blogs%2Foauth2-authorization-grant-with-postman%2Fauthorization_flow_pkce_s_1.jpg" alt="An example of the Postman Authorization configuration options that are required in order for Postman to retrieve tokens."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Postman&lt;/strong&gt; redirects the user with its embedded browser to the &lt;strong&gt;Keycloak&lt;/strong&gt;’s auth endpoint. &lt;strong&gt;Postman&lt;/strong&gt; includes Client Id (&lt;code&gt;client_id&lt;/code&gt;) and required scopes (&lt;code&gt;scope&lt;/code&gt;) in this redirect. Also, &lt;strong&gt;Postman&lt;/strong&gt; generates a new random value for the &lt;code&gt;code verifier&lt;/code&gt; and adds the hash value of it to the redirect URL as a new query parameter.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;HTTP 200&lt;br&gt;
GET &lt;a href="https://KEYCLOAKDOMAIN/auth/realms/test-realm/protocol/openid-connect/auth" rel="noopener noreferrer"&gt;https://KEYCLOAKDOMAIN/auth/realms/test-realm/protocol/openid-connect/auth&lt;/a&gt;?&lt;br&gt;
    &lt;span class="nv"&gt;response_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;code&amp;amp;&lt;br&gt;
    &lt;span class="nv"&gt;client_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CLIENTID&amp;amp;&lt;br&gt;
    &lt;span class="nv"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;state_value&amp;amp;&lt;br&gt;
    &lt;span class="nv"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;offline_access&amp;amp;&lt;br&gt;
    &lt;span class="nv"&gt;redirect_uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;a href="https://localhost:8081/test-callback" rel="noopener noreferrer"&gt;https://localhost:8081/test-callback&lt;/a&gt;&amp;amp;&lt;br&gt;
    &lt;span class="nv"&gt;code_challenge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Q0J7-pF3nmAP3XrTmUt6DEFL9vKG9_1V12fXXMTVIqk&amp;amp;&lt;br&gt;
    &lt;span class="nv"&gt;code_challenge_method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;S256&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Step 3&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Same as for standard authorization code flow, &lt;strong&gt;Keycloak&lt;/strong&gt; loads an HTML form and authenticates the user, and asks for consent to grant access to the client (&lt;strong&gt;Postman&lt;/strong&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;The User authenticates the request by filling out and submitting the form.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5
&lt;/h3&gt;

&lt;p&gt;If &lt;strong&gt;Keycloak&lt;/strong&gt; approves the User, then &lt;strong&gt;Keycloak&lt;/strong&gt; redirects the web browser to a URI (&lt;code&gt;redirect_uri&lt;/code&gt;) controlled by the Client (&lt;strong&gt;Postman&lt;/strong&gt;), including an authorization code (&lt;code&gt;code&lt;/code&gt;) and the original state value as query parameters. Keycloak also stores the &lt;code&gt;code challenge&lt;/code&gt; and &lt;code&gt;code challenge method&lt;/code&gt; alongside the state parameter.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;HTTP 302&lt;br&gt;
Response Header:&lt;br&gt;
  Location: &lt;a href="https://localhost:8081/test-callback" rel="noopener noreferrer"&gt;https://localhost:8081/test-callback&lt;/a&gt;?&lt;br&gt;
            &lt;span class="nv"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;state_value&amp;amp;&lt;br&gt;
            &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cc45ea5d-a930-4950-a2c2-62a9f29acfbf.7ecefe6d-021d-4a3b-9a26-e780a6680ecf.7306139f-c07c-4adc-b175-f6c509b80964&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Step 6&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Now, &lt;strong&gt;Postman&lt;/strong&gt; calls the authorization server (&lt;strong&gt;Keycloak&lt;/strong&gt;) token endpoint to exchange the authorization code for an access token to access the &lt;strong&gt;Resource Server&lt;/strong&gt; API on the user’s behalf. It sends the authorization code and code verifier in the body of a POST request, using &lt;code&gt;application/X-WWW-form-urlencoded&lt;/code&gt; encoding with the following parameters and authorization header, which supply the client credentials (&lt;code&gt;client_id:client_secret&lt;/code&gt;) in a base64 encoding format:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;HTTP 200&lt;br&gt;
POST &lt;a href="https://KEYCLOAKDOMAIN/auth/realms/test-realm/protocol/openid-connect/token" rel="noopener noreferrer"&gt;https://KEYCLOAKDOMAIN/auth/realms/test-realm/protocol/openid-connect/token&lt;/a&gt;&lt;br&gt;
Content-Type: application/x-www-form-urlencoded&lt;br&gt;
Authorization: Basic &lt;span class="nv"&gt;dGVzdC1jbGllbnQ6aUxUTGFJelNuM3pUdVAyZHhMY2FJc3JiVldNQXZkNzg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Body:&lt;br&gt;
    grant_type: &lt;span class="s2"&gt;"authorization_code"&lt;/span&gt;&lt;br&gt;
    code: &lt;span class="s2"&gt;"cc45ea5d-a930-4950-a2c2-62a9f29acfbf.7ecefe6d-021d-4a3b-9a26-e780a6680ecf.7306139f-c07c-4adc-b175-f6c509b80964"&lt;/span&gt;&lt;br&gt;
    redirect_uri: &lt;span class="s2"&gt;"&lt;a href="https://localhost:8081/test-callback" rel="noopener noreferrer"&gt;https://localhost:8081/test-callback&lt;/a&gt;"&lt;/span&gt;&lt;br&gt;
    code_verifier: &lt;span class="s2"&gt;"tClcOwZdqiPHHuMo0CyxMked9r1NJ_5_BicA0FI1Q0E"&lt;/span&gt;&lt;br&gt;
    client_id: &lt;span class="s2"&gt;"CLIENTID"&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Step 7&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;If the authorization code is valid and has not expired, then &lt;strong&gt;Keycloak&lt;/strong&gt; will respond with the access token in an &lt;code&gt;application/json&lt;/code&gt; encoded body along with some optional details about the scope and expiry time of token.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;HTTP 200&lt;br&gt;
Content-Type: application/json&lt;/p&gt;

&lt;p&gt;Body:&lt;br&gt;
    access_token: &lt;span class="s2"&gt;"eyJh..."&lt;/span&gt;,&lt;br&gt;
    expires_in: 300,&lt;br&gt;
    refresh_expires_in: 0,&lt;br&gt;
    refresh_token: &lt;span class="s2"&gt;"eyJh..."&lt;/span&gt;,&lt;br&gt;
    token_type: &lt;span class="s2"&gt;"Bearer"&lt;/span&gt;,&lt;br&gt;
    not-before-policy: 0,&lt;br&gt;
    session_state: &lt;span class="s2"&gt;"60a62786-1bf3-4a78-b4e2-89d414ee2026"&lt;/span&gt;,&lt;br&gt;
    scope: &lt;span class="s2"&gt;"offline_access email profile"&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Step 8&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Once the &lt;strong&gt;Postman&lt;/strong&gt; has obtained an access token, it can use it to access the &lt;strong&gt;Resource Server&lt;/strong&gt; API by including it in the header of HTTP requests as &lt;code&gt;Authorization: Bearer eyJh...&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;In this blog post, we showed what the problem might be when we use Authorization code grant type, how &lt;strong&gt;OAuth 2.0 Authorization code grant with PKCE&lt;/strong&gt; works and how &lt;strong&gt;Postman&lt;/strong&gt; can do that for us.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.manning.com/books/api-security-in-action" rel="noopener noreferrer"&gt;API Security in Action book&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.appsdeveloperblog.com/keycloak-authorization-code-grant-example/" rel="noopener noreferrer"&gt;Keycloak: Authorization Code Grant Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.keycloak.org/docs/latest/authorization_services/index.html#_overview_terminology" rel="noopener noreferrer"&gt;Authorization Services Terminology&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dropbox.tech/developers/pkce--what-and-why-" rel="noopener noreferrer"&gt;PKCE: What and Why?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>oauth</category>
      <category>postman</category>
      <category>keycloak</category>
      <category>api</category>
    </item>
    <item>
      <title>OAuth 2.0 Authorization code grant with Postman, Part 1</title>
      <dc:creator>Ali Khalili</dc:creator>
      <pubDate>Mon, 14 Feb 2022 10:17:04 +0000</pubDate>
      <link>https://dev.to/oneadvanced/oauth-20-authorization-code-grant-with-postman-part-1-5238</link>
      <guid>https://dev.to/oneadvanced/oauth-20-authorization-code-grant-with-postman-part-1-5238</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;In this blog post series, we will show you how the &lt;strong&gt;OAuth 2.0 Authorization code&lt;/strong&gt; grant works underneath when using &lt;strong&gt;Keycloak&lt;/strong&gt; and &lt;strong&gt;Postman&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For the first part, we are going to be exploring how OAuth 2.0 authorization grant works, and for the subsequent part, we will show you what is the problem with authorization code flow and how we can solve this problem with &lt;strong&gt;PKCE&lt;/strong&gt; using Postman.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirement
&lt;/h2&gt;

&lt;p&gt;For the following steps in this blog post on your local machine, you need to have the &lt;strong&gt;Keycloak&lt;/strong&gt; server running, a &lt;strong&gt;Keycloak&lt;/strong&gt; realm, and at least one user created. You also need to have the &lt;strong&gt;Postman&lt;/strong&gt; on your local machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Authorization Code grant type?
&lt;/h2&gt;

&lt;p&gt;In the Authorization Code grant, the client first redirects the user’s web browser to the authorization endpoint for the authorization server. The authorization server then authenticates the user and asks for consent to grant access to the application. If approved, then the authorization server redirects the web browser to a URI controlled by the client, including an authorization code. The client can then call the authorization server token endpoint to exchange the authorization code for an access token to access the API on the user’s behalf.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Postman&lt;/strong&gt; can play the client role for us in the authorization code grant flow with no effort. We also can obtain an access token from any authorization server which supports the &lt;strong&gt;OAuth 2.0&lt;/strong&gt; standard. Here we use a &lt;strong&gt;Keycloak&lt;/strong&gt; server for playing the authorization server role.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization code flow
&lt;/h2&gt;


&lt;p&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.svc.oneadvanced.com%2Fengineering-blogs%2Foauth2-authorization-grant-with-postman%2Fauthorization_flow.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.svc.oneadvanced.com%2Fengineering-blogs%2Foauth2-authorization-grant-with-postman%2Fauthorization_flow.jpg" alt="A diagram to visualize the authorization code flow that is explained in the steps below."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;For the first step, we need to fill all needed &lt;strong&gt;OAuth 2.0&lt;/strong&gt; configuration options, then click on Get New Access Token in the &lt;strong&gt;Postman&lt;/strong&gt; Authorization tab.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auth URL: &lt;code&gt;{server}/auth/realms/{realm}/protocol/openid-connect/auth&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Access Token URL: &lt;code&gt;{server}/auth/realms/{realm}/protocol/openid-connect/token&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.svc.oneadvanced.com%2Fengineering-blogs%2Foauth2-authorization-grant-with-postman%2Fauthorization_flow_s_1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.svc.oneadvanced.com%2Fengineering-blogs%2Foauth2-authorization-grant-with-postman%2Fauthorization_flow_s_1.jpg" alt="An example of the Postman Authorization configuration options that are required in order for Postman to retrieve tokens"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Postman&lt;/strong&gt; redirects the user with its embedded browser to the &lt;strong&gt;Keycloak&lt;/strong&gt;’s auth endpoint. &lt;strong&gt;Postman&lt;/strong&gt; includes Client Id (&lt;code&gt;client_id&lt;/code&gt;) and required scope (&lt;code&gt;scope&lt;/code&gt;) in this redirect.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

HTTP 200
GET https://KEYCLOAKDOMAIN/auth/realms/test-realm/protocol/openid-connect/auth?
    &lt;span class="nv"&gt;response_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;code&amp;amp;
    &lt;span class="nv"&gt;client_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CLIENTID&amp;amp;
    &lt;span class="nv"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;state_value&amp;amp;
    &lt;span class="nv"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;offline_access&amp;amp;
    &lt;span class="nv"&gt;redirect_uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://localhost:8081/test-callback


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ The &lt;strong&gt;Keycloak&lt;/strong&gt; or any authorization server we are using would require the client’s redirect URI to be pre-registered to prevent open redirect attacks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Keycloak&lt;/strong&gt; loads an HTML form and authenticates the User and asks for consent to grant access to the client(&lt;strong&gt;Postman&lt;/strong&gt;).&lt;/p&gt;


&lt;p&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.svc.oneadvanced.com%2Fengineering-blogs%2Foauth2-authorization-grant-with-postman%2Fauthorization_flow_s_3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.svc.oneadvanced.com%2Fengineering-blogs%2Foauth2-authorization-grant-with-postman%2Fauthorization_flow_s_3.jpg" alt="An example of Keycloak login page that is asking for the username or email of the user and their password"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; 
&lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"https://KEYCLOAKDOMAIN/auth/realms/test-realm/login-actions/authenticate?session_code=o0Do5Ts1tzEp3E6FcIxO3qxJtT_PuiFNdG2fJloYfyw&amp;amp;amp;execution=8ac4f6a5-7f35-4db7-9f5b-90953e7ddebd&amp;amp;amp;client_id=test-client&amp;amp;amp;tab_id=uxX7xjpChS8"&lt;/span&gt;
&lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"id-hidden-input"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"credentialId"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"login"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Sign In"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;The User authenticates the request by filling out and submitting the form.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 5
&lt;/h3&gt;

&lt;p&gt;If &lt;strong&gt;Keycloak&lt;/strong&gt; approved the User, then &lt;strong&gt;Keycloak&lt;/strong&gt; redirects the web browser to a URI (&lt;code&gt;redirect_uri&lt;/code&gt;) controlled by the Client (&lt;strong&gt;Postman&lt;/strong&gt;), including an authorization code (&lt;code&gt;code&lt;/code&gt;) and the original state value as a query parameter.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

HTTP 302
Response Header:
  Location: https://localhost:8081/test-callback?
            &lt;span class="nv"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;state_value&amp;amp;
            &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;183c6a33-b96d-4b33-aaf0-b7e74ca13675.60d1c32a-c664-4a73-a6b2-60fcc8e43aee.7306139f-c07c-4adc-b175-f6c509b80964


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Passing authorization code in the query parameter of the redirect URL is vulnerable to being stolen by malicious scripts or leaking in the server log, browser history.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 6
&lt;/h3&gt;

&lt;p&gt;Now, &lt;strong&gt;Postman&lt;/strong&gt; calls the authorization server (&lt;strong&gt;Keycloak&lt;/strong&gt;) token endpoint to exchange the authorization code for an access token to access the &lt;strong&gt;Resource Server&lt;/strong&gt; API on the user’s behalf. It sends the authorization code in the body of a POST request, using &lt;code&gt;application/X-WWW-form-urlencoded&lt;/code&gt; encoding with the following parameters and authorization header which supply the client credentials (&lt;code&gt;client_id:client_secret&lt;/code&gt;) in a base64 encoding format:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;HTTP 200&lt;br&gt;
POST &lt;a href="https://KEYCLOAKDOMAIN/auth/realms/test-realm/protocol/openid-connect/token" rel="noopener noreferrer"&gt;https://KEYCLOAKDOMAIN/auth/realms/test-realm/protocol/openid-connect/token&lt;/a&gt;&lt;br&gt;
Content-Type: application/x-www-form-urlencoded&lt;br&gt;
Authorization: Basic &lt;span class="nv"&gt;dGVzdC1jbGllbnQ6aUxUTGFJelNuM3pUdVAyZHhMY2FJc3JiVldNQXZkNzg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Body:&lt;br&gt;
    grant_type: &lt;span class="s2"&gt;"authorization_code"&lt;/span&gt;&lt;br&gt;
    code: &lt;span class="s2"&gt;"183c6a33-b96d-4b33-aaf0-b7e74ca13675.60d1c32a-c664-4a73-a6b2-60fcc8e43aee.7306139f-c07c-4adc-b175-f6c509b80964"&lt;/span&gt;&lt;br&gt;
    redirect_uri: &lt;span class="s2"&gt;"&lt;a href="https://localhost:8081/test-callback" rel="noopener noreferrer"&gt;https://localhost:8081/test-callback&lt;/a&gt;"&lt;/span&gt;&lt;br&gt;
    client_id: &lt;span class="s2"&gt;"CLIENTID"&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Step 7&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;If the authorization code is valid and has not expired, then &lt;strong&gt;Keycloak&lt;/strong&gt; will respond with the access token in an &lt;code&gt;application/json&lt;/code&gt; encoded body along with some optional details about the scope and the expiry time of the token.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;HTTP 200&lt;br&gt;
Content-Type: application/json&lt;/p&gt;

&lt;p&gt;Body:&lt;br&gt;
    access_token: &lt;span class="s2"&gt;"eyJh..."&lt;/span&gt;,&lt;br&gt;
    expires_in: 300,&lt;br&gt;
    refresh_expires_in: 0,&lt;br&gt;
    refresh_token: &lt;span class="s2"&gt;"eyJh..."&lt;/span&gt;,&lt;br&gt;
    token_type: &lt;span class="s2"&gt;"Bearer"&lt;/span&gt;,&lt;br&gt;
    not-before-policy: 0,&lt;br&gt;
    session_state: &lt;span class="s2"&gt;"60a62786-1bf3-4a78-b4e2-89d414ee2026"&lt;/span&gt;,&lt;br&gt;
    scope: &lt;span class="s2"&gt;"offline_access email profile"&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Step 8&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Once the &lt;strong&gt;Postman&lt;/strong&gt; has obtained an access token, it can use it to access the &lt;strong&gt;Resource Server&lt;/strong&gt; API by including it in the header of HTTP requests as &lt;code&gt;Authorization: Bearer eyJh...&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;In this blog post, we showed you how OAuth 2.0 Authorization code flow works and how &lt;strong&gt;Postman&lt;/strong&gt; can do that for us.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.manning.com/books/api-security-in-action" rel="noopener noreferrer"&gt;API Security in Action book&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.appsdeveloperblog.com/keycloak-authorization-code-grant-example/" rel="noopener noreferrer"&gt;Keycloak: Authorization Code Grant Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.keycloak.org/docs/latest/authorization_services/index.html#_overview_terminology" rel="noopener noreferrer"&gt;Authorization Services Terminology&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>oauth</category>
      <category>postman</category>
      <category>keycloak</category>
      <category>api</category>
    </item>
  </channel>
</rss>
