Setting the file. One moment.
Subchapter 30.2
references/oauth2-token-flow.mdMarkdown4 KBView on GitHub
Source: Agent ID Setup Instructions (opens in a new tab)
Agent Identities authenticate at runtime using credentials configured on the Blueprint (not on the Agent Identity — Agent Identities cannot hold credentials).
| Option | Use case | Credential type |
|---|---|---|
| Managed Identity + WIF | Production (Azure-hosted) | Federated Identity Credential on Blueprint |
| Client secret | Local dev / testing | Password credential on Blueprint |
Both options feed the two-step fmi_path exchange in runtime-token-exchange.md.
requests.patch(
f"{GRAPH}/applications/{blueprint_obj_id}",
headers=headers,
json={"identifierUris": [f"api://{blueprint_app_id}"]},
).raise_for_status()Use the typed path — FICs go on the Blueprint, not on the Agent Identity SP:
fic_body = {
"name": "my-fic-name",
"issuer": f"https://login.microsoftonline.com/{tenant_id}/v2.0",
"subject": mi_principal_id, # The MI's object ID (principalId), NOT client ID
"audiences": ["api://AzureADTokenExchange"],
}
requests.post(
f"{GRAPH}/applications/{blueprint_obj_id}"
f"/microsoft.graph.agentIdentityBlueprint/federatedIdentityCredentials",
headers=headers, json=fic_body,
).raise_for_status()from azure.identity import ManagedIdentityCredential
cred = ManagedIdentityCredential(client_id=MI_CLIENT_ID)
token = cred.get_token(f"api://{blueprint_app_id}/.default")
# Authorization: Bearer {token.token}import jwt
from jwt import PyJWKClient
jwks_client = PyJWKClient(
f"https://login.microsoftonline.com/{tenant_id}/discovery/v2.0/keys"
)
signing_key = jwks_client.get_signing_key_from_jwt(token_str)
claims = jwt.decode(
token_str,
signing_key.key,
algorithms=["RS256"],
audience=f"api://{blueprint_app_id}",
issuer=f"https://sts.windows.net/{tenant_id}/",
).../microsoft.graph.agentIdentityBlueprint/federatedIdentityCredentials).subject is the MI’s principalId (object ID), not its client ID.audiences must be ["api://AzureADTokenExchange"] — not your API audience.issuer: https://login.microsoftonline.com/{tenant}/v2.0.issuer for validation: https://sts.windows.net/{tenant}/ (different domain, trailing slash).PowerShell:
$body = @{
"passwordCredential" = @{
"displayName" = "Dev Secret"
"endDateTime" = "2027-01-01T00:00:00Z"
}
}
$credential = Invoke-MgGraphRequest -Method POST `
-Uri "https://graph.microsoft.com/v1.0/applications/<BLUEPRINT_OBJECT_ID>/addPassword" `
-Headers @{ "OData-Version" = "4.0"; "Content-Type" = "application/json" } `
-Body ($body | ConvertTo-Json -Depth 5) -OutputType PSObject
$credential.secretText # Save NOW — not retrievable laterPython:
resp = requests.post(
f"{GRAPH}/applications/{blueprint_obj_id}/addPassword",
headers=headers,
json={"passwordCredential": {
"displayName": "Dev Secret",
"endDateTime": "2027-01-01T00:00:00Z",
}},
)
resp.raise_for_status()
secret_text = resp.json()["secretText"] # Save NOWPass blueprint_secret=secret_text into get_parent_token(...) from
runtime-token-exchange.md, then call exchange_autonomous or exchange_obo.
secretText immediately — it can’t be retrieved later.PropertyNotCompatibleWithAgentIdentity).endDateTime.DefaultAzureCredential to acquire Blueprint tokens — Azure CLI tokens carry Directory.AccessAsUser.All and are rejected. Use ClientSecretCredential or the raw HTTP exchange.