Skip to navigation

GitHub Actions Workload Identity

GitHub Actions can issue a short-lived OIDC token for each workflow job. Mixlayer verifies the token’s repository and workflow claims and exchanges it for a short-lived Mixlayer access token, so the repository does not need a long-lived Mixlayer API-key secret.

1. Record stable repository identifiers

Find the repository and owner numeric IDs with the GitHub CLI:

gh api repos/example-org/example-repo \
--jq '{repository_id: .id, repository_owner_id: .owner.id}'

Numeric IDs remain stable across repository and organization renames. Use names such as repository for readability, but use IDs for the main admission boundary.

2. Configure the Mixlayer provider

Create an OIDC provider in Workload Identity:

SettingValue
Issuer URIhttps://token.actions.githubusercontent.com
Allowed audiencehttps://api.mixlayer.com
JWKS sourceOIDC discovery

Map the job and repository identity:

mixlayer.subject = assertion.sub
attribute.repository_id = assertion.repository_id
attribute.repository_owner_id = assertion.repository_owner_id
attribute.repository = assertion.repository
attribute.ref = assertion.ref
attribute.job_workflow_ref = assertion.job_workflow_ref

Restrict admission to the exact owner and repository IDs:

attribute.repository_owner_id == "12345678" &&
attribute.repository_id == "87654321"

For production access, add a more restrictive first authorization rule before the fallback:

[
{
"condition": "attribute.ref == \"refs/heads/main\" && attribute.job_workflow_ref == \"example-org/example-repo/.github/workflows/deploy.yml@refs/heads/main\"",
"permissions": ["api-read", "inference"]
},
{
"condition": "true",
"permissions": ["inference"]
}
]

The fallback permissions apply to every admitted job. If only the production workflow should authenticate, move its checks into the admission condition instead of relying on the rule above.

GitHub’s default sub format can vary by repository settings and creation date. Inspect a real token and prefer stable repository_id and repository_owner_id claims for the trust boundary.

3. Request and exchange the job token

The job needs id-token: write. This permission allows the job to request an OIDC token; it does not grant write access to repository contents.

Store the non-secret Mixlayer provider ID in a GitHub Actions configuration variable named MIXLAYER_IDENTITY_PROVIDER_ID.

file=.github/workflows/mixlayer.yml
name: Call Mixlayer
on:
workflow_dispatch:
permissions:
contents: read
id-token: write
jobs:
call-mixlayer:
runs-on: ubuntu-latest
env:
MIXLAYER_WIF_AUDIENCE: https://api.mixlayer.com
MIXLAYER_IDENTITY_PROVIDER_ID: ${{ vars.MIXLAYER_IDENTITY_PROVIDER_ID }}
steps:
- name: Exchange GitHub identity and call Mixlayer
shell: bash
run: |
encoded_audience=$(jq -rn \
--arg audience "$MIXLAYER_WIF_AUDIENCE" \
'$audience | @uri')
subject_token=$(curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=$encoded_audience" |
jq -er .value)
mixlayer_token=$(jq -n \
--arg provider "$MIXLAYER_IDENTITY_PROVIDER_ID" \
--arg token "$subject_token" \
'{
grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
subject_token_type: "urn:ietf:params:oauth:token-type:jwt",
subject_token: $token,
identity_provider_id: $provider
}' |
curl --fail-with-body --silent --show-error \
https://api.mixlayer.com/v1/workload_identity/token \
-H "Content-Type: application/json" \
--data-binary @- |
jq -er .access_token)
echo "::add-mask::$mixlayer_token"
curl --fail-with-body https://mixlayer.ai/v1/chat/completions \
-H "Authorization: Bearer $mixlayer_token" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen/qwen3.5-4b-free",
"messages": [{"role": "user", "content": "Hello from GitHub Actions"}]
}'

No Mixlayer secret is stored in GitHub. The workflow receives a new GitHub OIDC token for the job and exchanges it at runtime.

Tighten production policies

  • Use GitHub environments and required reviewers for production deployments.
  • Match the exact job_workflow_ref when a centrally controlled reusable workflow should be the only caller.
  • Match immutable repository and owner IDs before mutable names.
  • Do not grant access based only on the public GitHub issuer and audience; any GitHub repository can request a token for a caller-selected audience.
  • Do not print the GitHub or Mixlayer tokens in workflow logs.