Setting Up Microsoft Entra for a Federated Service Account
This guide shows you how to create a Microsoft Entra workload identity for a federated service account, allow it to request the audience Axual expects, and find the object id your tenant admin binds it to.
Type |
How-to guide |
Goal |
Prepare an Entra workload identity that a federated service account authenticates as, and collect the values Axual needs. |
Audience |
A Microsoft Entra administrator, or an engineer who owns the Azure workload that will call the Platform Manager API. |
When to use |
Use this guide before a tenant admin creates a federated service account, once your Axual operator has prepared the realm. |
This is the Azure side of federated authentication. The tenant admin creates the service account in Federated Service Accounts, and an operator prepares the realm in How to Prepare a Keycloak Realm for Federated Service Accounts.
Prerequisites
Federated authentication trusts a token that your Entra workload presents, so the workload and the audience it targets must exist in your Entra tenant first.
- Access and permissions
-
-
Administrator access to the Microsoft Entra tenant that holds the workload.
-
The Axual realm prepared for federation. See How to Prepare a Keycloak Realm for Federated Service Accounts.
-
- Tools and versions
-
-
The Azure portal or the
azCLI, to create the identity. -
curl, to verify the token request.
-
- Resources that must exist first
-
-
The audience the realm accepts. A tenant admin sees it as the Audience on the create service account form, and, for Entra, the Resource of the form
api://<AUDIENCE>. See Service Account and Federation Reference.
-
Values in angle brackets, such as <AUDIENCE>, are placeholders. Replace each with your own value.
|
Create the workload identity
The workload identity is what your automation runs as. Choose one kind: an app registration with a secret, or a secretless identity (an AKS workload identity or an Azure managed identity) that holds no secret and is the safer choice for a high-privilege account. Each gives the workload an object id, which the tenant admin binds the service account to.
Use an app registration with a client secret
This is the simplest option. The workload holds a secret and presents it to Entra.
-
In Entra, register an application for the workload and note its object id (the service principal object id).
-
Add a client secret to the application and store it in your workload’s secret store.
The workload authenticates to Entra with its client id and secret, and the token’s sub and oid are the service principal object id. Prefer a secretless option below for a high-privilege service account.
Use AKS workload identity (secretless)
On Azure Kubernetes Service (AKS), a pod authenticates with a projected Kubernetes token instead of a secret. This needs the cluster’s OpenID Connect (OIDC) issuer and the workload-identity webhook, which az aks update -g <RESOURCE_GROUP> -n <CLUSTER> --enable-oidc-issuer --enable-workload-identity enable.
-
On the workload’s Entra application, add a federated credential for the AKS scenario: the cluster’s OIDC issuer URL, the pod’s namespace, and its service-account name. Entra builds the subject
system:serviceaccount:<AKS_NAMESPACE>:<AKS_SERVICE_ACCOUNT>with audienceapi://AzureADTokenExchange. -
Annotate the Kubernetes service account with the application’s client id, and label the pod so the webhook injects the token:
apiVersion: v1 kind: ServiceAccount metadata: name: <AKS_SERVICE_ACCOUNT> namespace: <AKS_NAMESPACE> annotations: azure.workload.identity/client-id: <WORKLOAD_CLIENT_ID> --- # on the Pod (or the Deployment pod template): metadata: labels: azure.workload.identity/use: "true" spec: serviceAccountName: <AKS_SERVICE_ACCOUNT>At pod creation the webhook injects
AZURE_CLIENT_ID,AZURE_TENANT_ID, andAZURE_AUTHORITY_HOST, and mounts the projected token atAZURE_FEDERATED_TOKEN_FILE. The workload reads that file as its assertion, which the Azure SDK’sWorkloadIdentityCredentialdoes for you. The webhook runs once, at admission; it mints no tokens itself.
The workload’s object id is the service principal object id of the application the federated credential is attached to.
Use an Azure managed identity (secretless)
A user-assigned managed identity holds no secret and needs no federated credential of its own: the identity requests a token for the audience directly, from the Azure Instance Metadata Service (IMDS) or through the Azure SDK. The token has the same shape as the other options, with sub and oid equal to the managed identity’s principal object id.
-
Assign the managed identity to the workload, for example a virtual machine or an App Service.
-
Note the managed identity’s principal object id.
Azure hands out cached managed-identity tokens that are already minutes old, so the realm’s fedClientAssertionMaxExp must be raised for this path, unlike the AKS path, which mints a fresh token per call. Your operator sets this; see How to Prepare a Keycloak Realm for Federated Service Accounts.
|
Allow the workload to request the audience
The audience is a resource application in your tenant, separate from the workload (the caller): the resource’s application (client) ID is the <AUDIENCE> the realm accepts, and the caller requests a token for it. Entra only issues that token when the resource resolves and the caller is allowed to request it, and the token must be a v2 token so its aud claim is the bare application GUID.
-
On the resource application, expose the audience as an Application ID URI of the form
api://<AUDIENCE>, so the caller can request the resourceapi://<AUDIENCE>. The bare GUID form<AUDIENCE>/.defaultalso works. -
Configure the resource application to issue v2 access tokens, so
audis the bare GUID and the issuer ends in/v2.0. -
If the resource application requires assignment, define an app role on it (allowed member type Applications, enabled), grant that role to the caller, and grant admin consent. Without this, the token request is refused with
AADSTS501051.
The <AUDIENCE> must match the client id your operator set on the realm identity provider. Confirm it against the Audience shown on the create service account form before you begin.
|
Give the object id to your tenant admin
The service account binds to exactly one workload, by its object id.
-
Copy the workload’s object id from its Entra application or managed identity.
-
Give it to the tenant admin to enter as the Subject (sub) when they create the federated service account in Federated Service Accounts.
Verify with a token request
Confirm the workload can obtain a token for the audience before the tenant admin relies on it.
curl -s -X POST "https://login.microsoftonline.com/<ENTRA_TENANT_ID>/oauth2/v2.0/token" \
--data grant_type=client_credentials \
--data client_id=<WORKLOAD_CLIENT_ID> \
--data client_secret=<CLIENT_SECRET> \
--data scope=<AUDIENCE>/.default
To confirm the token is usable, decode it and check that aud is the bare audience GUID, iss ends in /v2.0, and sub (equal to oid) matches the object id you gave the tenant admin. The consumer then presents this token to Axual as described in Authenticating as a Service Account.
For an AKS workload, the webhook has already set the environment in the pod (example values):
AZURE_AUTHORITY_HOST=https://login.microsoftonline.com/
AZURE_TENANT_ID=<ENTRA_TENANT_ID>
AZURE_CLIENT_ID=<WORKLOAD_CLIENT_ID>
AZURE_FEDERATED_TOKEN_FILE=/var/run/secrets/azure/tokens/azure-identity-token
The projected token file is the assertion, so the request carries no secret:
curl -s -X POST "${AZURE_AUTHORITY_HOST}${AZURE_TENANT_ID}/oauth2/v2.0/token" \
--data grant_type=client_credentials \
--data client_id="$AZURE_CLIENT_ID" \
--data scope=<AUDIENCE>/.default \
--data client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
--data-urlencode "client_assertion=$(cat "$AZURE_FEDERATED_TOKEN_FILE")"
A real application uses the Azure SDK’s WorkloadIdentityCredential rather than this raw call. The resulting token has the same shape as the client-secret token, so everything downstream is identical.
Common errors
These errors surface while obtaining the Entra token, before Axual is involved.
| Error | Cause |
|---|---|
|
The tenant in the token URL is wrong. Use the tenant that holds the workload. |
|
The requested resource does not resolve. Expose |
|
The caller lacks its app-role assignment on a resource application that requires assignment. Grant the role and admin consent. |
|
AKS only: no matching federated identity record. The credential’s subject, issuer, or audience does not match the pod’s projected token. |