SpyBara
Go Premium

Documentation 2026-05-24 06:25 UTC to 2026-05-27 06:42 UTC

8 files changed +1,394 −1. View all changes and history on the product overview
2026
Fri 29 06:38 Thu 28 06:37 Wed 27 06:42 Sun 24 06:25 Fri 22 06:33 Thu 21 06:36 Wed 20 06:35 Tue 19 11:58 Mon 18 22:01 Thu 14 21:00 Tue 12 18:57 Thu 7 21:57 Wed 6 00:01 Tue 5 23:00 Sat 2 05:57
Details

31 - For OAuth, if static credentials are provided, then they will be used. Otherwise, ChatGPT can use Client ID Metadata Documents when the authorization server advertises support and the connector creator chooses CIMD. CIMD supports public-client token exchange (`none`) and signed client assertion token exchange (`private_key_jwt`). ChatGPT can also use DCR when configured.31 - For OAuth, if static credentials are provided, then they will be used. Otherwise, ChatGPT can use Client ID Metadata Documents when the authorization server advertises support and the connector creator chooses CIMD. CIMD supports public-client token exchange (`none`) and signed client assertion token exchange (`private_key_jwt`). ChatGPT can also use DCR when configured.

32 - Mixed authentication supports OAuth and No Authentication. This means the initialize and list tools APIs use no auth, and tools use OAuth or no auth based on the security schemes set on their tool metadata.32 - Mixed authentication supports OAuth and No Authentication. This means the initialize and list tools APIs use no auth, and tools use OAuth or no auth based on the security schemes set on their tool metadata.

33 - Created apps will show under "Drafts" in the app settings.33 - Created apps will show under "Drafts" in the app settings.

34- **Manage tools:** In app settings there is a details page per app. Use that to toggle tools on or off and refresh apps to pull new tools and descriptions from the MCP server.34- **Manage tools:** In app settings there is a details page per app. Use that to toggle tools on or off and refresh apps to pull new tools, descriptions, and server instructions from the MCP server.

35- **Use apps in conversations:** Choose **Developer mode** from the Plus menu and select the apps for the conversation. You may need to explore different prompting techniques to call the correct tools. For example:35- **Use apps in conversations:** Choose **Developer mode** from the Plus menu and select the apps for the conversation. You may need to explore different prompting techniques to call the correct tools. For example:

36 - Be explicit: "Use the \"Acme CRM\" app's \"update_record\" tool to …". When needed, include the server label and tool name.36 - Be explicit: "Use the \"Acme CRM\" app's \"update_record\" tool to …". When needed, include the server label and tool name.

37 - Disallow alternatives to avoid ambiguity: "Do not use built-in browsing or other tools; only use the Acme CRM connector."37 - Disallow alternatives to avoid ambiguity: "Do not use built-in browsing or other tools; only use the Acme CRM connector."


41 - Developer mode does not require `search`/`fetch` tools. Any tools your connector exposes (including write actions) are available, subject to confirmation settings.41 - Developer mode does not require `search`/`fetch` tools. Any tools your connector exposes (including write actions) are available, subject to confirmation settings.

