Workload identity federation
Workload identity federation allows cloud-hosted infrastructure in providers like Microsoft Azure, Google Cloud Platform, or GitHub Actions to authenticate to a tailnet or the Tailscale API using provider-native identity tokens instead of Tailscale auth keys or OAuth clients. By leveraging the provider's federated OpenID Connect (OIDC) identities, tailnet administrators can simplify credential management and infrastructure automation.
How it works

When a cloud workload (such as a CI job, serverless function, or virtual machine) wants to join your tailnet or call the Tailscale API, it first asks its own platform for an OIDC token.
The OIDC token is a signed JSON Web Token (JWT) that conveys three assurances from the cloud platform:
- It vouches for the workload's identity.
- It specifies exactly which workload the JWT represents.
- It declares who is permitted to consume the token.
Because the platform signs the token with its publicly advertised keys, anyone can verify the signature and trust that the claims are genuine.
Before any exchange can take place, a tailnet admin establishes trust by specifying the OIDC issuer to trust and defining claim-matching rules that map specific workloads, such as a particular GitHub repository, Google Cloud service account, or Azure workload, onto the tags and API scopes they should receive. Tokens that fail to match these rules are rejected automatically.
The workload then sends that OIDC token to Tailscale's token exchange endpoint. Behind the scenes, Tailscale fetches the issuer's public keys, validates the signature, standard claims (issuer, audience, expiry), and claim-matching rules and then returns a short-lived API token with the scopes you configured when configuring identity federation in the Tailscale admin console.
With this API token, the workload can join or manage the tailnet with the Tailscale API.
Get started
You need to configure a federate identity in the admin console and exchange workload identity tokens with Tailscale.
Configure federated identities in the admin console
Before a cloud workload can use its signed OIDC token to authenticate to Tailscale, you must set up a federated identity in Tailscale and assign all necessary scopes.
- Open the Trust credentials page of the admin console.
- Select the Credential button.
- Select OpenID Connect.
- Select an Issuer from the dropdown. Common cloud providers are included in the dropdown, but any infrastructure provider that supports OIDC for workload identity federation can be used if Custom issuer is selected.
- Enter the Issuer URL for the cloud provider's OIDC issuer if using a Custom issuer.
- Enter the Subject. This value determines the attributes of the workload that must match in order to receive a Tailscale API token. Learn more about the syntax of the subject (
sub) claims for common cloud providers: - (Optional) Add additional Custom claims to further narrow access.
- Select the relevant read and write scopes from the list and select Generate credential.
- Copy the Client ID and Audience (aud claim). These are not secrets, and you will be able to view them in the admin console.
Claim value format
Values specified for the subject and custom claims are matched against claims values in the OIDC JWT.
Values can contain an * to match against any character. Other characters specified must directly match the value of the sub claim.
For example, specifying my-example-sub/* for the subject will successfully match sub claims that start with my-example-sub/.
Exchange workload identity tokens with Tailscale
In order to act on the Tailscale API, you must exchange the workload's signed OIDC JWT for a short-lived Tailscale API token.
This example shows how GitHub actions can retrieve an OIDC JWT, exchange it for a short-lived Tailscale API token, and then use that Tailscale API token to call the Tailscale API. When configuring the credential in the Tailscale admin console, you will need to select the devices:read scope.
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
on:
workflow_dispatch:
inputs:
audience:
description: "Audience for the OIDC token"
required: true
default: "<api.tailscale.com/ID>"
client_id:
description: "Client ID for the Tailscale OIDC JWT exchange"
required: true
default: "<tailnet-id/client-id>"
tailnet:
description: "Tailnet name for the demo API request"
required: true
default: "<your-tailnet-name>"
jobs:
echo-token:
runs-on: ubuntu-latest
steps:
- name: get OIDC token from GitHub Actions
id: get_oidc_token
run: |
JWT=$(curl -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${{ inputs.audience }}" | jq -r '.value')
echo "::add-mask::$JWT" # Mask the JWT in the logs
echo "jwt=$JWT" >> $GITHUB_OUTPUT
- name: perform OIDC token exchange
run: |
# Perform the OIDC token exchange with Tailscale
RESPONSE=$(curl -X POST https://api.tailscale.com/api/v2/oauth/token-exchange \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=${{ inputs.client_id}}" \
-d "jwt=${{ steps.get_oidc_token.outputs.jwt }}")
# make API request to demonstrate access token
export ACCESS_TOKEN=$(echo $RESPONSE | jq -r '.access_token')
echo "::add-mask::$ACCESS_TOKEN" # Mask the access token in the logs
curl https://api.tailscale.com/api/v2/tailnet/${{ inputs.tailnet }}/devices \
--header "Authorization: Bearer ${ACCESS_TOKEN}"
To test this workflow:
- Save the YAML above as
token.yamlin your repository's.github/workflowsdirectory. - Visit the Actions tab of your repository and select .github/workflows/token.yaml in the sidebar.
- Select Run workflow.
- In the dropdown, paste the Audience (aud claim) and Client ID that you generated when configuring the federated identity in the Tailscale admin console. Lastly, enter the tailnet name, which is your tailnet ID. You can find your tailnet ID in the General page of the admin console.
- Select Run workflow.
- After a few seconds, the workflow will appear in the workflow runs table. To confirm that it ran successfully:
- Select the workflow from the table.
- Select the echo-token action on the workflow detail page.
- Expand the perform OIDC token exchange step.
- The workflow step's output should display a JSON object listing all of the devices in your tailnet.
Register new nodes using workload identity
A device must run Tailscale v1.90.1 or later to have the --client-id and --id-token flags.
You can use a client ID and OIDC token directly in tailscale up to register a new node:
tailscale up --client-id=${CLIENT_ID} --id-token=${IDENTITY_TOKEN} --advertise-tags=tag:ci
The workload identity credential must have the auth_keys scope and the tags passed to --advertise-tags must match the tags you selected when you configured the federated identity.
The --client-id flag can accept additional URL-style parameters:
tailscale up --client-id='${CLIENT_ID}?ephemeral=false&preauthorized=true'--id-token=${IDENTITY_TOKEN} --advertise-tags=tag:ci
The available parameters are:
ephemeral: register as an ephemeral node (defaults totrue)preauthorized: skip manual device approval (defaults tofalse)
Limitations
- The issuer that provides signed JWTs to your workloads must be publicly accessible.
