Using Postman Automation to Test API Endpoints Protected by Okta’s PKCE Flow
Tags: productivity, tutorial, postman, okta
Published: 2021-06-01 15:03:43

[Postman](https://www.postman.com/) is a great tool for testing our APIs and streamlining backend development. One of the big hurdles, however, is testing API endpoints that are protected. There are some imperfect workarounds that require us to manually enter our credentials each time we need to retrieve an access token. But through painstaking trial and error, I’ve put together a solution to automate the Postman login process with the click of a button! In this blog, I will go over step-by-step how you can create the same automated Postman login setup. The following requests are based on [the Okta platform](https://developer.okta.com/) and Okta’s [authorization code flow with PKCE documentation](https://developer.okta.com/docs/guides/implement-auth-code-pkce/overview/).

**<span style="text-decoration:underline;">
Collection and Environment Variables Setup</span>**

1. Create a [collection](https://learning.postman.com/docs/getting-started/creating-the-first-collection/#:~:text=your%20first%20collection-,Postman%20Collections%20are%20a%20group%20of,you%20can%20organize%20into%20folders.&text=However%2C%20as%20your%20Postman%20usage,a%20group%20for%20easier%20access.) under _Collections > + > Create New Collection_. We’ll name this collection “Okta Login,” but this can be named anything you like. The collection will allow us to use [runners](https://learning.postman.com/docs/running-collections/intro-to-collection-runs/) to run all our requests at once.

2. Setup our [environment variables](https://learning.postman.com/docs/sending-requests/managing-environments/) based on [Okta’s authorization code flow docs](https://developer.okta.com/docs/guides/implement-auth-code/use-flow/). 

![Postman Environment Variables Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xf2yk4g7bsh5ja6kmk5o.png)

- The _email_ and _password_ are the user credentials.
- The _oktaUrl_ (Okta domain) and _oktaClientId_ (Client ID) can be found within the general settings of your Okta app.
- The _redirectUri_ must match one of the URIs that you have approved for your Okta application. These [redirect URI](https://developer.okta.com/docs/guides/implement-auth-code/use-flow/) value(s) can be found under the _Login redirect URIs_ field in your Okta _Applications_ settings (screenshot below). If your application doesn’t already have a redirect URI, you can set it up with a http:<nolink>//localhost:3000. As part of the authorization code flow, users are redirected back to your client application via the redirectUri after logging in with Okta. In our case, we won’t be redirecting anywhere, but the redirectUri is required as a parameter of the request. 

![Okta App Settings Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jtegvz0xvyo175zihinp.png)

- The _codeChallenge_ and _codeVerifier_ values can be generated here: [https://tonyxu-io.github.io/pkce-generator/](https://tonyxu-io.github.io/pkce-generator/). The code challenge and code verifier values are used in the [Proof Key of Code Exchange (PKCE)](https://www.loginradius.com/blog/async/pkce/#:~:text=PKCE%20is%20mainly%20useful%20for,Code%20Verifier%20and%20Code%20challenge.) flow. You can find more details on Okta’s implementation [here](https://developer.okta.com/docs/guides/implement-auth-code-pkce/use-flow/).
- The _authServer_ is set as `default` unless you have created a custom auth server.
- The _sessionToken_, _authorizationCode_, and _accessToken_ can be left blank, as we will programatically fill in these values from our requests.

We will tidy things up by using [Postman variables](https://learning.postman.com/docs/sending-requests/variables/). We can access these environment variables by adding two curly braces around our environment variable name. For example, instead of typing “http<nolink>://localhost:3000,” we can just use `{{redirectUri}}`. This helps keep our variables consistent and easily managed/updated.
 

**<span style="text-decoration:underline;">Creating Requests</span>**


1.First, we will create a POST request to your Okta domain + `/api/v1/authn`. Since we have this value set in our environment variable, we can just use `{{oktaUrl}}/api/v1/authn` in the URL. In the JSON body of the request, we will send our username and password.

![Auth Flow Step 1 Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h79i4ch4cdbo5l0j3hrt.png)

This is the authentication piece of the flow. Okta will return all the user info, including the session token. Since we want to automate this process, we will create a script so that this session token is saved into an environment variable. We can add scripts within the _[Tests](https://learning.postman.com/docs/writing-scripts/test-scripts/)_ section. Add the script below to the _Tests_ section of this first request.

```js
const response = JSON.parse(responseBody);

pm.environment.set("sessionToken", response.sessionToken);

pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

pm.test("Response returns a session token", function () {
    pm.expect(response).to.have.property("sessionToken");
});
```

2.Next, create a GET request to `{{oktaUrl}}/oauth2/default/v1/authorize`. We will need to exchange that session token for an authorization code, which will involve sending a few values as query parameters:
  - client_id=`{{oktaClientId}}`
  - scope=openid
  - redirect_uri=`{{redirectUri}}`
  - response_type=code
  - state=state
  - sessionToken=`{{sessionToken}}`
  - code_challenge=`{{codeChallenge}}`


For more details on what the parameters are used for, you can check out the docs [here](https://developer.okta.com/docs/guides/implement-auth-code/use-flow/).

![Auth Flow Step 2 Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n6y1cwqsnpqhgg1tpqwb.png)

We will save the authorization code from Okta's response to this request as an environment variable. Add the following script to the _tests_ section of this second request:

```js
const responseUrl = postman.getResponseHeader("Location");
const authorizationCode = responseUrl ? responseUrl.match(/code=([^&]*)/)[1] : null;

pm.environment.set("authorizationCode", authorizationCode);

pm.test("Status code is 302", function () {
    pm.response.to.have.status(302);
})

pm.test("Response returns an authorization code", function () {
    pm.expect(authorizationCode).not.equal(null);
});
```

3.Last, we will create a POST request to `{{oktaUrl}}/oauth2/{{authServer}}/v1/token?state=state` to exchange the authorization code for our access token. We will need to send this in a `x-www-form-urlencoded` format with the following query parameters:
  - grant_type=authorization_code
  - redirect_uri=`{{redirectUri}}`
  - code=`{{authorizationCode}}`
  - code_verifier=`{{codeVerifier}}`
  - client_id=`{{oktaClientId}}`

![Auth Flow Step 3 Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rgbsbhebkhx82jk6ohwz.png)

We will finally save the access token that we need from Okta's response to this request as an environment variable. Add the the following script to the _tests_ section of this third request:

```js
const response = JSON.parse(responseBody);

pm.environment.set("accessToken", response.access_token);

pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});
  
pm.test("Response returns an access token", function () {
    pm.expect(response).to.have.property("access_token");
});
```

**<span style="text-decoration:underline;">Running Our Collection and Final Setup</span>**

Now that we have everything setup, we can simply run our collection using Postman runners. To do this, double click on the _Okta Login_ collection. You will see the _Run_ button, which opens up the _Runner_ tab.

![Okta Login Collection Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8hkr1iv3kclvdzebo1sa.png)

We then can click on _Run Okta Login_ and voila! We have our access token saved in our environment variables, and we can now use it to hit protected endpoints on our server.

![Postman Runner](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/na1gxyo5rztqyybd6vcv.png)


**<span style="text-decoration:underline;">Access Token Usage</span>**

Accessing our protected routes is possible now that we have our access token. In the authorization tab of your request, select _Bearer Token_ from the drop-down menu. Add `{{accessToken}}` as the value for _Token_ and presto… we can now make API requests as if we were logged in as a user!

![Access Token Usage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pku5ixlu51fe92r2t1dv.png)

**<span style="text-decoration:underline;">Conclusion</span>**

Using Postman collection runners to get our Okta access token makes API testing and backend development much more streamlined. Since we can programmatically get our access token, this collection can also be useful in creating full regression tests to ensure that all endpoints (including the protected ones) are working as expected. This setup can also be tweaked to be used with other identity providers that utilize the authorization code flow, such as Auth0, AWS Cognito, etc. If you have any questions or improvements, let me know in the comments below!