# JWT Test Tokens

Generate JWT tokens to test your deployed APIs through Azure API Management.

[TOC]

---

## 📋 Overview

| Aspect            | Details                                                          |
| ----------------- | ---------------------------------------------------------------- |
| **Goal**          | Generate a valid JWT token for testing secured API endpoints     |
| **Prerequisites** | Personal test tools repository, Okta access, Azure DevOps access |
| **Time estimate** | ~10 minutes                                                      |
| **Difficulty**    | Beginner                                                         |

---

## 🎯 Why You Need This

When an API is deployed to Azure, API Management secures it by default. To test the deployed API with Postman, RestClient, or similar tools, you need an `Authorization` header with a valid JWT token.

**Key concepts:**

- **Scopes** - Application-level permissions allowing the app to access API functionality
- **Corporate vs External** - Forge uses dual identity providers: Entra ID (corporate) and Okta (external)
- **user-groups scope** - Special scope for user-context access in Okta (external)
- **user_impersonation scope** - Special scope for user-context access in Entra ID (corporate)

---

## 🏛️ Choosing Corporate vs External

Before generating a token, determine which identity provider and tool to use:

| If you're testing as...                      | Identity Provider      | Tool                                 |
| -------------------------------------------- | ---------------------- | ------------------------------------ |
| Internal employee                            | Microsoft Entra ID     | **SAIF CLI** (`saif auth generate`) |
| External user (policyholder, provider, etc.) | Okta (External tenant) | **Azure DevOps Pipeline**            |

> 💡 **Key Difference**: Corporate tokens use Entra ID and are generated via the SAIF CLI. External tokens use Okta and are generated via an Azure DevOps pipeline.

---

## 🔧 Prerequisites

### For Corporate (Entra ID) Tokens

- ✅ SAIF CLI installed (`saif --version` to verify)
- ✅ Know your application name (e.g., `it-api-exp-brishe-test`)

### For External (Okta) Tokens

