# Authentication Profiles: Choose and Configure a Method

> Most APIs refuse a request that does not prove who is calling. In Shift-Left Studio you describe how to prove it once, in an authentication profile, and every test, pack, workflow and performance run in the project uses it.

Source: https://totalshiftleft.ai/help-center/product-documentation/authentication-profiles-and-methods

> **Applies to:** All editions (Free: up to 3 profiles per project; Professional, Trial and Enterprise: unlimited) · Web app and Desktop app · Access to the project's settings

## Overview

Most APIs refuse a request that does not prove who is calling. In Shift-Left Studio you describe how to prove it once, in an **authentication profile**, and every test, pack, workflow and performance run in the project uses it. You never paste a token into individual tests.

A profile holds one authentication method (API key, Basic, OAuth 2.0, AWS Signature v4 and so on), its settings, and its secrets. You tie a profile to an environment, so the same tests send staging credentials to staging and production credentials to production.

This article explains how to create a profile, how Studio decides which profile a run uses, and what every method's fields mean. Two methods have their own articles because they involve signing in: [OAuth 2.0 Sign-In](/help-center/product-documentation/oauth-2-interactive-sign-in) and [Sign In With Steps](/help-center/product-documentation/sign-in-with-steps).

## Key concepts

| Term | Meaning |
|---|---|
| Authentication profile | A named, reusable set of credentials for one project. |
| Method | How the credential is sent: a header, a query parameter, a signature, a client certificate, or a token that Studio obtains for you. |
| Environment | The environment a profile belongs to (set in the profile's **Settings** step). |
| Active | The profile that owns an environment. Only one profile per environment is active at a time. |
| Default profile | The fallback used when no profile is active for the environment. It is also pre-selected for new test cases. |
| Additional Headers | Extra headers the profile sends along with its credential. |

## Before you begin

- Open the project and go to **Project Settings**, then the **Authentication Profiles** tab.
- Have the credentials from the API's owner: key names, URLs, client IDs, and the secret values.
- On the Free edition, a project can hold up to 3 profiles. The **New Profile** button is disabled when you reach the limit.
- If you want tests to read secrets from HashiCorp Vault, AWS Secrets Manager or Azure Key Vault, an administrator must connect one first (see [Keep secrets in a secret manager](#keep-secrets-in-a-secret-manager)).

## Step 1 — Start a new profile

1. On the **Authentication Profiles** tab, click **New Profile** (or **Create Profile** if the project has none yet).
2. In **Basic Info**, enter a **Profile Name**, for example `Orders API – Staging`.
3. Optionally add a **Description** and **Tags**. Press Enter after each tag.
4. Click **Next**.

## Step 2 — Choose and configure the method

1. In the **Authentication** step, select a card under **Authentication Method**.
2. Fill in the fields under **Configuration**. The [method reference](#method-reference) below explains each one.
3. Optional: click **Load Sample Configuration** to see a filled-in example, then replace the values with your own.
4. Optional: under **Additional Headers**, click **+ Add Header** to send extra headers with every request, such as `X-Tenant-Id`. Headers set on an individual test override these.
5. Click **Next**.

> **Tip:** Secret fields are masked. Use the eye icon to check what you typed before you save.

## Step 3 — Tie the profile to an environment

1. In the **Settings** step, choose the **Environment** this profile is for.
2. Select **Set as default profile** if this profile should be the project's fallback and be pre-selected for new test cases. A default profile is always active for all environments.
3. Leave **Profile is active** selected so the profile can be used.
4. Click **Next**.

## Step 4 — Test and save

1. In **Test & Save**, check the **Configuration Summary**.
2. Optional: enter a **Test Endpoint (Optional)** such as `/api/health`. If you leave it empty, Studio tries common endpoints on its own.
3. Click **Test Authentication** and read the result.
4. Click **Save Profile**.

You can test a saved profile at any time: on its card, click the **Test Profile** icon, enter a **Test URL**, and click **Run Test**. A result of **Authentication test successful** means the API answered with a 2xx or 3xx status. **Authentication test failed: the API answered 401** means the request went out but the API refused the credential.

## Step 5 — Make the profile the one a run uses

On each profile card you can **Edit Profile**, **Test Profile**, see **Usage**, **Duplicate**, **Activate** or **Deactivate**, and **Delete Profile**. The status badge reads **Default**, **Active** or **Inactive** for the project's current environment.

When a test runs, Studio picks the profile in this order and writes its choice to the run log (for example, "Using active profile for Staging: Orders API – Staging (oauth2)"):

| Order | Source | How you set it |
|---|---|---|
| 1 | The profile chosen on the test itself | Test editor, **Authentication Profile** section |
| 2 | The profile active for the run's environment | **Activate** on the profile card |
| 3 | The most recently updated profile whose environment matches | The profile's **Environment** setting |
| 4 | The default profile | **Set as default profile** |
| 5 | No profile | The test's own settings only |

A test set to **No Profile** ("Use individual test settings only") skips profiles entirely.

## Method reference

Each method below lists its fields as they appear in the dialog, and where Studio places the credential on the request. Methods marked "signed at send time" are computed over the final URL and body, just before the request leaves.

### No Authentication

Sends nothing. Use it to switch a project or environment off authentication on purpose.

### API Key

| Field | What to enter |
|---|---|
| **Key Name** | The header or parameter name, for example `X-API-Key`. |
| **Key Value** | The key. Encrypted. |
| **Location** | **Header** or **Query Parameter**. |

Sent as a header, or appended to the query string when the request is sent. Example: Key Name `X-API-Key`, Location **Header**, value `ak_live_...` → `X-API-Key: ak_live_...`.

### API Key + Bearer Token

For APIs that exchange a key for a short-lived token. Choose a **Token Source**:

- **Use Bearer Token directly**: paste a **Bearer Token** and choose **Bearer Prefix**.
- **Fetch token from URL**: Studio sends the key to the **Token Endpoint** and uses the token it returns.

| Field | What to enter |
|---|---|
| **API Key Name** | Header or query parameter name for the key on the token request. |
| **API Key** | The key. Encrypted. |
| **API Key Location** | **Header** or **Query Parameter**. |
| **Token Endpoint** | The URL that returns the token. |
| **Token Expiry (seconds)** | Used when the response does not state an expiry. Default 60. |
| **Refresh (sec)** | Fetch a new token this many seconds before expiry. Default 10. |
| **Bearer Prefix** | **Yes (add "Bearer " prefix)** or **No (just the token)**. |

The token goes in the `Authorization` header. Studio reads `access_token` (or `token.access_token`) and common expiry fields from the response.

### Basic Authentication

**Username** and **Password** (encrypted). Sent as `Authorization: Basic <base64 of username:password>`.

### Bearer Token

Choose a **Token Source**:

- **Use Bearer Token directly**: paste the **Bearer Token**. It is sent as `Authorization: Bearer <token>` and is never renewed.
- **Fetch token from URL**: Studio calls a token URL and caches the result.

| Field (Fetch token from URL) | What to enter |
|---|---|
| **Token URL** | The URL that returns a token. |
| **HTTP Method** | **GET** (default) or **POST**. |
| **Request Headers (JSON)** | Headers for the token request. |
| **Query Parameters (JSON)** | Query parameters for the token request. |
| **Request Body (JSON)** | Body for a POST, for example your login fields. |
| **Token JSON Path (Optional)** | Where the token is, for example `token.access_token`. |
| **Expiry JSON Path (Optional)** | Where the expiry is, for example `expires_in`. |

> **Important:** The token request's headers and body are not treated as secret fields. Do not type a password into **Request Body (JSON)**. Use a project variable or a secret reference instead, or choose a method that stores the password encrypted, such as [Sign In With Steps](/help-center/product-documentation/sign-in-with-steps).

### OAuth 2.0

Choose an **OAuth Flow**: **Authorization Code (sign in with browser)**, **Client Credentials (app only, no user)**, **Device Code (sign in with a code)**, **Password Grant (username + password)**, or **Implicit (legacy — paste a token)**. The fields change with the flow.

| Field | Used by | What to enter |
|---|---|---|
| **Client ID** | All flows | Issued by your identity provider. |
| **Client Secret** | Required for Client Credentials; optional otherwise | Encrypted. Leave blank for a public (PKCE) client. |
| **Token URL** | All except Implicit | The provider's token endpoint. |
| **Authorization URL** | Authorization Code | The provider's sign-in page. |
| **Device Authorization URL** | Device Code | The provider's device-code endpoint. |
| **Username** / **Password** | Password Grant | The resource owner. Password encrypted. |
| **Client Authentication** | All except Implicit | **Send as Basic Auth header** or **Send as request body**. |
| **Scopes** | All | Space-separated. Add `offline_access` to get a refresh token. |
| **Additional Authorization Parameters (JSON)** | Authorization Code | Extra sign-in parameters, for example `{"prompt": "select_account"}`. |
| **Additional Token Request Headers (JSON)** / **Additional Token Request Body (JSON)** | All except Implicit | Provider-specific extras, such as `audience`. |
| **Token Revocation URL** | Authorization Code, Device Code | Revokes the refresh token when you sign out. |
| **Access Token** | All | Optional pasted token. It expires and is never renewed. |

The token is sent as `Authorization: Bearer <token>`. Client Credentials and Password Grant fetch tokens on their own and cache them until they expire. Authorization Code and Device Code need one sign-in; see [OAuth 2.0 Sign-In](/help-center/product-documentation/oauth-2-interactive-sign-in). **Fill in for a provider (optional)** pre-fills the URLs for Microsoft Entra ID, Okta, Auth0, Keycloak and Google.

### OAuth 1.0a

**Consumer Key**, **Consumer Secret**, **Token**, **Token Secret** (secrets encrypted) and **Signature Method** (**HMAC-SHA1**, **HMAC-SHA256** or **PLAINTEXT**). Signed at send time into the `Authorization` header.

### AWS Signature v4

| Field | What to enter |
|---|---|
| **Access Key ID** | For example `AKIA...`. |
| **Secret Access Key** | Encrypted. |
| **AWS Region** | For example `us-east-1`. |
| **AWS Service** | For example `execute-api`, `s3`. |
| **Session Token (Optional)** | For temporary credentials. Encrypted. |

Signed at send time over the exact URL and body. A SOAP request cannot be signed with AWS Signature v4, because the envelope is built after authentication is applied; the run log warns you and the request is sent unsigned.

### Custom Header

**Header Name** and **Header Value** (encrypted). Sends one fixed header, for example `X-Auth-Token: ...`.

### Query Parameter

**Parameter Name** and **Parameter Value** (encrypted). Appended to every request URL when it is sent, for example `?api_key=...`.

### Mutual TLS (mTLS)

Paste the **Client Certificate (PEM)** and **Private Key (PEM)**. The private key is encrypted and never sent back to the browser. The server, or the local runner (Agent), presents the certificate when a test runs, over HTTPS only. A plain HTTP request is sent without it, and the run log says so.

### Hawk Authentication

**Hawk ID**, **Hawk Key** (encrypted) and **Algorithm** (**SHA-256** or **SHA-1**). Signed at send time into the `Authorization` header.

### JWT Authentication

Paste the **JWT Token** (encrypted). Sent as `Authorization: JWT <token>`. A pasted token expires; if your provider issues JWTs through OAuth 2.0, use OAuth 2.0 so the token renews itself.

### Cookie / Session

Paste a **Cookie Header**, for example `AppServiceAuthSession=...` copied from your browser's developer tools. Encrypted. Sent as the `Cookie` header. It stops working when the real session ends.

### Cookie Login Flow

Studio calls a login endpoint, captures the cookies it sets, and reuses them.

| Field | What to enter |
|---|---|
| **Login URL** | The login endpoint. |
| **Login HTTP Method** | **POST** (default), **GET** or **PUT**. |
| **Login Request Headers (JSON)** | Headers for the login call. Not encrypted, so avoid putting secrets here. |
| **Login Request Body (JSON)** | For example `{"username": "user", "password": "{{PASSWORD}}"}`. Encrypted. |
| **Follow Login Redirects** | Follow 3xx redirects and collect cookies across them. |
| **Session Cache TTL (seconds)** | How long to reuse the session. Default 900. |
| **CSRF Token Source**, **CSRF Token Path**, **CSRF Header to Send** | If the API needs an anti-CSRF token, where to read it and which header to echo it on. |

### Sign in with steps

For APIs that sign in with several calls, such as a login followed by a one-time code. See [Sign In With Steps](/help-center/product-documentation/sign-in-with-steps).

### Digest Authentication

Listed as **Digest Authentication (not supported on runs yet)**. Digest needs a challenge-and-retry exchange that runs do not perform, so requests are sent without it. Use Basic or a custom header if your API accepts one.

## Keep secrets safe

- Every secret field (passwords, client secrets, keys, tokens, the mTLS private key, pasted cookies) is encrypted at rest.
- Tokens that Studio obtains by signing in stay on the server. They are never shown in the browser.
- When a test runs on the local runner (Agent), the Agent receives what it needs for that run. For a signed-in profile it receives a live access token only, never the refresh token.
- The Project Assistant never accepts a secret typed into chat (see below).

### Keep secrets in a secret manager

On the Trial and Enterprise editions, an administrator can connect HashiCorp Vault, AWS Secrets Manager or Azure Key Vault under **Settings** → **Integrations** → **Secret Managers**, then turn on **Enable Secret Managers**. Secret managers are off until an administrator turns them on. You can then put a reference such as `secretref://<providerId>/<path>#<field>` in a test's headers, query parameters or body, or in an OAuth 2.0 profile field, instead of the secret itself. Studio resolves it in memory just before the request is sent.

## Use profiles in tests, packs, workflows and performance runs

- **Tests:** in the test editor, the **Authentication Profile** section lets you pick a profile, **No Profile**, or let the environment decide. **Advanced: Override with custom authentication** replaces the profile for that test only.
- **Packs:** in the pack wizard's execution preferences, turn on **Override** and choose an **Authentication Profile** for every test in the pack, or click **Auto-pick default**.
- **Workflows:** authentication is not chosen at pack level. Each Test node uses its own project's profile for the run's environment, then that project's default.
- **Performance runs:** requests are built with the same authentication as functional runs, and signed-in profiles keep a valid token during long runs. A signed request (AWS Signature v4, OAuth 1.0a, Hawk) is computed once, not per request, and a scenario that uses a client certificate runs from the server only. See [Performance Testing](/help-center/product-documentation/performance-testing-overview).

## Configure it with the Project Assistant

You can ask the Project Assistant to set up a profile, for example "Set up OAuth 2.0 client credentials for staging with token URL https://login.example.com/token and scope orders.read". It fills in the method's settings (URLs, client ID, scopes, header names, region) and can start a browser or device sign-in. It refuses to take a secret in chat, by name, because a secret typed into a conversation stays in the transcript. Instead it opens the **Authentication** screen with the missing field marked so you can paste the secret there.

## Troubleshooting

| Symptom | Why it happens | What to do |
|---|---|---|
| Every test fails with 401 | The profile was not applied, or its credential is wrong or expired. | Open a failed run's log and find the "Using profile…" line. If none is there, activate a profile for that environment or set a default. Then use **Test Profile** against a known endpoint. |
| 401 only in one environment | A different profile is active there. | Check the badge on each card for that environment and **Activate** the right one. |
| 403 with an HTML page in the response | A gateway or sign-in page answered, not the API. | Check the environment's base URL and any network allow-list. Run analysis labels this as an environment issue. |
| "Assigned auth profile '…' does not exist" | The test points at a deleted profile. | Choose another profile in the test's **Authentication Profile** section. |
| "…is not available in this project" | The assigned profile is disabled or belongs to another project. | Activate it, or pick a profile from this project. |
| Test passes, runs fail with "Sign-in expired" | The OAuth 2.0 or step sign-in expired or was revoked. | Open the profile and sign in again. |
| AWS-signed SOAP calls are refused | SOAP cannot be SigV4-signed. | Use another method for that service. |
| mTLS certificate not presented | The request used plain HTTP. | Use an `https://` base URL. |
| Digest-protected API returns 401 | Digest is not supported yet. | Use Basic or a custom header if the API allows. |

## Best practices

- Create one profile per environment and **Activate** it, rather than editing one profile back and forth.
- Use a dedicated test account for credentials, never a person's own account.
- Prefer methods that renew themselves (OAuth 2.0, Sign in with steps, token URLs) over pasted tokens.
- Name profiles after the API and environment so the run log is easy to read.
- Check **Usage** before deleting or changing a profile.

## FAQ

**Can one test use a different profile from the rest of the project?**
Yes. Choose it in the test's **Authentication Profile** section. That choice wins over environment and default profiles.

**Why can't I deactivate a profile?**
The project's default profile cannot be deactivated. Make another profile the default first.

**Does duplicating a signed-in profile copy the sign-in?**
No. A duplicate must be signed in on its own.

**Are secrets visible to other project members?**
Secret fields are stored encrypted and shown masked. Anyone who can edit the profile can replace them.

## Related articles

- [Project Settings: Environments and Auth](/help-center/product-documentation/project-settings)
- [OAuth 2.0 Sign-In: Browser and Device Code](/help-center/product-documentation/oauth-2-interactive-sign-in)
- [Sign In With Steps](/help-center/product-documentation/sign-in-with-steps)
- [Test Run](/help-center/product-documentation/test-run)
- [Project Assistant Overview](/help-center/product-documentation/project-assistant-overview)
- [Performance Testing](/help-center/product-documentation/performance-testing-overview)

## For administrators (self-hosted installations)

| Setting | Default | What switching it does |
|---|---|---|
| `SECRET_MANAGERS_ENABLED` | off | Fallback for the **Enable Secret Managers** switch when it has not been set on the screen. |
| `OAUTH_TOKEN_CACHE_ENABLED` | on | `false` fetches a new OAuth 2.0 token for every request instead of caching it. |

