Configure external identity providers with AKS structured authentication (preview)

This article shows you how to configure external identity providers for Azure Kubernetes Service (AKS) control plane authentication using structured authentication. You learn how to create JSON Web Token (JWT) authenticators, configure claim validation and mapping, and test the authentication flow.

Important

AKS preview features are available on a self-service, opt-in basis. Previews are provided "as is" and "as available," and they're excluded from the service-level agreements and limited warranty. AKS previews are partially covered by customer support on a best-effort basis. As such, these features aren't meant for production use. For more information, see the following support articles:

Prerequisites

  • If you prefer to run CLI reference commands locally, install the Azure CLI. If you're running on Windows or macOS, consider running Azure CLI in a Docker container. For more information, see How to run the Azure CLI in a Docker container.

    • If you're using a local installation, sign in to the Azure CLI by using the az login command. To finish the authentication process, follow the steps displayed in your terminal. For other sign-in options, see Sign in with the Azure CLI.

    • When you're prompted, install the Azure CLI extension on first use. For more information about extensions, see Use extensions with the Azure CLI.

    • Run az version to find the version and dependent libraries that are installed. To upgrade to the latest version, run az upgrade.

  • This article requires version 2.77.0 or later of the Azure CLI.
  • You need to install the aks-preview Azure CLI extension version 18.0.0b41 or later to use structured authentication features.
    • If you don't already have the aks-preview extension, install it using the az extension add command:
      az extension add --name aks-preview
      
    • If you already have the aks-preview extension, update it to make sure you have the latest version using the az extension update command:
      az extension update --name aks-preview
      
    • Verify you have the required version:
      az extension show --name aks-preview --query version
      
  • An AKS cluster running Kubernetes version 1.30 or later. To create an AKS cluster, see Quickstart: Deploy an Azure Kubernetes Service (AKS) cluster using Azure CLI.
  • kubectl command-line tool to interact with your Kubernetes cluster. To install kubectl locally, use the az aks install-cli command.
    az aks install-cli
    
  • An external identity provider that supports OpenID Connect (OIDC).
  • Network connectivity from cluster nodes to your identity provider.
  • If you plan to use the kubelogin plugin, install it using these setup instructions

Set environment variables

Set the following environment variables for your resource group and cluster name:

export RESOURCE_GROUP="<your-resource-group-name>"
export CLUSTER_NAME="<your-cluster-name>"

Register the preview feature

If you're using a subscription without the feature registered, register the JWTAuthenticatorPreview feature:

az feature register --name JWTAuthenticatorPreview --namespace Microsoft.ContainerService

Check the registration status:

az feature show --name JWTAuthenticatorPreview --namespace Microsoft.ContainerService

When the status shows Registered, refresh the resource provider registration:

az provider register --namespace Microsoft.ContainerService

Set up your identity provider

Configure your external identity provider to support OIDC authentication. Select your identity provider for specific setup instructions:

GitHub Actions OIDC Setup

  1. Ensure your GitHub Actions workflows have the necessary permissions.
  2. Configure the id-token: write permission in your workflow files:
    permissions:
      id-token: write
      contents: read
    
  3. Set up appropriate repository and organization settings for OIDC token access. Configure repository OIDC settings and organization security policies for token usage.

Create JWT authenticator configuration

Create a JSON configuration file that defines how to validate and process tokens from your identity provider. Select your identity provider for specific configuration examples:

GitHub Configuration

For GitHub Actions OIDC, create a file named jwt-config.json with the following configuration:

{
  "issuer": {
      "url": "https://token.actions.githubusercontent.com",
      "audiences": [
          "my-api"
      ]
  },
  "claimValidationRules": [
      {
          "expression": "has(claims.sub)",
          "message": "must have sub claim"
      }
  ],
  "claimMappings": {
      "username": {
          "expression": "'aks:jwt:github:' + claims.sub"
      }
  },
  "userValidationRules": [
      {
          "expression": "has(user.username)",
          "message": "must have username"
      },
      {
          "expression": "!user.username.startsWith('aks:jwt:github:system')",
          "message": "username must not start with 'aks:jwt:github:system'"
      }
  ]
}

Configuration elements

  • issuer: The OIDC issuer configuration.
    • url: The OIDC issuer URL that must match the iss claim in JWTs.
    • audiences: List of audiences that JWTs must be issued for (checked against aud claim).
    • certificateAuthority: Optional base64-encoded root certificate bundle for Transport Layer Security (TLS) verification.
  • claimValidationRules: Array of validation rules using CEL expressions to validate JWT claims.
    • expression: CEL expression that must evaluate to true.
    • message: Error message displayed when validation fails.
  • claimMappings: Defines how JWT claims map to Kubernetes user information.
    • username: CEL expression defining how to construct the username from claims.
    • groups: CEL expression defining how to construct group memberships from claims.
    • uid: Optional CEL expression for user identifier.
    • extra: Optional map of more user attributes.
  • userValidationRules: Array of validation rules applied to the final user information.
    • expression: CEL expression that must evaluate to true for the mapped user.
    • message: Error message displayed when user validation fails.

