OAuth 2.0 Authorization code grant with Postman, Part 2

alikhalili

Ali Khalili

Posted on February 14, 2022

OAuth 2.0 Authorization code grant with Postman, Part 2

Overview

In the first part, we have shown how the OAuth 2.0 Authorization code grant works when using Keycloak and Postman. Authorization code flow is the most common secure OAuth 2.0 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.

Requirement

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

Securing code exchange with PKCE

Given the above issues, OAuth 2.0 provides a more secure authorization flow to a better secure mobile apps or other types of public clients.
From the RFC 7636: Proof Key for Code Exchange:

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

The way PKCE, 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 code verifier. 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 code verifier to create a code challenge using the SHA-256 hash function. Then the client adds the code challenge as part of the authorization request using the following additional parameters:



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".


Enter fullscreen mode Exit fullscreen mode

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

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 code verifier.

Authorization code flow with PKCE


A diagram to visualize the authorization code flow with PKCE that is explained in the steps below.

Step 1

For the first step, we need to fill all needed OAuth 2.0 configuration options, then click on Get New Access Token in the Postman Authorization tab.

  • Auth URL: {server}/auth/realms/{realm}/protocol/openid-connect/auth
  • Access Token URL: {server}/auth/realms/{realm}/protocol/openid-connect/token

    An example of the Postman Authorization configuration options that are required in order for Postman to retrieve tokens.

Step 2

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



HTTP 200
GET https://KEYCLOAKDOMAIN/auth/realms/test-realm/protocol/openid-connect/auth?
response_type=code&
client_id=CLIENTID&
state=state_value&
scope=offline_access&
redirect_uri=https://localhost:8081/test-callback&
code_challenge=Q0J7-pF3nmAP3XrTmUt6DEFL9vKG9_1V12fXXMTVIqk&
code_challenge_method=S256

Enter fullscreen mode Exit fullscreen mode




Step 3

Same as for standard authorization code flow, Keycloak loads an HTML form and authenticates the user, and asks for consent to grant access to the client (Postman).

Step 4

The User authenticates the request by filling out and submitting the form.

Step 5

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



HTTP 302
Response Header:
Location: https://localhost:8081/test-callback?
state=state_value&
code=cc45ea5d-a930-4950-a2c2-62a9f29acfbf.7ecefe6d-021d-4a3b-9a26-e780a6680ecf.7306139f-c07c-4adc-b175-f6c509b80964

Enter fullscreen mode Exit fullscreen mode




Step 6

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



HTTP 200
POST https://KEYCLOAKDOMAIN/auth/realms/test-realm/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic dGVzdC1jbGllbnQ6aUxUTGFJelNuM3pUdVAyZHhMY2FJc3JiVldNQXZkNzg=

Body:
grant_type: "authorization_code"
code: "cc45ea5d-a930-4950-a2c2-62a9f29acfbf.7ecefe6d-021d-4a3b-9a26-e780a6680ecf.7306139f-c07c-4adc-b175-f6c509b80964"
redirect_uri: "https://localhost:8081/test-callback"
code_verifier: "tClcOwZdqiPHHuMo0CyxMked9r1NJ_5_BicA0FI1Q0E"
client_id: "CLIENTID"

Enter fullscreen mode Exit fullscreen mode




Step 7

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



HTTP 200
Content-Type: application/json

Body:
access_token: "eyJh...",
expires_in: 300,
refresh_expires_in: 0,
refresh_token: "eyJh...",
token_type: "Bearer",
not-before-policy: 0,
session_state: "60a62786-1bf3-4a78-b4e2-89d414ee2026",
scope: "offline_access email profile"

Enter fullscreen mode Exit fullscreen mode




Step 8

Once the Postman has obtained an access token, it can use it to access the Resource Server API by including it in the header of HTTP requests as Authorization: Bearer eyJh....

Wrap-up

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

References

💖 💪 🙅 🚩
alikhalili
Ali Khalili

Posted on February 14, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related