42 - See more guidance in [Using tools](https://developers.openai.com/api/docs/guides/tools) and [Prompting](https://developers.openai.com/api/docs/guides/prompting).42 - See more guidance in [Using tools](https://developers.openai.com/api/docs/guides/tools) and [Prompting](https://developers.openai.com/api/docs/guides/prompting).

43 - Improve tool selection with better tool descriptions: In your MCP server, write action-oriented tool names and descriptions that include "Use this when…" guidance, note disallowed/edge cases, and add parameter descriptions (and enums) to help the model choose the right tool among similar ones and avoid built-in tools when inappropriate.43 - Improve tool selection with better tool descriptions: In your MCP server, write action-oriented tool names and descriptions that include "Use this when…" guidance, note disallowed/edge cases, and add parameter descriptions (and enums) to help the model choose the right tool among similar ones and avoid built-in tools when inappropriate.

44 - Add server instructions for cross-tool guidance: Use the MCP [`instructions` field](https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle#initialization) for server-wide guidance such as required tool sequences, shared rate limits, or relationships between tools. Keep the first 512 characters self-contained.

44 45 

45 Examples:46 Examples:

46 47 

guides/red-teaming.md +22 −0 created

Details

1# Red teaming

2 

3Red teaming uses adversarial test cases to help uncover unsafe, insecure, or policy-violating behavior before deployment. It complements evals by focusing on misuse cases, failure modes, and high-risk interactions that ordinary quality testing may not expose.

4 

5<strong>Important:</strong> Only submit to OpenAI Red Teaming code or other

6 assets that you own or are expressly authorized to test. Do not use OpenAI Red

7 Teaming to analyze or report vulnerabilities in open-source or any third-party

8 code without OpenAI's express written permission.

9 

10## Use Promptfoo for open-source red teaming

11 

12[Promptfoo](https://github.com/promptfoo/promptfoo) is an open-source framework for evaluating prompts, agents, and AI applications. Its red teaming workflows help you generate adversarial test cases, inspect target behavior, and use the results to improve your system.

13 

14For the broader open-source methodology, see Promptfoo’s [LLM red teaming guide](https://www.promptfoo.dev/docs/red-team/).

15 

16## Enterprise availability

17 

18OpenAI Red Teaming is available for enterprise customers that need a managed offering for red teaming AI applications and agents. Enterprise workflows can support broader coordination, review, and reporting needs than a standalone local workflow.

19 

20## Red teaming and evals

21 

22Use [evals](https://developers.openai.com/api/docs/guides/evals) to measure whether an AI system behaves as intended. Use red teaming to probe how that system behaves under adversarial, abusive, or unexpected inputs. Mature evaluation programs often use both.

Details

1# Workload identity federation

2 

3Workload identity federation lets trusted workloads exchange externally issued identity tokens for short-lived OpenAI access tokens. Use these guides to configure your external identity provider, create OpenAI service account mappings, and authenticate workloads without storing long-lived API keys.

4 

5For token exchange request and response details, authorization behavior, and current limitations, see the [workload identity token exchange reference](https://developers.openai.com/api/reference/workload-identity-federation).

6 

7## How it works

8 

9Workload identity federation has four parts:

10 

111. A **workload identity provider** describes the trusted issuer. It stores the expected OIDC issuer, audience, and key source used to verify external subject tokens.

122. A **service account mapping** authorizes specific external token attributes to mint tokens for a particular OpenAI service account within a project.

133. A **token exchange** request sends the external subject token to OpenAI and returns a short-lived OpenAI access token.

144. The workload uses the OpenAI-issued access token as a bearer credential to authenticate requests to the OpenAI API.

15 

16You must be an organization owner to configure this feature. To access it, go to [Organization Settings > Security > Workload Identity Provider](https://platform.openai.com/settings/organization/security/workload-identity-provider). Configure service account mappings from the workload identity provider details page.

17 

18## Choose a setup guide

19 

20Start with the guide that matches where your workload runs:

21 

22<div className="my-4 w-full max-w-full overflow-hidden">

23 </div>

24 

25OpenAI supports OIDC-compatible JWT subject tokens in the documented configurations. If you need an OIDC provider that isn't listed, contact us.

26 

27Each provider guide shows how to issue and inspect a subject token on that platform, and how to configure the OpenAI SDK to exchange it for a short-lived OpenAI access token.

28 

29## Configure a Workload Identity Provider

30 

31Create a Workload Identity Provider for each external issuer you trust. Workload identity federation supports OIDC JWT subject tokens.

32 

33Workload Identity Provider configuration includes these dashboard options:

34 

35| Option | Description |

36| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |

37| Name | A unique name for the Workload Identity Provider in your organization. |

38| OIDC Issuer URL | The expected OIDC issuer URL. Issuer comparisons ignore a trailing slash. |

39| Audience | The expected `aud` claim on the external subject token. |

40| Description | Optional description for the Workload Identity Provider. |

41| Use uploaded JWKS for token verification | When enabled, OpenAI verifies tokens against an uploaded JWKS instead of fetching keys from OIDC discovery. |

42| JWKS JSON | The uploaded public JWKS object used when uploaded JWKS verification is enabled. The JWKS must contain a non-empty `keys` array and no private key material. |

43| Attribute transformations | Optional CEL expressions that derive custom `openai.*` attributes from token claims for mapping decisions. |

44 

45### Transform token claims with CEL

46 

47Attribute transformations use Common Expression Language (CEL). OpenAI supports the standard CEL operators specified in [langdef.md](https://github.com/google/cel-spec/blob/master/doc/langdef.md) and doesn't add custom workload identity federation-specific functions. Each expression receives one root object:

48 

49- `assertion`: The verified JWT claim set.

50 

51In the dashboard, the `openai.` prefix is applied automatically. Enter the suffix, such as `subject`, and an expression, such as `assertion.sub`. The API stores the derived attribute as `openai.subject`.

52 

53```json

54[

55 {

56 "attribute": "openai.subject",

57 "expression": "assertion.sub"

58 },

59 {

60 "attribute": "openai.repository",

61 "expression": "assertion.repository"

62 }

63]

64```

65 

66Use CEL syntax defined by the CEL language specification. For example, you can read claim values with expressions such as `assertion.sub` or `assertion.repository`. Unsupported syntax or functions fail mapping resolution.

67 

68```json

69[

70 {

71 "attribute": "openai.repository_ref",

72 "expression": "assertion.repository + \"@\" + assertion.ref"

73 },

74 {

75 "attribute": "openai.production",

76 "expression": "assertion.ref == \"refs/heads/main\""

77 }

78]

79```

80 

81Transformation results must be scalar values: strings, booleans, integers, or finite numbers. Arrays, objects, null values, and evaluation errors fail mapping resolution. OpenAI converts scalar transformation results to strings before comparing them to mapping values. For example, `true` becomes `"true"` and `7` becomes `"7"`.

82 

83Mapping keys that start with `openai.` resolve only from attribute transformations. Raw subject token claims that already use an `openai.` prefix don't affect mapping decisions unless you configure a matching transformation.

84 

85### Manage JWKS and key rotation

86 

87OpenAI verifies OIDC subject tokens with the key source configured on the Workload Identity Provider.

88 

89- **OIDC discovery:** OpenAI fetches the issuer's `/.well-known/openid-configuration`, then fetches the discovered `jwks_uri`. Discovery documents and remote JWKS payloads are cached for 600 seconds.

90- **Key refresh on miss:** If a token `kid` isn't found in the cached JWKS, OpenAI refreshes the JWKS and tries the lookup again before rejecting the token.

91- **Uploaded JWKS:** When **Use uploaded JWKS for token verification** is enabled, OpenAI uses the uploaded JWKS stored on the Workload Identity Provider and doesn't perform OIDC discovery or remote JWKS fetching. After a provider update is saved and available to token exchange, new exchanges use the saved JWKS.

92- **Multiple keys:** A JWKS can contain multiple public keys, and each key must have a unique non-empty `kid`.

93 

94During signing-key rotation, publish both old and new public keys in the issuer JWKS during the rotation window. This lets tokens signed by the old key continue working while OpenAI accepts tokens signed by the new key. For uploaded JWKS mode, update the Workload Identity Provider JWKS before issuing tokens with the new `kid`; OpenAI rejects tokens signed by a key absent from the configured JWKS.

95 

96## Configure service account mappings

97 

98A service account mapping defines which external identities can mint access tokens for an OpenAI service account.

99 

100Mapping configuration includes these dashboard options:

101 

102| Option | Description |

103| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |

104| Name | A unique name for the mapping within the Workload Identity Provider. |

105| Key | The attribute key to match. Use a raw token claim, such as `sub`, `aud`, or `iss`, or a derived attribute like `openai.subject`. |

106| Value | The attribute value that must match before OpenAI issues a token. |

107| Description | Optional description for the mapping. |

108| Project | The project that owns the target service account. |

109| Service account | The service account the workload can use. You can create a new service account in the selected project or select an existing service account. |

110| Permissions | Optional API permissions that further narrow access tokens minted from this mapping. These permissions can't grant access beyond the mapped service account. |

111 

112Attribute assertion values must be scalar JSON values. String values may use one trailing wildcard, such as `repo:example/*`. The wildcard must have a non-empty prefix; `*` by itself isn't supported.

113 

114Valid wildcard values:

115 

116- `repo:openai/*`

117- `repository:my-org/*`

118 

119Invalid wildcard values:

120 

121- `*`

122- `repo:*:prod`

123- `repo/*/main`

124 

125The dashboard shows mapping-level restrictions as **Permissions**. Token exchange responses expose the same restrictions as OAuth scopes in the `scope` property. Admin API scopes can't be assigned to Workload Identity Provider mappings, and downstream API authorization still applies after OpenAI mints a token.

126 

127### Mapping resolution example

128 

129Mapping resolution starts after OpenAI verifies the external subject token. OpenAI looks up mappings for the requested `identity_provider_id` and `service_account_id`, skips disabled mappings, evaluates only the attributes needed by each mapping, and issues a token only if exactly one enabled mapping matches all configured attributes.

130 

131For example, a GitHub Actions token might contain these claims:

132 

133```json

134{

135 "iss": "https://token.actions.githubusercontent.com",

136 "aud": "https://api.openai.com/v1",

137 "sub": "repo:my-org/my-repo:ref:refs/heads/main",

138 "repository": "my-org/my-repo",

139 "ref": "refs/heads/main"

140}

141```

142 

143The Workload Identity Provider can define a derived attribute:

144 

145```json

146[

147 {

148 "attribute": "openai.repository_ref",

149 "expression": "assertion.repository + \"@\" + assertion.ref"

150 }

151]

152```

153 

154Then a service account mapping can require both raw and derived attributes:

155 

156| Key | Value |

157| ----------------------- | --------------------------------------------- |

158| `iss` | `https://token.actions.githubusercontent.com` |

159| `sub` | `repo:my-org/my-repo:*` |

160| `openai.repository_ref` | `my-org/my-repo@refs/heads/main` |

161 

162This mapping matches only when all three attributes match. The `sub` value uses a trailing wildcard, so it matches any value with the prefix `repo:my-org/my-repo:`. The `openai.repository_ref` key resolves from the attribute transformation; OpenAI doesn't use a raw token claim named `openai.repository_ref`.

163 

164If multiple enabled mappings match the same token exchange, OpenAI rejects the exchange. OpenAI enforces a unique mapping for each `(provider, service account)` pair and doesn't combine permissions across multiple mappings.

165 

166## Security recommendations

167 

168- Use a dedicated OpenAI service account for each application or workload.

169- Separate production and non-production environments.

170- Prefer exact claim matching over broad attribute patterns.

171- Grant only the minimum OpenAI permissions required.

172- Review and remove unused mappings regularly.

173- Monitor token exchange failures and unexpected access patterns.

174- Avoid sharing identities across unrelated workloads.

Details

1# Configuring workload identity federation for AWS

2 

3import {

4 awsOutboundWorkloadIdentitySdk,

5 awsWorkloadIdentitySdk,

6} from "./examples";

7 

8Use AWS as a Workload Identity Provider in either of these scenarios:

9 

10- **AWS outbound identity federation:** Exchange an AWS STS-issued OIDC JWT from `GetWebIdentityToken` for a short-lived OpenAI access token.

11- **Amazon EKS:** Exchange a projected Amazon EKS service account token for a short-lived OpenAI access token.

12 

13OpenAI supports AWS-issued OIDC JWTs from outbound identity federation and

14 Kubernetes projected service account tokens issued by Amazon EKS. OpenAI does

15 not support SigV4-signed requests or AWS STS temporary access key credentials

16 as workload identity federation subject tokens.

17 

18 

19 

20<div data-content-switcher-pane data-value="outbound">

21 

22## AWS outbound identity federation

23 

24AWS outbound identity federation lets an AWS principal request a signed OIDC JWT from AWS STS and present that token to an external service. In OpenAI workload identity federation, the AWS-issued JWT is the subject token that OpenAI validates before issuing an OpenAI access token.

25 

26### Setting up AWS outbound identity federation

27 

28Enable outbound identity federation for the AWS account that will issue tokens. For setup details, see the AWS guide to [getting started with outbound identity federation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_outbound_getting_started.html).

29 

30```bash

31aws iam enable-outbound-web-identity-federation

32```

33 

34Record the account-specific issuer URL returned by AWS. You will configure this value as the OpenAI Workload Identity Provider issuer, and it must match the `iss` claim in AWS-issued tokens.

35 

36The AWS STS `GetWebIdentityToken` API is not available on the STS global

37 endpoint. Configure the AWS CLI or SDK to use a regional STS endpoint.

38 

39Grant the workload permission to call `sts:GetWebIdentityToken`. Restrict the audience and maximum token lifetime in IAM so the AWS principal can mint only tokens intended for OpenAI. This example allows tokens for the audience `https://api.openai.com/v1` with a maximum lifetime of 300 seconds:

40 

41```json

42{

43 "Version": "2012-10-17",

44 "Statement": [

45 {

46 "Effect": "Allow",

47 "Action": "sts:GetWebIdentityToken",

48 "Resource": "*",

49 "Condition": {

50 "ForAllValues:StringEquals": {

51 "sts:IdentityTokenAudience": "https://api.openai.com/v1"

52 },

53 "NumericLessThanEquals": {

54 "sts:DurationSeconds": 300

55 }

56 }

57 }

58 ]

59}

60```

61 

62Request an AWS-issued OIDC token with the same audience you will configure on the OpenAI Workload Identity Provider. Use `ES384` unless your environment requires `RS256` compatibility.

63 

64```bash

65TOKEN=$(aws sts get-web-identity-token \

66 --audience "https://api.openai.com/v1" \

67 --signing-algorithm ES384 \

68 --duration-seconds 300 \

69 --tags Key=environment,Value=production \

70 Key=workload,Value=batch-ingest \

71 --query "WebIdentityToken" \

72 --output text)

73```

74 

75### Verify the AWS-issued token

76 

77Before configuring workload identity federation, decode a sample AWS-issued token locally and inspect its claims:

78 

79```bash

80TOKEN="$TOKEN" python3 - <<'PY'

81import base64

82import json

83import os

84 

85payload = os.environ["TOKEN"].split(".")[1]

86payload += "=" * (-len(payload) % 4)

87print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))

88PY

89```

90 

91This command decodes the JWT payload without verifying the token signature. Use a local decoder for production tokens, and avoid pasting production tokens into third-party tools.

92 

93A decoded AWS-issued OIDC token will look similar to:

94 

95```json

96{

97 "iss": "https://abc123-def456-ghi789-jkl012.tokens.sts.global.api.aws",

98 "aud": "https://api.openai.com/v1",

99 "sub": "arn:aws:iam::123456789012:role/OpenAIWifRole",

100 "iat": 1716235422,

101 "exp": 1716235722,

102 "jti": "jwt-id-example",

103 "https://sts.amazonaws.com/": {

104 "aws_account": "123456789012",

105 "source_region": "us-west-2",

106 "org_id": "o-exampleorgid",

107 "principal_tags": {

108 "environment": "production"

109 },

110 "request_tags": {

111 "environment": "production",

112 "workload": "batch-ingest"

113 }

114 }

115}

116```

117 

118Not every AWS-issued token contains every AWS-specific claim. The claims under `https://sts.amazonaws.com/` depend on the calling principal, session context, and request tags.

119 

120Verify the claims you plan to configure in OpenAI:

121 

122- `iss`: Must match the AWS account-specific issuer URL configured in the OpenAI Workload Identity Provider.

123- `aud`: Must match the `GetWebIdentityToken` audience and the OpenAI Workload Identity Provider audience.

124- `sub`: Identifies the IAM principal ARN that requested the token. Prefer matching the exact role ARN.

125- AWS-specific claims: Use the decoded token as the source of truth before matching account, organization, principal tag, or request tag values.

126 

127Use the decoded payload to compare the token you received with the issuer, audience, and mapping values configured in OpenAI. Most configuration issues are visible in the `iss`, `aud`, and `sub` claims before you exchange the token.

128 

129### Setting up workload identity federation

130 

131Create a Workload Identity Provider in OpenAI for the AWS account issuer, then add a service account mapping that matches stable claims from the AWS-issued token.

132 

133Configure the Workload Identity Provider first, then create the service account mapping.

134 

135#### Set up the Workload Identity Provider

136 

1371. **Create the Workload Identity Provider.** Set **Name** to a unique value, such as `aws-outbound-prod`. Use **Description**, such as `Production AWS outbound identity federation workloads`, to help admins identify the provider.

138 

1392. **Set the issuer and audience.** Set **OIDC Issuer URL** to the AWS account-specific issuer URL returned when outbound identity federation was enabled. This value must match the token's `iss` claim. Set **Audience** to the same audience passed to `GetWebIdentityToken`. In this example, that value is `https://api.openai.com/v1`.

140 

1413. **Use AWS OIDC discovery.** Leave **Use uploaded JWKS for token verification** disabled. OpenAI uses the AWS issuer's OIDC discovery metadata and JWKS to verify the AWS-issued token.

142 

1434. **Add attribute transformations only if you need derived mapping attributes.** Raw token matching supports top-level scalar claims such as `sub`, `aud`, and `iss`. AWS-specific namespaced claims are nested under `https://sts.amazonaws.com/`, so create derived attributes with CEL bracket notation before using them in mappings. For example, enter `aws_environment` with expression `assertion["https://sts.amazonaws.com/"]["principal_tags"]["environment"]` to create `openai.aws_environment` from the decoded token example above. Verify the nested claim path in a sample token before using it; if a transformation cannot be evaluated, mapping resolution fails. Raw token claims that already start with `openai.` are ignored for `openai.` mapping keys unless a matching transformation is configured.

144 

145#### Set up the service account mapping

146 

1471. **Create a service account mapping.** Set **Name** to a value that is unique within the Workload Identity Provider, such as `aws-role-openai-wif`. Use **Description**, such as `Production AWS role for OpenAI API workload`, to explain which workload can use the mapping.

148 

1492. **Match the AWS principal.** Set **Key** to `sub` and **Value** to the IAM principal ARN from the decoded token, such as `arn:aws:iam::123456789012:role/OpenAIWifRole`. Matching on the exact `sub` claim provides the strongest isolation for AWS outbound identity federation.

150 

1513. **Add additional claim matches if needed.** You can match on any available scalar claim or transformed attribute. For example, use transformed attributes derived from AWS account, organization, principal tag, or request tag claims if you need additional trust boundaries.

152 

1534. **Choose the OpenAI target.** Set **Project** to the OpenAI project that owns the target service account. Set **Service account** to the OpenAI service account the AWS workload can use, such as `aws-outbound-prod-openai-wif`.

154 

1555. **Narrow API permissions if needed.** Select appropriate **Permissions** such as `api.model.request` and `api.vector_store.read` to further narrow access tokens minted from this mapping. Leave permissions blank to avoid adding a WIF-specific scope restriction; the token still authorizes as the mapped service account.

156 

157### Using the token in code

158 

159Configure your OpenAI SDK client to request an AWS-issued OIDC token from AWS STS and exchange it for an OpenAI-issued access token.

160 

161Set `OPENAI_WIF_AUDIENCE` to the same audience configured on the OpenAI Workload Identity Provider. The subject token provider calls AWS STS `GetWebIdentityToken` with that audience, returns the AWS-issued JWT as the subject token, and the OpenAI SDK exchanges it for an OpenAI-issued access token.

162 

163</div>

164 

165 <div data-content-switcher-pane data-value="eks" hidden>

166 

167## Amazon EKS projected service account tokens

168 

169Use Amazon EKS as a Workload Identity Provider by exchanging an EKS-issued projected service account token for a short-lived OpenAI access token.

170 

171### Setting up EKS

172 

173Use a Kubernetes `ServiceAccount` for the EKS workload that needs to call the OpenAI API. If you do not already have one, create it:

174 

175```bash

176kubectl create serviceaccount openai-wif --namespace default

177```

178 

179EKS projected service account tokens use a `sub` claim in the format `system:serviceaccount:<namespace>:<service-account-name>`. For the service account above, the `sub` claim is `system:serviceaccount:default:openai-wif`.

180 

181Retrieve the OIDC issuer URL associated with the EKS cluster:

182 

183```bash

184aws eks describe-cluster \

185 --name <cluster-name> \

186 --region <region> \

187 --query "cluster.identity.oidc.issuer" \

188 --output text

189```

190 

191Example output:

192 

193```text

194https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3

195```

196 

197The issuer you configure in the OpenAI Workload Identity Provider must match this issuer URL and the `iss` claim in the projected EKS service account token.

198 

199Configure the projected service account token with the audience OpenAI expects and an expiration suitable for your workload. OpenAI validates the token's issuer, signature, audience, and expiration. In this example, the token file is mounted at `/var/run/secrets/tokens/token`, uses the audience `https://api.openai.com/v1`, and expires after 3600 seconds. You may use a different audience if the projected token audience and OpenAI Workload Identity Provider audience match:

200 

201```yaml

202apiVersion: v1

203kind: Pod

204metadata:

205 name: openai-wif-app

206 namespace: default

207spec:

208 serviceAccountName: openai-wif

209 containers:

210 - name: app

211 image: my-image

212 volumeMounts:

213 - name: eks-sa-token

214 mountPath: /var/run/secrets/tokens

215 readOnly: true

216 volumes:

217 - name: eks-sa-token

218 projected:

219 sources:

220 - serviceAccountToken:

221 path: token

222 audience: "https://api.openai.com/v1"

223 expirationSeconds: 3600

224```

225 

226### Verify the EKS token

227 

228Before configuring workload identity federation, decode a sample projected service account token locally and inspect its claims. From a running pod with the projected token mounted:

229 

230```bash

231TOKEN=$(kubectl exec -n default openai-wif-app -- cat /var/run/secrets/tokens/token)

232 

233TOKEN="$TOKEN" python3 - <<'PY'

234import base64

235import json

236import os

237 

238payload = os.environ["TOKEN"].split(".")[1]

239payload += "=" * (-len(payload) % 4)

240print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))

241PY

242```

243 

244This command decodes the JWT payload without verifying the token signature. Use a local decoder for production tokens, and avoid pasting production tokens into third-party tools.

245 

246A decoded EKS projected service account token will look similar to:

247 

248```json

249{

250 "iss": "https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3",

251 "aud": ["https://api.openai.com/v1"],

252 "sub": "system:serviceaccount:default:openai-wif",

253 "iat": 1716235422,

254 "exp": 1716239022,

255 "kubernetes.io": {

256 "namespace": "default",

257 "serviceaccount": {

258 "name": "openai-wif",

259 "uid": "11111111-2222-3333-4444-555555555555"

260 }

261 }

262}

263```

264 

265Use the decoded payload to compare the token you received with the issuer, audience, and mapping values configured in OpenAI. Most configuration issues are visible in the `iss`, `aud`, and `sub` claims before you exchange the token.

266 

267### Setting up workload identity federation

268 

269Create a Workload Identity Provider in OpenAI for the EKS issuer, then add a service account mapping that matches attributes from the projected token.

270 

271Configure the Workload Identity Provider first, then create the service account mapping.

272 

273#### Set up the Workload Identity Provider

274 

2751. **Create the Workload Identity Provider.** Set **Name** to a unique value, such as `aws-eks-prod`. Use **Description**, such as `Production EKS cluster`, to help admins identify the cluster.

276 

2772. **Set the issuer and audience.** Set **OIDC Issuer URL** to the issuer returned by `aws eks describe-cluster --query "cluster.identity.oidc.issuer"`. This value must match the `iss` claim in the projected EKS service account token. Set **Audience** to the same audience configured on the projected service account token volume. In this example, that value is `https://api.openai.com/v1`.

278 

2793. **Use EKS OIDC discovery.** Leave **Use uploaded JWKS for token verification** disabled. OpenAI uses the EKS issuer's OIDC discovery metadata and JWKS to verify the projected service account token.

280 

2814. **Add attribute transformations only if you need derived mapping attributes.** Raw token claims such as `sub`, `aud`, and `iss` can be used directly in mapping assertions. For example, create a transformed attribute named `subject` with expression `assertion.sub`. In the dashboard, enter `subject` as the attribute name; OpenAI stores it as `openai.subject`, which you can reference in mappings.

282 

283 > **Note:** Raw token claims that already start with `openai.` are ignored for `openai.` mapping keys unless a matching transformation is configured.

284 

285#### Set up the service account mapping

286 

2871. **Create a service account mapping.** Set **Name** to a unique value within the Workload Identity Provider, such as `openai-mapping-eks`. Use **Description**, such as `Workload Identity Provider Mapping for EKS Workloads`, to explain which workload can use the mapping.

288 

2892. **Match the EKS service account subject.** Set **Key** to `sub` and **Value** to `system:serviceaccount:default:openai-wif`. You can match on any available claim or transformed attribute. Matching on `sub` is the most restrictive option because it uniquely identifies a Kubernetes service account.

290 

2913. **Choose the OpenAI target.** Set **Project** to the OpenAI project that owns the target service account. Set **Service account** to the OpenAI service account the EKS workload can use, such as `aws-eks-prod-openai-wif`. Check `Create a new service account in this project` if you wish to create a new service account for this mapping rather than reuse an existing one.

292 

2934. **Narrow API permissions if needed.** Select appropriate **Permissions** such as `api.model.request` and `api.vector_store.read` to further narrow access tokens minted from this mapping. Leave permissions blank to avoid adding a WIF-specific scope restriction; the token still authorizes as the mapped service account.

294 

295### Using the token in code

296 

297Configure your OpenAI SDK client to read the projected EKS service account token and exchange it for an OpenAI-issued access token.

298 

299Use the mounted token path, such as `/var/run/secrets/tokens/token`, as the subject token source for the SDK workload identity federation provider. The SDK exchanges that EKS token for an OpenAI-issued access token and uses the OpenAI token to authenticate API requests.

300 

301The following examples initialize an OpenAI client with a custom subject token provider. The provider reads the projected EKS service account token from the mounted file path and uses it as the subject token for workload identity federation.

302 

303</div>

304 

305 

306 

307## AWS best practices

308 

309- Use a dedicated AWS identity per workload. Use separate IAM roles for AWS outbound identity federation and separate Kubernetes service accounts for EKS workloads.

310- Configure a dedicated audience for OpenAI access. Use the same audience value in the AWS-issued or EKS projected token and in the OpenAI Workload Identity Provider configuration.

311- Keep token lifetimes reasonably short. For AWS outbound identity federation, use IAM conditions such as `sts:DurationSeconds`; for EKS, set an appropriate projected token expiration.

312- Prefer exact subject matching. Match on the full IAM principal ARN for AWS outbound tokens or the full Kubernetes service account subject for EKS tokens.

313- Scope mappings to stable boundaries. Use account, organization, namespace, or transformed attributes when they reduce access without creating broad trust rules.

314- Reload tokens when exchanging them. Request AWS outbound tokens when needed, and read EKS projected tokens from the mounted file path so rotated tokens are picked up automatically.

315- Grant only the permissions required by the workload. Use mapping-level permissions to further narrow access granted by the target OpenAI service account.

Details

1# Configuring workload identity federation for GitHub Actions

2 

3Use GitHub Actions as a Workload Identity Provider by exchanging a GitHub-issued OIDC token for a short-lived OpenAI access token. This lets workflows authenticate to the OpenAI API without storing a long-lived API key in GitHub secrets.

4 

5GitHub can mint a signed OIDC JWT for a workflow job that has `id-token: write` permission and requests an identity token. OpenAI validates the token issuer, audience, signature, and mapping attributes before issuing an OpenAI access token.

6 

7## Setting up GitHub Actions

8 

9Grant the workflow or job permission to request a GitHub OIDC token:

10 

11```yaml

12permissions:

13 id-token: write

14 contents: read

15```

16 

17The `id-token: write` permission lets the job request an OIDC JWT. It does not grant write access to repository contents. The `contents: read` permission is needed by `actions/checkout`.

18 

19Request the token with the exact audience configured in your OpenAI Workload Identity Provider. Custom JavaScript actions can call `core.getIDToken("your-wif-audience")`; shell steps can call GitHub's OIDC request URL directly. Audience values containing reserved URL characters, such as `https://api.openai.com/v1`, should be URL encoded before being appended to the request URL:

20 

21```bash

22AUDIENCE="https://api.openai.com/v1"

23ENCODED_AUDIENCE=$(jq -rn --arg audience "$AUDIENCE" '$audience | @uri')

24 

25TOKEN=$(curl -sSf -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \

26 "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${ENCODED_AUDIENCE}" | jq -r .value)

27```

28 

29Important GitHub OIDC claims include:

30 

31- `iss`: The token issuer. For GitHub Actions, this is `https://token.actions.githubusercontent.com`.

32- `aud`: The audience value requested by the workflow. Configure OpenAI to require the exact value you request, such as `your-wif-audience` or `https://api.openai.com/v1`.

33- `sub`: The main subject string. GitHub builds it from workflow metadata such as repository, branch, tag, pull request, or environment.

34- `repository`: The repository running the workflow, such as `my-org/my-repo`.

35- `repository_owner`: The organization or user that owns the repository, such as `my-org`.

36- `ref`: The Git ref that triggered the workflow, such as `refs/heads/main` or `refs/tags/v1.0.0`.

37- `workflow`: The workflow claim. Use the actual claim value emitted by GitHub, such as `deploy` if that is the workflow claim in your job.

38- `workflow_ref`: The workflow file path and ref, such as `my-org/my-repo/.github/workflows/deploy.yml@refs/heads/main`.

39- `environment`: The GitHub environment name, such as `production`, when the job uses an environment.

40- `run_id`, `run_number`, `run_attempt`, and `job_workflow_ref`: Run and job identifiers that can help with auditing or more advanced trust rules.

41 

42For the full claim list and subject formats, see GitHub's [OpenID Connect reference](https://docs.github.com/en/actions/reference/security/oidc).

43 

44## Verify the token

45 

46Before configuring workload identity federation, decode a sample GitHub OIDC token in the workflow runner and inspect its claims. After requesting the token in a workflow step:

47 

48```bash

49TOKEN="$TOKEN" python3 - <<'PY'

50import base64

51import json

52import os

53 

54payload = os.environ["TOKEN"].split(".")[1]

55payload += "=" * (-len(payload) % 4)

56print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))

57PY

58```

59 

60This command decodes the JWT payload without verifying the token signature. Use a local decoder for production tokens, and avoid pasting production tokens into third-party tools. Never log the raw GitHub OIDC token or the exchanged OpenAI access token.

61 

62A decoded GitHub Actions OIDC token will look similar to:

63 

64```json

65{

66 "iss": "https://token.actions.githubusercontent.com",

67 "aud": "https://api.openai.com/v1",

68 "sub": "repo:my-org/my-repo:environment:production",

69 "repository": "my-org/my-repo",

70 "repository_owner": "my-org",

71 "ref": "refs/heads/main",

72 "workflow": "deploy",

73 "workflow_ref": "my-org/my-repo/.github/workflows/deploy.yml@refs/heads/main",

74 "environment": "production",

75 "run_id": "1234567890",

76 "run_attempt": "1"

77}

78```

79 

80Use the decoded payload to compare the token you received with the issuer, audience, and mapping values configured in OpenAI. Most configuration issues are visible in the `iss`, `aud`, `repository`, `ref`, and `workflow_ref` claims before you exchange the token.

81 

82## Setting up workload identity federation

83 

84Create a Workload Identity Provider in OpenAI for GitHub Actions, then add a service account mapping that matches the GitHub workflow claims you trust.

85 

86Configure the Workload Identity Provider first, then create the service account mapping.

87 

88### Set up the Workload Identity Provider

89 

901. **Create the Workload Identity Provider.** Set **Name** to a unique value, such as `github-actions-prod`. Use **Description**, such as `Production GitHub Actions workflows`, to help admins identify the provider.

91 

922. **Set the issuer and audience.** Set **OIDC Issuer URL** to `https://token.actions.githubusercontent.com`. Set **Audience** to the exact audience your workflow requests, such as `your-wif-audience` or `https://api.openai.com/v1`.

93 

943. **Use GitHub OIDC discovery.** Leave **Use uploaded JWKS for token verification** disabled. OpenAI uses GitHub's OIDC discovery metadata and JWKS to verify the GitHub-signed token.

95 

964. **Add attribute transformations only if you need derived mapping attributes.** Raw GitHub claims such as `repository`, `ref`, and `workflow` can be used directly in mapping assertions. If you create derived attributes, the dashboard applies the `openai.` prefix automatically; for example, enter `github_repository` with expression `assertion.repository` to create `openai.github_repository`. Raw token claims that already start with `openai.` are ignored for `openai.` mapping keys unless a matching transformation is configured.

97 

98### Set up the service account mapping

99 

1001. **Create a service account mapping.** Set **Name** to a unique value within the Workload Identity Provider, such as `github-actions-main-deploy`. Use **Description**, such as `Production deploy workflow on main`, to explain which workflow can use the mapping.

101 

1022. **Add exact claim assertions.** Add one **Key** and **Value** row for each GitHub claim that must match. OpenAI requires every configured row to match before it issues an access token. For a production deploy workflow, use assertions like:

103 

104 ```text

105 iss == "https://token.actions.githubusercontent.com"

106 aud == "https://api.openai.com/v1"

107 repository == "my-org/my-repo"

108 ref == "refs/heads/main"

109 workflow_ref == "my-org/my-repo/.github/workflows/deploy.yml@refs/heads/main"

110 ```

111 

112 Prefer `workflow_ref` over `workflow` for privileged mappings because admins usually intend to trust a specific workflow file path and ref. Workflow names can be renamed, and multiple workflow files can share the same name.

113 

114 In the mapping UI, enter these as key/value rows, such as **Key** `repository` with **Value** `my-org/my-repo`, **Key** `ref` with **Value** `refs/heads/main`, and **Key** `workflow_ref` with **Value** `my-org/my-repo/.github/workflows/deploy.yml@refs/heads/main`. If the job uses a GitHub environment, also add **Key** `environment` with **Value** `production`.

115 

116 > **Caution:** Avoid overly broad mappings, such as trusting only `repository_owner == "my-org"`, unless every repository in that owner namespace should be able to mint OpenAI access tokens.

117 

1183. **Choose the OpenAI target.** Set **Project** to the OpenAI project that owns the target service account. Set **Service account** to the OpenAI service account the GitHub workflow can use, such as `github-actions-prod-deploy`.

119 

1204. **Narrow API permissions if needed.** Select appropriate **Permissions** such as `api.model.request` and `api.vector_store.read` to further narrow access tokens minted from this mapping. Leave permissions blank to avoid adding a WIF-specific scope restriction; the token still authorizes as the mapped service account.

121 

122## Using the token in a workflow

123 

124Configure your OpenAI SDK client to request a GitHub OIDC token and exchange it for an OpenAI-issued access token.

125 

126The workflow must grant `id-token: write` permission and pass the workload identity federation settings to the SDK code. The SDK requests the GitHub OIDC token from the `ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN` environment variables that GitHub exposes to the job, then uses the exchanged OpenAI access token to authenticate API requests.

127 

128For example, run your application code from a workflow like this:

129 

130```yaml

131name: deploy

132 

133on:

134 push:

135 branches:

136 - main

137 workflow_dispatch:

138 

139permissions:

140 id-token: write

141 contents: read

142 

143jobs:

144 deploy:

145 runs-on: ubuntu-latest

146 environment: production

147 steps:

148 - uses: actions/checkout@v4

149 

150 - name: Run OpenAI SDK code

151 env:

152 OPENAI_WIF_AUDIENCE: ${{ vars.OPENAI_WIF_AUDIENCE }}

153 OPENAI_IDENTITY_PROVIDER_ID: ${{ vars.OPENAI_IDENTITY_PROVIDER_ID }}

154 OPENAI_SERVICE_ACCOUNT_ID: ${{ vars.OPENAI_SERVICE_ACCOUNT_ID }}

155 run: node ./scripts/call-openai.js

156```

157 

158Store `OPENAI_WIF_AUDIENCE`, `OPENAI_IDENTITY_PROVIDER_ID`, and `OPENAI_SERVICE_ACCOUNT_ID` as GitHub Actions variables. They identify the provider and service account but are not bearer credentials.

159 

160The following examples initialize an OpenAI client with a custom subject token provider. The provider requests a GitHub OIDC token for the configured audience and uses it as the subject token for workload identity federation.

161 

162## GitHub Actions best practices

163 

164- Use environment protections for production deployments. Require approvals or branch restrictions before workflows can access production OpenAI resources.

165- Restrict mappings by repository. Match on repository-specific claims whenever possible instead of allowing access from all repositories within an organization.

166- Restrict mappings by branch or workflow. Consider matching claims such as `repository`, `ref`, `environment`, or `workflow_ref` to limit token issuance.

167- Use separate OpenAI service accounts for CI/CD and production workloads. Build pipelines often require different permissions than deployed applications.

168- Avoid granting access to pull requests from untrusted forks. Forked pull requests may execute attacker-controlled code and should not receive production credentials.

169- Use short-lived exchanges. GitHub OIDC tokens are intended for ephemeral authentication and should be exchanged only when needed.

170- Audit repository ownership changes. Repository transfers, renames, and permission changes can affect the security assumptions behind existing mappings.

171- Prefer exact claim matching. Match on claims such as `repository`, `ref`, and `environment` instead of relying on organization-wide trust relationships.

Details

1# Configuring workload identity federation for Google Cloud

2 

3import {

4 googleGkeWorkloadIdentitySdk,

5 googleWorkloadIdentitySdk,

6} from "./examples";

7 

8Use Google Cloud as a Workload Identity Provider in either of these scenarios:

9 

10- **Google workload identity:** Exchange a Google-signed OIDC token issued to an attached Google service account for a short-lived OpenAI access token.

11- **Google Kubernetes Engine:** Exchange a projected GKE service account token for a short-lived OpenAI access token.

12 

13 

14 

15<div data-content-switcher-pane data-value="workload-identity">

16 

17## Google workload identity

18 

19Google Cloud workloads can request signed OIDC identity tokens from the Google metadata server without storing long-lived service account keys. In OpenAI workload identity federation, the Google identity token is the subject token that OpenAI validates before issuing an OpenAI access token. This flow works on Compute Engine, Cloud Run, GKE workloads using attached Google service accounts, and other Google-managed runtimes that expose the metadata server identity endpoint.

20 

21### Setting up Google workload identity

22 

23Create a Google service account for the workload that needs to call the OpenAI API. For the full setup flow, see Google's guide to [create service accounts](https://docs.cloud.google.com/iam/docs/service-accounts-create).

24 

25For example, create a service account with the Google Cloud CLI:

26 

27```bash

28gcloud iam service-accounts create openai-wif \

29 --description="Service account for OpenAI workload identity federation" \

30 --display-name="OpenAI workload identity federation"

31```

32 

33Create the Compute Engine VM with the service account attached, or attach the service account to the Google Cloud resource running your application. The resource must be able to call the Google metadata server at runtime. For VM setup details, see Google's guide to [create a VM that uses a user-managed service account](https://docs.cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances).

34 

35Do not create or download service account keys for this flow. The workload uses the attached service account and the metadata server to request a short-lived OIDC token.

36 

37### Getting a Google identity token

38 

39From the Google Cloud resource with the service account attached, request an OIDC identity token from the metadata server with the configured audience. This token is the subject token that OpenAI exchanges for an OpenAI-issued access token.

40 

41```bash

42AUDIENCE="https://api.openai.com/v1"

43 

44TOKEN=$(curl -sS -G -H "Metadata-Flavor: Google" \

45 "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity" \

46 --data-urlencode "audience=${AUDIENCE}")

47```

48 

49The metadata server returns a Google-signed JWT. For more information about the metadata server identity endpoint, see Google's guide to [verify VM identity](https://docs.cloud.google.com/compute/docs/instances/verifying-instance-identity).

50 

51### Verify the token

52 

53Before configuring workload identity federation, decode a sample Google identity token locally and inspect its claims:

54 

55```bash

56TOKEN="$TOKEN" python3 - <<'PY'

57import base64

58import json

59import os

60 

61payload = os.environ["TOKEN"].split(".")[1]

62payload += "=" * (-len(payload) % 4)

63print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))

64PY

65```

66 

67This command decodes the JWT payload without verifying the token signature. Use a local decoder for production tokens, and avoid pasting production tokens into third-party tools.

68 

69A decoded Google metadata server identity token will look similar to:

70 

71```json

72{

73 "iss": "https://accounts.google.com",

74 "aud": "https://api.openai.com/v1",

75 "azp": "110123456789012345678",

76 "sub": "110123456789012345678",

77 "email": "openai-wif@my-project.iam.gserviceaccount.com",

78 "email_verified": true,

79 "iat": 1716235422,

80 "exp": 1716239022

81}

82```

83 

84Use the decoded payload to compare the token you received with the issuer, audience, and mapping values configured in OpenAI. Most configuration issues are visible in the `iss`, `aud`, `email`, and `sub` claims before you exchange the token.

85 

86### Setting up workload identity federation

87 

88Create a Workload Identity Provider in OpenAI for Google-issued identity tokens, then add a service account mapping that matches stable claims from the token.

89 

90Configure the Workload Identity Provider first, then create the service account mapping.

91 

92#### Set up the Workload Identity Provider

93 

941. **Create the Workload Identity Provider.** Set **Name** to a unique value, such as `google-workload-identity-prod`. Use **Description**, such as `Production Google Cloud workloads`, to help admins identify the provider.

95 

962. **Set the issuer and audience.** Set **OIDC Issuer URL** to `https://accounts.google.com`. Set **Audience** to the custom audience your workload requests from the Google metadata server, such as `https://api.openai.com/v1`. This value must match the token's `aud` claim.

97 

983. **Use Google OIDC discovery.** Leave **Use uploaded JWKS for token verification** disabled. OpenAI uses Google's OIDC discovery metadata and JWKS to verify the Google-signed identity token.

99 

1004. **Add attribute transformations if you need derived mapping attributes.** For example, enter `subject` with expression `assertion.sub` to create `openai.subject` from the subject claim. The dashboard applies the `openai.` prefix automatically. Raw token claims that already start with `openai.` are ignored for `openai.` mapping keys unless a matching transformation is configured.

101 

102#### Set up the service account mapping

103 

1041. **Create a service account mapping.** Set **Name** to a unique value within the Workload Identity Provider, such as `compute-openai-wif`. Use **Description**, such as `Production Compute Engine OpenAI API workload`, to explain which workload can use the mapping.

105 

1062. **Match stable Google service account claims.** Add one **Key** and **Value** row for each claim that must match. Use `sub` as the primary identity binding because it is stable and unique. You may additionally match `email` for readability.

107 

1083. **Choose the OpenAI target.** Set **Project** to the OpenAI project that owns the target service account. Set **Service account** to the OpenAI service account the Google Cloud workload can use, such as `google-workload-identity-prod-openai-wif`.

109 

1104. **Narrow API permissions if needed.** Select appropriate **Permissions** such as `api.model.request` and `api.vector_store.read` to further narrow access tokens minted from this mapping. Leave permissions blank to avoid adding a WIF-specific scope restriction; the token still authorizes as the mapped service account.

111 

112### Using the token in code

113 

114Configure your OpenAI SDK client to request a Google identity token from the metadata server and exchange it for an OpenAI-issued access token.

115 

116Set `OPENAI_WIF_AUDIENCE` to the custom audience configured as the Workload Identity Provider audience. The SDK requests a Google identity token for that audience, exchanges it for an OpenAI-issued access token, and uses the OpenAI token to authenticate API requests.

117 

118</div>

119 

120 <div data-content-switcher-pane data-value="gke" hidden>

121 

122## Google Kubernetes Engine

123 

124Use Google Kubernetes Engine as a Workload Identity Provider by exchanging a GKE-issued projected service account token for a short-lived OpenAI access token.

125 

126GKE workloads can authenticate using either:

127 

128- A projected Kubernetes service account token issued by the cluster OIDC issuer.

129- A Google service account identity token obtained through GKE Workload Identity, where a Kubernetes service account is bound to a Google service account.

130 

131Use projected Kubernetes service account tokens when you want OpenAI to trust the cluster's OIDC issuer directly. Use GKE Workload Identity when your workload already relies on a Google service account identity and you want OpenAI to trust Google-issued identity tokens instead.

132 

133If your GKE workload is configured with GKE Workload Identity and can request

134 Google identity tokens from the metadata server, follow the [Google workload

135 identity](#google-workload-identity) instructions above instead of the GKE

136 projected token flow.

137 

138### Setting up GKE

139 

140These instructions assume a managed GKE cluster. For a self-managed Kubernetes cluster, use the [Kubernetes guide](https://developers.openai.com/api/docs/guides/workload-identity-federation/kubernetes).

141 

142Use a Kubernetes `ServiceAccount` for the GKE workload that needs to call the OpenAI API. If you do not already have one, create it:

143 

144```bash

145kubectl create serviceaccount openai-wif --namespace default

146```

147 

148Retrieve the issuer URL associated with the GKE cluster:

149 

150```bash

151kubectl get --raw /.well-known/openid-configuration | jq -r .issuer

152```

153 

154Example output:

155 

156```text

157https://container.googleapis.com/v1/projects/my-project/locations/us-central1/clusters/openai-wif

158```

159 

160The issuer you configure in the OpenAI Workload Identity Provider must match this issuer URL and the `iss` claim in the projected GKE service account token.

161 

162Configure the projected service account token with the audience OpenAI expects and an expiration suitable for your workload. OpenAI validates the token's issuer, signature, audience, and expiration. In this example, the token file is mounted at `/var/run/secrets/tokens/token`, uses the audience `https://api.openai.com/v1`, and expires after 3600 seconds. You may use a different audience if the projected token audience and OpenAI Workload Identity Provider audience match:

163 

164```yaml

165apiVersion: v1

166kind: Pod

167metadata:

168 name: openai-wif-app

169 namespace: default

170spec:

171 serviceAccountName: openai-wif

172 containers:

173 - name: app

174 image: my-image

175 volumeMounts:

176 - name: gke-sa-token

177 mountPath: /var/run/secrets/tokens

178 readOnly: true

179 volumes:

180 - name: gke-sa-token

181 projected:

182 sources:

183 - serviceAccountToken:

184 path: token

185 audience: "https://api.openai.com/v1"

186 expirationSeconds: 3600

187```

188 

189### Verify the token

190 

191Before configuring workload identity federation, decode a sample projected service account token locally and inspect its claims. From a running pod with the projected token mounted:

192 

193```bash

194TOKEN=$(kubectl exec -n default openai-wif-app -- cat /var/run/secrets/tokens/token)

195 

196TOKEN="$TOKEN" python3 - <<'PY'

197import base64

198import json

199import os

200 

201payload = os.environ["TOKEN"].split(".")[1]

202payload += "=" * (-len(payload) % 4)

203print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))

204PY

205```

206 

207This command decodes the JWT payload without verifying the token signature. Use a local decoder for production tokens, and avoid pasting production tokens into third-party tools.

208 

209A decoded GKE projected service account token will look similar to:

210 

211```json

212{

213 "iss": "https://container.googleapis.com/v1/projects/my-project/locations/us-central1/clusters/openai-wif",

214 "aud": ["https://api.openai.com/v1"],

215 "sub": "system:serviceaccount:default:openai-wif",

216 "iat": 1716235422,

217 "exp": 1716239022,

218 "kubernetes.io": {

219 "namespace": "default",

220 "serviceaccount": {

221 "name": "openai-wif",

222 "uid": "11111111-2222-3333-4444-555555555555"

223 }

224 }

225}

226```

227 

228Use the decoded payload to compare the token you received with the issuer, audience, and mapping values configured in OpenAI. Most configuration issues are visible in the `iss`, `aud`, and `sub` claims before you exchange the token.

229 

230### Setting up workload identity federation

231 

232Create a Workload Identity Provider in OpenAI for the GKE issuer, then add a service account mapping that matches attributes from the projected token.

233 

234Configure the Workload Identity Provider first, then create the service account mapping.

235 

236#### Set up the Workload Identity Provider

237 

2381. **Create the Workload Identity Provider.** Set **Name** to a unique value, such as `google-gke-prod`. Use **Description**, such as `Production GKE cluster`, to help admins identify the cluster.

239 

2402. **Set the issuer and audience.** Set **OIDC Issuer URL** to the issuer returned by `kubectl get --raw /.well-known/openid-configuration | jq -r .issuer`. This value must match the `iss` claim in the projected GKE service account token. Set **Audience** to the same audience configured on the projected service account token volume. In this example, that value is `https://api.openai.com/v1`.

241 

2423. **Use GKE OIDC discovery.** Leave **Use uploaded JWKS for token verification** disabled. OpenAI uses the GKE issuer's OIDC discovery metadata and JWKS to verify the projected service account token.

243 

2444. **Add attribute transformations if you need derived mapping attributes.** For example, enter `gke_subject` with expression `assertion.sub` to create `openai.gke_subject`. The dashboard applies the `openai.` prefix automatically. Raw token claims that already start with `openai.` are ignored for `openai.` mapping keys unless a matching transformation is configured.

245 

246#### Set up the service account mapping

247 

2481. **Create a service account mapping.** Set **Name** to a unique value within the Workload Identity Provider, such as `default-openai-wif`. Use **Description**, such as `Default namespace GKE OpenAI API workload`, to explain which workload can use the mapping.

249 

2502. **Match the GKE service account subject.** Set **Key** to `sub` and **Value** to `system:serviceaccount:default:openai-wif`. For GKE service accounts, the subject format is `system:serviceaccount:<namespace>:<service-account-name>`.

251 

2523. **Choose the OpenAI target.** Set **Project** to the OpenAI project that owns the target service account. Set **Service account** to the OpenAI service account the GKE workload can use, such as `google-gke-prod-openai-wif`.

253 

2544. **Narrow API permissions if needed.** Select appropriate **Permissions** such as `api.model.request` and `api.vector_store.read` to further narrow access tokens minted from this mapping. Leave permissions blank to avoid adding a WIF-specific scope restriction; the token still authorizes as the mapped service account.

255 

256### Using the token in code

257 

258Configure your OpenAI SDK client to read the projected GKE service account token and exchange it for an OpenAI-issued access token.

259 

260Use the mounted token path, such as `/var/run/secrets/tokens/token`, as the subject token source for the SDK workload identity federation provider. The SDK exchanges that GKE token for an OpenAI-issued access token and uses the OpenAI token to authenticate API requests.

261 

262The following examples initialize an OpenAI client with a custom subject token provider. The provider reads the projected GKE service account token from the mounted file path and uses it as the subject token for workload identity federation.

263 

264</div>

265 

266 

267 

268## Google Cloud best practices

269 

270- Use dedicated Google service accounts for each workload. Avoid sharing service accounts across unrelated services or environments.

271- Use workload identity flows instead of long-lived service account keys. Avoid distributing and rotating JSON key files for workloads that can use metadata-server identity tokens or GKE Workload Identity.

272- Scope identities to the smallest practical workload boundary. Separate service accounts for individual applications provide clearer auditing and least-privilege access.

273- Use attribute-based mappings carefully. Prefer stable identifiers such as service account subject claims over mutable metadata where possible.

274- Separate production and non-production projects. Distinct projects reduce the risk of accidental privilege sharing and simplify auditing.

275- Grant only required IAM permissions. Restrict the Google identity to only the permissions required for the workload.

276- Monitor service account usage. Unexpected token exchanges may indicate configuration drift or compromised workloads.

Details

1# Configuring workload identity federation for Kubernetes

2 

3Use Kubernetes as a Workload Identity Provider by exchanging a projected Kubernetes service account token for a short-lived OpenAI access token.

4 

5## Setting up Kubernetes

6 

7This guide assumes Kubernetes service account token projection is enabled, which is available by default in modern Kubernetes releases. OpenAI workload identity federation requires OIDC-compatible projected service account tokens. Legacy Kubernetes service account tokens stored in Secrets are not supported.

8 

9Use a Kubernetes `ServiceAccount` for the workload that needs to call the OpenAI API. If you do not already have one, create it:

10 

11```bash

12kubectl create serviceaccount openai-wif --namespace default

13```

14 

15Get the OIDC issuer for your Kubernetes cluster:

16 

17```bash

18kubectl get --raw /.well-known/openid-configuration | jq -r .issuer

19```

20 

21Even if you upload the JWKS and OpenAI does not perform JWKS discovery against the OIDC issuer, this issuer must match the issuer configured in the Workload Identity Provider.

22 

23Get the cluster JWKS and save the returned key set. You will need it when configuring the Workload Identity Provider:

24 

25```bash

26kubectl get --raw /openid/v1/jwks

27```

28 

29Configure the projected service account token with the audience OpenAI expects and an expiration suitable for your workload. OpenAI validates the token's issuer, signature, audience, and expiration. In this example, the token file is mounted at `/var/run/secrets/tokens/token`, uses the audience `https://api.openai.com/v1`, and expires after 3600 seconds. You may use a different audience if the projected token audience and OpenAI Workload Identity Provider audience match:

30 

31```yaml

32apiVersion: v1

33kind: Pod

34metadata:

35 name: openai-wif-app

36 namespace: default

37spec:

38 serviceAccountName: openai-wif

39 containers:

40 - name: app

41 image: my-image

42 volumeMounts:

43 - name: ksa-token

44 mountPath: /var/run/secrets/tokens

45 readOnly: true

46 volumes:

47 - name: ksa-token

48 projected:

49 sources:

50 - serviceAccountToken:

51 path: token

52 audience: "https://api.openai.com/v1"

53 expirationSeconds: 3600

54```

55 

56## Verify the token

57 

58Before configuring workload identity federation, decode a sample projected service account token locally and inspect its claims. From a running pod with the projected token mounted:

59 

60```bash

61TOKEN=$(kubectl exec -n default openai-wif-app -- cat /var/run/secrets/tokens/token)

62 

63TOKEN="$TOKEN" python3 - <<'PY'

64import base64

65import json

66import os

67 

68payload = os.environ["TOKEN"].split(".")[1]

69payload += "=" * (-len(payload) % 4)

70print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))

71PY

72```

73 

74This command decodes the JWT payload without verifying the token signature. Use a local decoder for production tokens, and avoid pasting production tokens into third-party tools.

75 

76A decoded Kubernetes projected service account token will look similar to:

77 

78```json

79{

80 "iss": "https://kubernetes.example.com",

81 "aud": ["https://api.openai.com/v1"],

82 "sub": "system:serviceaccount:default:openai-wif",

83 "iat": 1716235422,

84 "exp": 1716239022,

85 "kubernetes.io": {

86 "namespace": "default",

87 "serviceaccount": {

88 "name": "openai-wif",

89 "uid": "11111111-2222-3333-4444-555555555555"

90 }

91 }

92}

93```

94 

95Use the decoded payload to compare the token you received with the issuer, audience, and mapping values configured in OpenAI. Most configuration issues are visible in the `iss`, `aud`, and `sub` claims before you exchange the token.

96 

97## Setting up workload identity federation

98 

99Create a Workload Identity Provider in OpenAI for the Kubernetes issuer, then add a service account mapping that matches attributes from the projected token.

100 

101Configure the Workload Identity Provider first, then create the service account mapping.

102 

103### Set up the Workload Identity Provider

104 

1051. **Create the Workload Identity Provider.** Set **Name** to a unique value, such as `kubernetes-prod`. Use **Description**, such as `Production Kubernetes cluster`, to help admins identify the cluster.

106 

1072. **Set the issuer and audience.** Set **OIDC Issuer URL** to the issuer returned by `kubectl get --raw /.well-known/openid-configuration | jq -r .issuer`. This value must match the `iss` claim in the projected token. Set **Audience** to the same opaque audience string configured on the projected service account token volume. In this example, that value is `https://api.openai.com/v1`.

108 

1093. **Upload the Kubernetes JWKS.** Enable **Use uploaded JWKS for token verification**, then set **JWKS JSON** to the output from `kubectl get --raw /openid/v1/jwks`. OpenAI uses this public key set to verify projected Kubernetes service account tokens. Upload the full key set including the surrounding `keys`.

110 

111 > **Note:** For self-hosted Kubernetes clusters, OpenAI supports only local JWKS mode. Upload the JWKS returned by your cluster; OpenAI does not perform OIDC discovery against the configured issuer. OpenAI still compares the configured issuer with the `iss` field in the token.

112 

113 If your cluster rotates service account signing keys, update the uploaded JWKS in the Workload Identity Provider configuration. Tokens signed by keys that are not present in the configured JWKS are rejected. If the JWKS contains multiple active public keys, include the full `keys` array.

114 

1154. **Add attribute transformations only if you need derived mapping attributes.** Raw token claims such as `sub`, `aud`, and `iss` can be used directly in mapping assertions. If you plan to match on transformed attributes rather than raw token claims, the dashboard applies the `openai.` prefix automatically; for example, enter `workload_subject` with expression `assertion.sub` to create `openai.workload_subject`. Raw token claims that already start with `openai.` are ignored for `openai.` mapping keys unless a matching transformation is configured.

116 

117### Set up the service account mapping

118 

1191. **Create a service account mapping.** Set **Name** to a unique value within the Workload Identity Provider, such as `openai-mapping-kubernetes`. Use **Description**, such as `Workload Identity Provider Mapping for Kubernetes Workloads`, to explain which workload can use the mapping.

120 

1212. **Match the Kubernetes service account subject.** Set **Key** to `sub` and **Value** to `system:serviceaccount:default:openai-wif`. For Kubernetes service accounts, the subject format is `system:serviceaccount:<namespace>:<service-account-name>`.

122 

1233. **Choose the OpenAI target.** Set **Project** to the OpenAI project that owns the target service account. Set **Service account** to the OpenAI service account the Kubernetes workload can use, such as `kubernetes-prod-openai-wif`. Check `Create a new service account in this project` if you wish to create a new service account for this mapping rather than reuse an existing one.

124 

1254. **Narrow API permissions if needed.** Select appropriate **Permissions** such as `api.model.request` and `api.vector_store.read` to further narrow access tokens minted from this mapping. Leave permissions blank to avoid adding a WIF-specific scope restriction; the token still authorizes as the mapped service account.

126 

127## Using the token in code

128 

129Configure your OpenAI SDK client to read the projected Kubernetes token and exchange it for an OpenAI-issued access token.

130 

131Use the mounted token path, such as `/var/run/secrets/tokens/token`, as the subject token source for the SDK workload identity federation provider. The SDK exchanges that Kubernetes token for an OpenAI-issued access token and uses the OpenAI token to authenticate API requests.

132 

133The following examples initialize an OpenAI client with a custom subject token provider. The provider reads the projected Kubernetes service account token from the mounted file path and uses it as the subject token for workload identity federation.

134 

135## Kubernetes best practices

136 

137- Use a stable OIDC issuer. The issuer URL must match the projected service account token `iss` claim and should remain stable across cluster upgrades and maintenance operations.

138- Protect signing keys carefully. Anyone with access to the cluster's service account signing keys can mint tokens that may be accepted by OpenAI.

139- Use dedicated service accounts for OpenAI integrations. Avoid reusing service accounts that are also used for unrelated infrastructure or application access.

140- Keep the uploaded JWKS current. OpenAI uses the configured JWKS to validate workload identity tokens in local JWKS mode, so update the Workload Identity Provider before rotating to new signing keys.

141- Minimize custom claim complexity. Prefer matching on standard claims such as `sub` and `aud`, or transformed attributes derived directly from those claims.

142- Treat namespace ownership as part of your security model. If namespace administrators can create service accounts, ensure mappings are scoped appropriately to prevent unintended privilege escalation.

143- Monitor issuer and signing key changes. Rotating signing keys without updating the Workload Identity Provider JWKS can cause token exchange failures.

Details

1# Configuring workload identity federation for Microsoft Azure

2 

3import {

4 azureAksWorkloadIdentitySdk,

5 azureManagedIdentityWorkloadIdentitySdk,

6} from "./examples";

7 

8Use Microsoft Azure as a Workload Identity Provider in either of these scenarios:

9 

10- **Azure managed identity:** Exchange a Microsoft Entra ID access token issued for a managed identity for a short-lived OpenAI access token.

11- **AKS:** Exchange a projected Azure Kubernetes Service (AKS) service account token for a short-lived OpenAI access token.

12 

13 

14 

15<div data-content-switcher-pane data-value="managed-identity">

16 

17## Azure managed identity

18 

19Azure managed identities let Azure-hosted workloads request Microsoft Entra tokens without storing long-lived secrets. In OpenAI workload identity federation, the managed identity token is the subject token that OpenAI validates before issuing an OpenAI access token.

20 

21### Setting up Azure managed identity

22 

23Create or use a Microsoft Entra application registration that represents the token audience OpenAI should trust. Configure its **Application ID URI**; this URI is the `resource` value your workload requests from Azure Instance Metadata Service (IMDS), and it appears as the `aud` claim in the issued token. For the Microsoft setup steps, see the Microsoft Entra guide to [create a new Entra ID application and service principal](https://learn.microsoft.com/en-au/entra/identity-platform/howto-create-service-principal-portal#register-an-application-with-azure-ad-and-create-a-service-principal).

24 

25The Application ID URI configured in Microsoft Entra ID, the IMDS `resource`

26 parameter, the resulting token's `aud` claim, and the OpenAI Workload Identity

27 Provider audience must all match.

28 

29[Create](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/manage-user-assigned-managed-identities-azure-portal?pivots=identity-mi-methods-azp) a managed identity, then [assign](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm#user-assigned-managed-identity) that managed identity to the Azure resource running your application, such as a virtual machine. The resource must be able to call IMDS at runtime. For Azure setup details, see Microsoft's [managed identities overview](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) and the relevant Azure resource documentation for assigning the identity.

30 

31### Getting an Azure managed identity token

32 

33From the Azure resource with the managed identity assigned, request a token from IMDS with the Application ID URI as the `resource` parameter. This token is the subject token that OpenAI exchanges for an OpenAI-issued access token.

34 

35```bash

36APPLICATION_ID_URI="api://<application-client-id>"

37 

38TOKEN=$(curl -sS -G -H "Metadata: true" \

39 "http://169.254.169.254/metadata/identity/oauth2/token" \

40 --data-urlencode "api-version=2018-02-01" \

41 --data-urlencode "resource=${APPLICATION_ID_URI}" \

42 | jq -r .access_token)

43```

44 

45If the resource has multiple user-assigned managed identities, add the `client_id`, `object_id`, or `msi_res_id` query parameter for the managed identity you want to use. Microsoft documents the IMDS token request parameters in [Use managed identities on a virtual machine to acquire access token](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token).

46 

47### Verify the token

48 

49Before configuring workload identity federation, decode a sample token locally and inspect its claims:

50 

51```bash

52TOKEN="$TOKEN" python3 - <<'PY'

53import base64

54import json

55import os

56 

57payload = os.environ["TOKEN"].split(".")[1]

58payload += "=" * (-len(payload) % 4)

59print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))

60PY

61```

62 

63This command decodes the JWT payload without verifying the token signature. Use a local decoder for production tokens, and avoid pasting production tokens into third-party tools.

64 

65A decoded Microsoft Entra ID managed identity token will look similar to:

66 

67```json

68{

69 "iss": "https://login.microsoftonline.com/11111111-2222-3333-4444-555555555555/v2.0",

70 "aud": "api://00000000-1111-2222-3333-444444444444",

71 "tid": "11111111-2222-3333-4444-555555555555",

72 "appid": "22222222-3333-4444-5555-666666666666",

73 "oid": "33333333-4444-5555-6666-777777777777",

74 "sub": "33333333-4444-5555-6666-777777777777",

75 "xms_mirid": "/subscriptions/<subscription-id>/resourcegroups/my-resource-group/providers/Microsoft.Compute/virtualMachines/openai-wif-vm",

76 "iat": 1716235422,

77 "exp": 1716239022

78}

79```

80 

81Verify the claims you plan to configure in OpenAI:

82 

83- `iss`: Use the exact issuer value from the token. The issuer may be `https://login.microsoftonline.com/<tenant-id>/v2.0`, but do not assume that suffix.

84- `aud`: Must match the Application ID URI, the IMDS `resource` parameter, and the OpenAI Workload Identity Provider audience.

85- `tid`: The Microsoft Entra tenant ID.

86- `appid`: The managed identity's application/client ID, when present.

87 

88Managed identity tokens can also contain claims such as `azp`, `oid`, `sub`, or `xms_mirid`. Use the decoded token as the source of truth, and choose claims that identify the exact managed identity and resource boundary you trust.

89 

90Use the decoded payload to compare the token you received with the issuer, audience, and mapping values configured in OpenAI. Most configuration issues are visible in the `iss`, `aud`, `tid`, and managed identity claims before you exchange the token.

91 

92### Setting up workload identity federation

93 

94Create a Workload Identity Provider in OpenAI for the Microsoft Entra ID issuer, then add a service account mapping that matches stable claims from the managed identity token.

95 

96Configure the Workload Identity Provider first, then create the service account mapping.

97 

98#### Set up the Workload Identity Provider

99 

1001. **Create the Workload Identity Provider.** Set **Name** to a unique value, such as `azure-managed-identity-prod`. Use **Description**, such as `Production Azure managed identity workloads`, to help admins identify the provider.

101 

1022. **Set the issuer and audience.** Set **OIDC Issuer URL** to the exact value of the token's `iss` claim. Obtain a sample managed identity token and inspect its claims first. For example, the issuer may be `https://login.microsoftonline.com/<tenant-id>/v2.0`. Set **Audience** to the Microsoft Entra Application ID URI you configured, such as `api://<application-client-id>`. This value must match the token's `aud` claim.

103 

1043. **Use Microsoft Entra token verification.** Leave **Use uploaded JWKS for token verification** disabled. OpenAI uses Microsoft Entra issuer metadata and JWKS to verify the managed identity token.

105 

1064. **Add attribute transformations if you need derived mapping attributes.** For example, enter `managed_identity_client_id` with expression `assertion.appid` to create `openai.managed_identity_client_id` from the managed identity application/client ID claim. The dashboard applies the `openai.` prefix automatically. Raw token claims that already start with `openai.` are ignored for `openai.` mapping keys unless a matching transformation is configured.

107 

108#### Set up the service account mapping

109 

1101. **Create a service account mapping.** Set **Name** to a value that is unique within that Workload Identity Provider, such as `vm-openai-wif`. Use **Description**, such as `Production VM Azure managed identity workload`, to explain which workload can use the mapping.

111 

1122. **Match stable managed identity claims.** Add one **Key** and **Value** row for each claim that must match. If the token contains `appid`, set **Key** to `appid` and **Value** to the managed identity client ID. The `appid` claim identifies the managed identity's application/client ID and is generally the most stable claim for binding a mapping to a specific managed identity. If your token does not contain `appid`, use another stable claim from the decoded token, such as `azp`, `oid`, `sub`, or `xms_mirid`. To bind the mapping to one tenant, also set **Key** to `tid` and **Value** to the Microsoft Entra tenant ID. Decode a sample token from IMDS and use claims that are stable for the managed identity and resource you trust.

113 

1143. **Choose the OpenAI target.** Set **Project** to the OpenAI project that owns the target service account. Set **Service account** to the OpenAI service account the Azure workload can use, such as `azure-managed-identity-prod-openai-wif`.

115 

1164. **Narrow API permissions if needed.** Select appropriate **Permissions** such as `api.model.request` and `api.vector_store.read` to further narrow access tokens minted from this mapping. Leave permissions blank to avoid adding a WIF-specific scope restriction; the token still authorizes as the mapped service account.

117 

118### Using the token in code

119 

120Configure your OpenAI SDK client to request an Azure managed identity token from IMDS and exchange it for an OpenAI-issued access token.

121 

122Set `OPENAI_WIF_AUDIENCE` to the Microsoft Entra Application ID URI configured as the Workload Identity Provider audience. The SDK requests a managed identity token for that audience, exchanges it for an OpenAI-issued access token, and uses the OpenAI token to authenticate API requests.

123 

124</div>

125 

126 <div data-content-switcher-pane data-value="aks" hidden>

127 

128## Azure Kubernetes Service (AKS)

129 

130Use AKS as a Workload Identity Provider by exchanging an AKS-issued projected service account token for a short-lived OpenAI access token.

131 

132AKS workloads can also use Azure Workload Identity to obtain a Microsoft Entra

133 ID access token for a managed identity attached to the workload. In that

134 configuration, OpenAI validates the Microsoft Entra token rather than the

135 projected Kubernetes service account token. Configure OpenAI workload identity

136 federation using the steps in [Azure managed

137 identity](#azure-managed-identity), and configure Azure Workload Identity

138 according to Microsoft's documentation.

139 

140### Setting up AKS

141 

142Retrieve the OIDC issuer URL associated with the AKS cluster:

143 

144```bash

145az aks show \

146 --name <cluster-name> \

147 --resource-group <resource-group> \

148 --query "oidcIssuerProfile.issuerUrl" \

149 --output tsv

150```

151 

152If the issuer URL is empty, enable the AKS OIDC issuer for the cluster. Use the following command:

153 

154```bash

155az aks update \

156 --resource-group <resource-group> \

157 --name <cluster-name> \

158 --enable-oidc-issuer

159```

160 

161The issuer you configure in the OpenAI Workload Identity Provider must match this issuer URL and the `iss` claim in the projected AKS service account token.

162 

163Use a Kubernetes `ServiceAccount` for the AKS workload that needs to call the OpenAI API. If you do not already have one, create it:

164 

165```bash

166kubectl create serviceaccount openai-wif --namespace default

167```

168 

169Configure the projected service account token with the audience OpenAI expects and an expiration suitable for your workload. OpenAI validates the token's issuer, signature, audience, and expiration. In this example, the token file is mounted at `/var/run/secrets/tokens/token`, uses the audience `https://api.openai.com/v1`, and expires after 3600 seconds. You may use a different audience if the projected token audience and OpenAI Workload Identity Provider audience match.

170 

171```yaml

172apiVersion: v1

173kind: Pod

174metadata:

175 name: openai-wif-app

176 namespace: default

177spec:

178 serviceAccountName: openai-wif

179 containers:

180 - name: app

181 image: my-image

182 volumeMounts:

183 - name: aks-sa-token

184 mountPath: /var/run/secrets/tokens

185 readOnly: true

186 volumes:

187 - name: aks-sa-token

188 projected:

189 sources:

190 - serviceAccountToken:

191 path: token

192 audience: "https://api.openai.com/v1"

193 expirationSeconds: 3600

194```

195 

196### Verify the token

197 

198Before configuring workload identity federation, decode a sample projected service account token locally and inspect its claims. From a running pod with the projected token mounted:

199 

200```bash

201TOKEN=$(kubectl exec -n default openai-wif-app -- cat /var/run/secrets/tokens/token)

202 

203TOKEN="$TOKEN" python3 - <<'PY'

204import base64

205import json

206import os

207 

208payload = os.environ["TOKEN"].split(".")[1]

209payload += "=" * (-len(payload) % 4)

210print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))

211PY

212```

213 

214This command decodes the JWT payload without verifying the token signature. Use a local decoder for production tokens, and avoid pasting production tokens into third-party tools.

215 

216A decoded AKS projected service account token will look similar to:

217 

218```json

219{

220 "iss": "https://eastus.oic.prod-aks.azure.com/11111111-2222-3333-4444-555555555555/22222222-3333-4444-5555-666666666666/",

221 "aud": ["https://api.openai.com/v1"],

222 "sub": "system:serviceaccount:default:openai-wif",

223 "iat": 1716235422,

224 "exp": 1716239022,

225 "kubernetes.io": {

226 "namespace": "default",

227 "serviceaccount": {

228 "name": "openai-wif",

229 "uid": "11111111-2222-3333-4444-555555555555"

230 }

231 }

232}

233```

234 

235Verify the claims you plan to configure in OpenAI:

236 

237- `iss`: Must match the AKS issuer URL configured in the OpenAI Workload Identity Provider.

238- `aud`: Must match the projected service account token audience and the OpenAI Workload Identity Provider audience.

239- `sub`: Must match the Kubernetes service account subject you configure in the service account mapping.

240 

241Use the decoded payload to compare the token you received with the issuer, audience, and mapping values configured in OpenAI. Most configuration issues are visible in the `iss`, `aud`, and `sub` claims before you exchange the token.

242 

243### Setting up workload identity federation

244 

245Create a Workload Identity Provider in OpenAI for the AKS issuer, then add a service account mapping that matches attributes from the projected token.

246 

247Configure the Workload Identity Provider first, then create the service account mapping.

248 

249#### Set up the Workload Identity Provider

250 

2511. **Create the Workload Identity Provider.** Set **Name** to a unique value, such as `azure-aks-prod`. Use **Description**, such as `Production AKS cluster`, to help admins identify the cluster.

252 

2532. **Set the issuer and audience.** Set **OIDC Issuer URL** to the issuer returned by `az aks show --query "oidcIssuerProfile.issuerUrl"`. This value must match the `iss` claim in the projected AKS service account token. Set **Audience** to the same audience configured on the projected service account token volume. In this example, that value is `https://api.openai.com/v1`.

254 

2553. **Use AKS OIDC discovery.** Leave **Use uploaded JWKS for token verification** disabled. OpenAI uses the AKS issuer's OIDC discovery metadata and JWKS to verify the projected service account token.

256 

2574. **Add attribute transformations if you need derived mapping attributes.** For example, enter `aks_subject` with expression `assertion.sub` to create `openai.aks_subject`. The dashboard applies the `openai.` prefix automatically. Raw token claims that already start with `openai.` are ignored for `openai.` mapping keys unless a matching transformation is configured.

258 

259#### Set up the service account mapping

260 

2611. **Create a service account mapping.** Set **Name** to a value that is unique within that Workload Identity Provider, such as `default-openai-wif`. Use **Description**, such as `Default namespace AKS OpenAI API workload`, to explain which workload can use the mapping.

262 

2632. **Match the AKS service account subject.** Set **Key** to `sub` and **Value** to `system:serviceaccount:default:openai-wif`. For AKS service accounts, the subject format is `system:serviceaccount:<namespace>:<service-account-name>`.

264 

265 The Workload Identity Provider restricts tokens to the configured AKS issuer. The service account mapping further restricts access to the specified Kubernetes service account subject.

266 

2673. **Choose the OpenAI target.** Set **Project** to the OpenAI project that owns the target service account. Set **Service account** to the OpenAI service account the AKS workload can use, such as `azure-aks-prod-openai-wif`.

268 

2694. **Narrow API permissions if needed.** Select appropriate **Permissions** such as `api.model.request` and `api.vector_store.read` to further narrow access tokens minted from this mapping. Leave permissions blank to avoid adding a WIF-specific scope restriction; the token still authorizes as the mapped service account.

270 

271### Using the token in code

272 

273Configure your OpenAI SDK client to read the projected AKS service account token and exchange it for an OpenAI-issued access token.

274 

275Use the mounted token path, such as `/var/run/secrets/tokens/token`, as the subject token source for the SDK workload identity federation provider. The SDK exchanges that AKS token for an OpenAI-issued access token and uses the OpenAI token to authenticate API requests.

276 

277The following examples initialize an OpenAI client with a custom subject token provider. The provider reads the projected AKS service account token from the mounted file path and uses it as the subject token for workload identity federation.

278 

279</div>

280 

281 

282 

283## Microsoft Azure best practices

284 

285- Use managed identities whenever possible. Managed identities provide a simpler and more secure authentication model than distributing credentials manually.

286- Use separate managed identities, Microsoft Entra applications, and OpenAI mappings for different applications and environments. Avoid sharing one identity across development, staging, and production workloads.

287- Restrict accepted audiences. Configure only the audiences required for OpenAI workload identity federation.

288- Use dedicated Microsoft Entra ID applications for security boundaries. Separate applications provide clearer ownership, auditing, and access management.

289- Prefer workload-specific mappings. Match on workload-specific claims rather than broad tenant-wide attributes.

290- Review federated credential configurations regularly. Stale federated credentials can unintentionally continue granting access long after workloads are retired.

291- Separate production and non-production identities. Production workloads should authenticate through distinct federated identities and OpenAI service accounts.