Important

All username and group mappings must include the aks:jwt: prefix to prevent conflicts with other authentication methods.

Create the JWT authenticator

Add the JWT authenticator to your AKS cluster:

az aks jwtauthenticator add \
    --resource-group $RESOURCE_GROUP \
    --cluster-name $CLUSTER_NAME \
    --name external-auth \
    --config-file jwt-config.json

Verify the authenticator

List all JWT authenticators on your cluster:

az aks jwtauthenticator list \
    --resource-group $RESOURCE_GROUP \
    --cluster-name $CLUSTER_NAME

Get details of a specific authenticator:

az aks jwtauthenticator show \
    --resource-group $RESOURCE_GROUP \
    --cluster-name $CLUSTER_NAME \
    --name external-auth

Set up client for authentication

Configure your client to authenticate with your external identity provider. Select your identity provider for specific configuration:

GitHub Actions Workflow Authentication

For GitHub Actions OIDC, create a workflow that obtains an OIDC token and uses it to authenticate with your AKS cluster. Here's an example workflow that gets all pods running on the cluster:

name: AKS Access with GitHub OIDC
on:
  workflow_dispatch:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  aks-access:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Install kubectl
        uses: azure/setup-kubectl@v3
        with:
          version: 'latest'

      - name: Get GitHub OIDC token
        id: get_token
        run: |
          TOKEN=$(curl -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
            "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=my-api" | \
            jq -r '.value')
          echo "::add-mask::$TOKEN"
          echo "oidc_token=$TOKEN" >> $GITHUB_OUTPUT

      - name: Create kubeconfig with OIDC token
        run: |
          cat <<EOF > kubeconfig
          apiVersion: v1
          kind: Config
          clusters:
          - cluster:
              certificate-authority-data: ${{ secrets.AKS_CA_DATA }}
              server: ${{ secrets.AKS_SERVER_URL }}
            name: aks-cluster
          contexts:
          - context:
              cluster: aks-cluster
              user: github-oidc-user
            name: aks-context
          current-context: aks-context
          users:
          - name: github-oidc-user
            user:
              token: ${{ steps.get_token.outputs.oidc_token }}
          EOF

      - name: List all pods in the cluster
        run: |
          export KUBECONFIG=./kubeconfig
          kubectl get pods --all-namespaces

Required repository secrets and variables

Set up these secrets in your GitHub repository:

Secrets:

  • AKS_SERVER_URL: Your AKS cluster's API server URL.
  • AKS_CA_DATA: Base64-encoded certificate authority data for your AKS cluster.

Note

The audience value my-api should match the audience configured in your JWT authenticator configuration.

Getting AKS cluster information

To get the required cluster information, run:

# Get cluster info
az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query "fqdn" -o tsv | \
  awk '{print "https://" $0 ":443"}'

# Get CA data (base64 encoded)
az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --file - --format exec | \
  grep certificate-authority-data | awk '{print $2}'

Method 2: Using static token

If you have a JWT token, you can use it directly:

users:
- name: external-user
  user:
    token: eyJhbGciOiJSUzI1NiIs...

Test authentication

You can trigger the workflow by:

  • Pushing to the main branch
  • Manually triggering it from the Actions tab in your repository

Monitor the workflow execution in the Actions tab to verify authentication is working.

Expected output for first-time setup before Role-Based Access Control (RBAC) configuration:

Error from server (Forbidden): nodes is forbidden: User "aks:jwt:github:your-sub" cannot list resource "nodes" in API group "" at the cluster scope

This error indicates successful authentication but lack of authorization.

Configure Kubernetes Role-Based Access Control (RBAC)

Create appropriate RBAC bindings for your external users. Use the cluster admin credentials to apply these configurations. Select your identity provider for provider-specific examples:

Create a sample role and binding

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: external-user-role
rules:
- apiGroups: [""]
  resources: ["pods", "services", "nodes"]
  verbs: ["get", "list"]
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: external-user-binding
subjects:
- kind: User
  # This matches the username expression in claim mappings for GitHub; example of GitHub subject is "repo:<organization-name>/<repository-name>:ref:refs/heads/main"
  name: aks:jwt:github:your-github-sub
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: external-user-role
  apiGroup: rbac.authorization.k8s.io

Apply the RBAC configuration:

kubectl apply -f rbac-config.yaml

Verify access

Test that the external user can now access resources:

kubectl get nodes --user external-user
kubectl get pods --user external-user

Remove JWT authenticator

Delete an authenticator when no longer needed:

az aks jwtauthenticator delete \
    --resource-group $RESOURCE_GROUP \
    --cluster-name $CLUSTER_NAME \
    --name external-auth

Next steps