- ✅ [Personal test tools repository](create-test-tools-repository.md) created
- ✅ Access to [Okta Apps](https://saif.okta.com/app/UserHome)
- ✅ Access to Azure DevOps pipelines
- ✅ Your project ID and scopes identified

## 🚀 Instructions

### Option A: Generate Corporate Token (Entra ID) with SAIF CLI

Use this method for testing as an **internal employee** with Entra ID authentication.

#### 1. Run the Token Generate Command

```powershell
saif auth generate --name <application-name>
```

**Example:**

```powershell
# Generate token for brishe-test application
saif auth generate --name it-api-exp-brishe-test
```

If you don't provide the `--name` parameter, the CLI will prompt you for the application name and show matching applications.

#### 2. Select Your Application

The CLI will search for applications matching your name and display a list. Select the correct application from the menu.

**Application naming pattern:** `{project-id}-{environment}`

**Examples:**

- `it-api-exp-brishe-test`
- `it-api-exp-brishe-qa`
- `it-api-exp-brishe-uat`

#### 3. Copy the Token

The token will be displayed in the console. Copy the entire token output (no additional formatting).

#### 4. Use in Testing Tools

Add the token as an `Authorization` header in your HTTP client:

```
Authorization: Bearer <token>
```

**Example in Postman:**

- Header: `Authorization`
- Value: `Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI...`

---

### Option B: Generate External Token (Okta) with Azure DevOps Pipeline

Use this method for testing as an **external user** (policyholder, provider, etc.) with Okta authentication.

#### 1. Pipeline Prerequisite

You will need to add a secret variable on your pipeline to enter your password to be used in the token generation run. This is a one-time task after creating the pipeline that needs to be performed before the first run.

1. Click **Edit**
2. Click **Variables**
3. Click the plus button to add a variable
4. The variable name should be **Password**
5. Check the checkbox **Keep this value secret**
6. Check the checkbox **Let users override this value when running the pipeline**

[This is the MS documentation for doing that](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/set-secret-variables?view=azure-devops&tabs=yaml%2Cbash)

#### 2. Finding the Auth Server ID

The Auth Server ID is printed in your API deployment pipeline outputs:

1. In Azure DevOps, navigate to your main API deployment pipeline
2. Find the most recent deployment run to the target environment (Test/QA/UAT)
3. Click the **Deploy** stage
4. Click the **Deploy auth_ext_okta_client (terraform)** job
5. Scroll to the bottom of the **Terraform Apply** step
6. Look for the **Terraform Outputs** section:

```
📄 Terraform Outputs:
====================
AuthServerAudience =
AuthServerId =
AuthServerUrl =
ClientId =
ClientSecret =
OpenIdConnectClientId =
OpenIdConnectClientSecret =
TenantOrigin =
====================
```

7. Copy the **AuthServerId** value

#### 3. Generating a Token

1. In Azure DevOps, run the **it-test-tools-[username]-gen-np-jwt** pipeline in your personal test tools repository
2. In the parameters dialog pane that appears, enter the following (see table below for examples):
   - Project ID
   - Scopes (YAML array)
   - Auth Server ID
   - Okta Org: Select **External**
   - ExternalUsername (your external user email)
3. Click **Variables**
4. Click **Password**
5. Enter your AD password into the **Value** text box and click the **Update** button
6. Click run
7. Once the pipeline completes, navigate to the run summary
8. In the summary details, under the **Related** column, click the **1 published; 1 consumed** link, this will navigate you to the artifacts page for the pipeline run
9. Expand the **JWT** list item
10. Click **token.txt** to download a text file containing the JWT
11. Copy/paste this into your testing tool as an **Authorization** request header, format: `Authorization|Bearer [JWT]`

---

## 📝 Example Parameters (External Tokens Only)

### Pipeline Parameter - External Example

| Parameter        | Example              |
| ---------------- | -------------------- |
| Project ID       | it-api-sys-envsvc    |
| Scopes           | - read<br>- write    |
| Auth Server ID   | aushpkatj89kOhK6Y1d7 |
| Okta Org         | External             |
| ExternalUserName | wilbon@lincoln.com   |

---

## ✅ Verify It Worked

Confirm your token is valid:

1. **Decode the token** - Run `saif auth validate` and paste the token when prompted, or use [jwt.io](https://jwt.io) to inspect the payload
2. **Check scopes** - Verify your requested scopes appear in the token
3. **Test the API** - Make a request to your API with the token

```powershell
# Run without arguments and paste the token when prompted (recommended)
saif auth validate
```

**Success indicator:** API returns data instead of 401 Unauthorized.

---

## 🔍 Troubleshooting

### Word-wrapped tokens

Terminals interpret pasted newlines as command separators. If you paste a word-wrapped JWT directly on the command line (e.g. `saif auth validate <paste>`), each wrapped line is treated as a separate command, causing errors like `'tOWM5...' is not recognized as a cmdlet`.

**Workarounds:**

- **Use interactive mode (recommended):** run `saif auth validate` with no arguments, then paste when prompted.
- **Widen your terminal:** make the terminal window wider than the token length before pasting so no wrapping occurs.
- **Store in a variable first (PowerShell):**

    ```powershell
    $token = "eyJ0eXAiOiJKV1Qi..."
    saif auth validate $token
    ```

### Token generation fails with authentication error

**Cause:** Password variable not configured or expired.

**Solution:** Reconfigure the Password variable in the pipeline (see Pipeline Prerequisite section).

### Token rejected with "invalid_token" error

**Cause:** Token may be expired or scopes don't match API requirements.

**Solution:** Generate a new token and verify the scopes match what the API expects.

### Cannot find Auth Server ID in Terraform Cloud

**Cause:** Okta workspace may not exist for this project.

**Solution:** Verify the Okta infrastructure is deployed. Check with your platform team if needed.

### Token works for some users but not others

**Cause:** Using wrong tenant (Corp vs External) for the user type.

**Solution:**

- Internal employees should use **Corp** tenant
- External users (policyholders, providers) should use **External** tenant
- Verify the user exists in the correct identity provider

### Need to test with Entra ID token (corporate)

**Cause:** Using the wrong token generation method.

**Solution:** For corporate/Entra ID tokens, use the SAIF CLI:

```powershell
saif auth generate --name <application-name>
```

See [Option A: Generate Corporate Token](#option-a-generate-corporate-token-entra-id-with-saif-cli) above for detailed instructions.

### SAIF CLI not installed

**Cause:** SAIF CLI not installed.

**Solution:**

1. Install SAIF CLI: `dotnet tool install -g SAIF.Platform.CLI`
2. Verify SAIF CLI is working: `saif --version`

> 💡 **Note**: The SAIF CLI handles authentication on your behalf—no separate Azure login required.

---

## 🚀 Next Steps

| Task                           | Guide                                                           |
| ------------------------------ | --------------------------------------------------------------- |
| Set up a test tools repository | [Test Tools Repository](create-test-tools-repository.md)        |
| Manage test users              | [External Test Users](manage-external-test-users.md)            |
| Learn about security           | [Security Overview](../index.md)                                |
