> ## Documentation Index
> Fetch the complete documentation index at: https://portkey-docs-docs-prisma-airs-updates.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Authorise Admin API requests with a Strata Cloud Manager access token issued to a service account

Admin API requests are authorised with a short-lived access token issued by Strata Cloud Manager, not with an AI Gateway API key.

<Warning>
  A gateway API key, the key you send as `Authorization: Bearer $API_KEY` on inference requests, is **not** accepted on any Admin API endpoint. See [Inference API authentication](/aigw/api-reference/inference-api/authentication) for the inference path.
</Warning>

You obtain an Admin API token by authenticating a **service account** against the Palo Alto Networks authentication service. The token carries the ID of the tenant service group (TSG) it was scoped to, and every request made with it is routed to that tenant.

```mermaid theme={"system"}
sequenceDiagram
    participant SCM as Strata Cloud Manager
    participant App as Your job
    participant Auth as Auth service
    participant API as Admin API

    SCM-->>App: Client ID, Secret, TSG ID
    App->>Auth: POST /oauth2/access_token
    Auth-->>App: access_token, expires_in 900

    loop Within 15 minutes
        App->>API: Authorization: Bearer
        API-->>App: One tenant's resources
    end
```

## What you need

Before you can request a token, three values must exist. All three come from Strata Cloud Manager.

| Value         | What it identifies                                                                    | Where it comes from                              |
| :------------ | :------------------------------------------------------------------------------------ | :----------------------------------------------- |
| TSG ID        | The tenant the token will act on. One TSG corresponds to one AI Gateway organisation. | Shown against the tenant in Strata Cloud Manager |
| Client ID     | The service account                                                                   | Issued when the service account is created       |
| Client Secret | The service account's credential                                                      | Shown **once**, at creation                      |

