Overview
In this blog post series, we will show you how the OAuth 2.0 Authorization code grant works underneath when using Keycloak and Postman.
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 PKCE using Postman.
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.
What is the Authorization Code grant type?
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.
Postman 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 OAuth 2.0 standard. Here we use a Keycloak server for playing the authorization server role.
Authorization code flow
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
Step 2
Postman redirects the user with its embedded browser to the Keycloak’s auth endpoint. Postman includes Client Id (client_id
) and required scope (scope
) in this redirect.
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
ℹ️ The Keycloak or any authorization server we are using would require the client’s redirect URI to be pre-registered to prevent open redirect attacks.
Step 3
Keycloak loads an HTML form and authenticates the User and asks for consent to grant access to the client(Postman).
<form
action="https://KEYCLOAKDOMAIN/auth/realms/test-realm/login-actions/authenticate?session_code=o0Do5Ts1tzEp3E6FcIxO3qxJtT_PuiFNdG2fJloYfyw&execution=8ac4f6a5-7f35-4db7-9f5b-90953e7ddebd&client_id=test-client&tab_id=uxX7xjpChS8"
method="post">
<input name="username" type="text"/>
<input name="password" type="password"/>
<input type="hidden" id="id-hidden-input" name="credentialId" />
<input name="login" value="Sign In"/>
</form>
Step 4
The User authenticates the request by filling out and submitting the form.
Step 5
If Keycloak approved 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 a query parameter.
HTTP 302
Response Header:
Location: https://localhost:8081/test-callback?
state=state_value&
code=183c6a33-b96d-4b33-aaf0-b7e74ca13675.60d1c32a-c664-4a73-a6b2-60fcc8e43aee.7306139f-c07c-4adc-b175-f6c509b80964
⚠️ 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.
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 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: "183c6a33-b96d-4b33-aaf0-b7e74ca13675.60d1c32a-c664-4a73-a6b2-60fcc8e43aee.7306139f-c07c-4adc-b175-f6c509b80964"
redirect_uri: "https://localhost:8081/test-callback"
client_id: "CLIENTID"
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 the expiry time of the 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"
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 you how OAuth 2.0 Authorization code flow works and how Postman can do that for us.
Top comments (2)
Amazing post !!
I have learned OAuth 2.0 and keyclock bit and I liked you explained in step wise.