<Note>
  A TSG must have a service account before you can make any API call against it. If a tenant has no service account of its own, a service account belonging to one of its ancestor TSGs can be used instead. See [Token scope within a TSG hierarchy](#token-scope-within-a-tsg-hierarchy).

  One TSG may have many service accounts, and one service account may have many tokens.
</Note>

<Info>
  *Tenant service group* and *tenant* are used interchangeably; there is no functional difference between them.
</Info>

## Create a service account

Service accounts are created in Strata Cloud Manager, through Common Services Identity & Access. A service account is not tied to a specific user.

<Steps>
  <Step title="Open Identity & Access">
    Sign in to [Strata Cloud Manager](https://stratacloudmanager.paloaltonetworks.com/) and go to **System Settings > Identity & Access**.
  </Step>

  <Step title="Select the tenant">
    Choose the tenant the service account belongs to.

    A service account added to a parent tenant is automatically added to all of that tenant's children, which is how a parent manages its children. Add it to a child tenant instead if you do not want that inheritance.

    Creating service accounts in different tenant service groups lets you assign different roles for different access permissions, and keeps the audit trail readable.
  </Step>

  <Step title="Add the identity">
    Select **Add** (or **Add Identity**), then set **Identity Type** to **Service Account**.

    Give it a unique and meaningful **Service Account Name**. Optionally add a **Service Account Contact** email and a **Description**. The contact person is not added as a user.
  </Step>

  <Step title="Save the client credentials">
    Select **Next**. The Client Credentials screen shows the **Client ID** and **Client Secret**.

    <Warning>
      The Client Secret is presented once. Copy both values, or select **Download CSV File**, before leaving the screen. If you lose the secret you must issue a new credential.
    </Warning>
  </Step>

  <Step title="Note the TSG ID">
    Select **Next**. The display name of the service account is formatted as `<ServiceAccountName>@<tsg_id>.iam.panserviceaccount.com`.

    Every service account of a parent tenant carries the parent TSG ID, and every service account of a child tenant carries the child TSG ID. Take note of the `tsg_id`, because you pass it on every token request.
  </Step>

  <Step title="Assign a role">
    On the Assign Roles screen, select the scope (for example **All Apps & Services**) and assign the role the service account needs. A service account with no role assignment cannot obtain a token.

    Grant the narrowest role that covers the Admin API operations you intend to automate. A custom role needs `iam.service_account` and `iam.custom_role` permissions if the account will manage identities itself.
  </Step>

  <Step title="Submit">
    Save to create the service account. You now have the Client ID, Client Secret and TSG ID needed to request a token.
  </Step>
</Steps>

## Request an access token

Exchange the service account credentials for an access token with `POST /oauth2/access_token`.

<Warning>
  The authentication service runs on a different FQDN from the rest of Strata Cloud Manager:
  `https://auth.apps.paloaltonetworks.com`
</Warning>

The endpoint uses basic auth, with the Client ID as the username and the Client Secret as the password, and takes the TSG ID in the `scope` field:

```sh Request an access token theme={"system"}
curl -d "grant_type=client_credentials&scope=tsg_id:<tsg_id>" \
  -u <client_id>:<client_secret> \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -X POST https://auth.apps.paloaltonetworks.com/oauth2/access_token
```

The service account you authenticate with must belong to the TSG named on `scope`, or to one of its ancestors.

A successful response carries the token and its lifetime in seconds:

```json theme={"system"}
{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 900
}
```

<Note>
  **Access tokens have a lifespan of 15 minutes.** Read `expires_in` rather than hard-coding the number, cache the token in memory for the life of that window, and refresh it about a minute before it lapses. Requesting a fresh token per API call is unnecessary; carrying one across a long-running job is what fails.
</Note>

## Call an Admin API endpoint

Send the token as a bearer token. Every Admin API endpoint takes the same header; the base URL and path for each one are shown on its own reference page.

```sh theme={"system"}
curl https://api.apps.paloaltonetworks.com/ai_gw/v2/configs \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json"
```

You do not pass the TSG ID on the request. The token already contains it, and the request is routed to that tenant on the strength of it.

## Token scope within a TSG hierarchy

A token issued for one TSG cannot be used against another. If you have a tenant, Tenant 1A, with a service account named `1a_svc`, then a token obtained through `1a_svc` reaches Tenant 1A and nothing else.

When you run multiple tenants you organise them as a hierarchy of TSGs. Creating a dedicated service account for every TSG and tenant in that hierarchy is the simplest arrangement, but it is not necessary. **A service account belonging to a TSG can name any descendant of that TSG when it requests a token.**

Consider a root TSG A with two tenants, and a child TSG B with two more:

```mermaid theme={"system"}
graph TD
    TSGA["TSG A<br/>a_svc"] --> T1A[Tenant 1A]
    TSGA --> T2A[Tenant 2A]
    TSGA --> TSGB["TSG B<br/>b_svc"]
    TSGB --> T1B[Tenant 1B]
    TSGB --> T2B[Tenant 2B]
```

Assume `a_svc` and `b_svc` were created with the `superuser` role on TSG A and TSG B respectively. Then:

* **`a_svc` can request a token for any TSG ID in the hierarchy**, because every TSG and tenant shown is a descendant of TSG A.
* **`b_svc` can request tokens for TSG B, Tenant 1B and Tenant 2B**, its own descendants.
* **`b_svc` cannot request a token for TSG A, Tenant 1A or Tenant 2A.** Those are its ancestor and its peers.
* Tenants 1A, 2A, 1B and 2B hold no service accounts of their own, so only the service accounts of their parent TSGs can obtain tokens for them.

<Note>
  The TSG IDs used in the examples on this page are deliberately fake. Real TSG IDs are 10-digit integers, such as `1000000001`.
</Note>

### Grant cross-hierarchy access with an access policy

`b_svc` cannot obtain a token for Tenant 1A, because Tenant 1A sits outside its subtree. Where you need exactly that, create an **access policy** on Tenant 1A naming the Client ID of `b_svc` as the principal. The policy overrides the hierarchy restriction for that one pairing.

You can do this from the multitenant UI, or with the Identity and Access Management *create an access policy* API. The following grants `b_svc` superuser permissions on Tenant 1A, represented here by TSG ID `18`:

```sh Grant b_svc access to Tenant 1A theme={"system"}
curl -d '{"role":"superuser","resource":"prn:18::::","principal":"b_svc@15.iam.panserviceaccount.com"}' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST https://api.strata.paloaltonetworks.com/iam/v1/access_policies
```

The token you authenticate this call with must itself be scoped to the TSG that owns the resource, `15` in the example above.

The same endpoint grants a person a role on a tenant, with their email address as the principal. Three fields make up a policy:

| Field       | Format                                                                                                                                                        |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `principal` | A user's email address, or a service account as `<name>@<tsg_id>.iam.panserviceaccount.com`                                                                   |
| `resource`  | `prn:<tsg_id>::::<workspace>`. Leave the last segment empty for the TSG root, which Strata Cloud Manager labels **All Apps & Services**                       |
| `role`      | A built-in role is a bare slug, such as `superuser` or `view_only_admin`. A role defined by a tenant carries that tenant's ID, as `my_custom_role:1000000001` |

`GET /iam/v1/access_policies` lists the policies on the tenant your token is scoped to, and `DELETE /iam/v1/access_policies/{id}` removes one. A duplicate `POST` returns `409`, so the call is safe to retry.

<Warning>
  The access policy endpoint does not check that the principal exists. A `POST` naming an address that belongs to nobody returns `201` and a policy ID, and the policy sits in the listing doing nothing until somebody with that address appears. Validate addresses against your directory before creating policies in bulk, and review the IDs you get back.
</Warning>

<Note>
  Older Palo Alto Networks documentation shows this endpoint as `https://api.sase.paloaltonetworks.com/access_policies`. `https://api.strata.paloaltonetworks.com/iam/v1/access_policies` is the current host and path.
</Note>

## Check your token

If the credentials baked into a token are not the ones you expect, the Admin API rejects the request and the error reports an invalid authorisation code.

Paste the token into [jwt.io](https://jwt.io/) to decode it and read the claims back. The decoded payload shows the `tsg_id` the token was issued for, which is the fastest way to confirm you are hitting the tenant you think you are, and an `access` claim listing the roles the service account holds on it.

### Common failures

| Symptom                                                             | Cause                                                                                                                                       |
| :------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------ |
| Token request rejected at `/oauth2/access_token`                    | The Client ID or Client Secret is wrong, or the service account has no role assignment                                                      |
| Token request rejected for the TSG on `scope`                       | The service account is not in that TSG or an ancestor of it. Create an [access policy](#grant-cross-hierarchy-access-with-an-access-policy) |
| Admin API returns an authorisation error with a valid-looking token | The token has expired, since they last 15 minutes, or it is scoped to a different tenant. Decode it and check `tsg_id`                      |
| Admin API rejects a key that works for inference                    | A gateway API key was sent instead of an access token. Only tokens from the authentication service are accepted                             |

## Related

<CardGroup cols={2}>
  <Card title="Admin API introduction" icon="book" href="/aigw/api-reference/admin-api/introduction">
    What the Admin API manages, and the permissions model behind it
  </Card>

  <Card title="Inference API authentication" icon="key" href="/aigw/api-reference/inference-api/authentication">
    Gateway API keys and JWT authentication for inference requests
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/aigw/api-reference/admin-api/error">
    Admin API error codes and what they mean
  </Card>

  <Card title="Audit logs" icon="shield-check" href="/aigw/product/enterprise-offering/audit-logs">
    Every administrative action, attributed to the principal that made it
  </Card>
</CardGroup>
