Azure Workload Identity Federation Setup
This guide walks through configuring an Azure App Registration that USDN can authenticate to using Workload Identity Federation — no client secrets are stored on the USDN platform. Once configured, you can use the Cloud Accounts page in the USDN portal to validate credentials and discover Resource Groups, Virtual Networks, subnets, and Network Security Groups in your Azure subscription.
Azure integration currently supports account onboarding and resource discovery only. The full one-click VM deploy lifecycle is available for AWS today and is planned for Azure in a future release. The portal will display a "Deploy coming soon" panel for Azure accounts in the meantime.
How It Works
USDN authenticates to Azure AD by exchanging a short-lived JSON Web Token (JWT) signed by the USDN OIDC issuer for an Azure access token. Azure verifies the JWT against a Federated Credential you configure on the App Registration, then issues a token scoped to your subscription.
The key invariant: USDN never stores a client secret. The trust anchor is the public JWKS endpoint that Azure AD pulls from our OIDC issuer at every token exchange.
Prerequisites
- An Azure subscription with permissions to create App Registrations and assign RBAC roles
- The USDN OIDC issuer URL:
<USDN_OIDC_ISSUER>(provided during onboarding, e.g.https://api.usdn.example.com) - Access to the USDN portal with an active organization
Step 1: Create the App Registration
The App Registration is the Azure AD identity that USDN authenticates as.
Using the Azure Portal
- Open the Azure Portal and navigate to Microsoft Entra ID > App registrations > New registration.
- Enter a name, e.g.
USDN Cloud Deploy. - For Supported account types, select Accounts in this organizational directory only (single tenant).
- Leave Redirect URI blank — USDN does not use the interactive auth flow.
- Click Register.
- From the app's Overview page, copy the following values — you will need them in Step 4:
- Application (client) ID
- Directory (tenant) ID
Using the Azure CLI
APP_NAME="USDN Cloud Deploy"
# Create the app registration
APP_JSON=$(az ad app create --display-name "${APP_NAME}" --sign-in-audience AzureADMyOrg)
APP_ID=$(echo "${APP_JSON}" | jq -r .appId)
TENANT_ID=$(az account show --query tenantId -o tsv)
# Create the matching service principal so RBAC role assignments work
az ad sp create --id "${APP_ID}"
echo "Application (client) ID: ${APP_ID}"
echo "Directory (tenant) ID: ${TENANT_ID}"
Step 2: Configure the Federated Credential
The Federated Credential is what tells Azure AD to trust JWTs minted by the USDN OIDC issuer. The subject and audience values must match exactly — Azure AD does not allow wildcards.
Using the Azure Portal
- From your App Registration, go to Certificates & secrets > Federated credentials > Add credential.
- Choose Other issuer as the scenario.
- Fill in the form with the values below:
| Field | Value |
|---|---|
| Issuer URL | <USDN_OIDC_ISSUER> (e.g. https://api.usdn.example.com) |
| Subject identifier | usdn:cloud-deploy |
| Name | usdn-cloud-deploy-federation |
| Audience | api://AzureADTokenExchange |
- Click Add.
Using the Azure CLI
USDN_ISSUER="https://api.usdn.example.com" # Provided during onboarding
cat > federated-credential.json << EOF
{
"name": "usdn-cloud-deploy-federation",
"issuer": "${USDN_ISSUER}",
"subject": "usdn:cloud-deploy",
"description": "Federated credential for USDN cloud deploy",
"audiences": ["api://AzureADTokenExchange"]
}
EOF
az ad app federated-credential create \
--id "${APP_ID}" \
--parameters @federated-credential.json
Federated Credential Fields Explained
| Field | Why it matters |
|---|---|
| Issuer URL | Azure AD fetches /.well-known/openid-configuration and the JWKS from this host to verify the JWT signature. It must be reachable from Azure AD over the public internet and serve valid HTTPS. |
| Subject | Must match iss claim's paired sub exactly. USDN sets this to the literal string usdn:cloud-deploy for every Azure JWT — wildcards are not supported. |
| Audience | Must be api://AzureADTokenExchange. This is Microsoft's reserved audience for workload identity federation. |
If the federated credential subject does not match the sub claim in our JWT byte-for-byte, Azure AD rejects the token exchange with AADSTS70021: No matching federated identity record found. The portal validation step will surface this as a connection failure.
Step 3: Grant the App Access to Your Subscription
Workload identity federation only handles authentication — you still need to authorize the App Registration to read resources in your subscription. The least-privilege role for onboarding + discovery is the built-in Reader role.
Using the Azure Portal
- Navigate to Subscriptions > (your subscription) > Access control (IAM) > Add > Add role assignment.
- Select the Reader role and click Next.
- Under Assign access to, choose User, group, or service principal.
- Click Select members, search for the App Registration name (
USDN Cloud Deploy), and add it. - Click Review + assign.
Using the Azure CLI
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
az role assignment create \
--assignee "${APP_ID}" \
--role "Reader" \
--scope "/subscriptions/${SUBSCRIPTION_ID}"
You can scope the role assignment to a specific Resource Group instead of the whole subscription if USDN only needs visibility into a subset of resources. Replace --scope with /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/<rg-name>.
Permission Summary
| Permission | Purpose |
|---|---|
Microsoft.Resources/subscriptions/read | Validate the subscription is reachable |
Microsoft.Resources/subscriptions/resourceGroups/read | Discover Resource Groups for the deploy wizard |
Microsoft.Network/virtualNetworks/read | List VNets for placement selection |
Microsoft.Network/virtualNetworks/subnets/read | List subnets within VNets |
Microsoft.Network/networkSecurityGroups/read | List NSGs for instance assignment |
All of these are covered by the built-in Reader role.
Step 4: Link the Account in USDN
- Log in to the USDN portal and navigate to Cloud Accounts (under Infrastructure).
- Click Link Cloud Account.
- Select Microsoft Azure as the provider.
- Fill in the required fields:
| Field | Value | Example |
|---|---|---|
| Account Name | A friendly label | Production Azure |
| Tenant ID | Directory (tenant) ID from Step 1 | 11111111-1111-1111-1111-111111111111 |
| Subscription ID | Target Azure subscription | 22222222-2222-2222-2222-222222222222 |
| Application (Client) ID | App Registration client ID from Step 1 | 33333333-3333-3333-3333-333333333333 |
| Default Region | Preferred Azure region | eastus |
-
Click Save. USDN will validate the credentials by minting a JWT, exchanging it for an access token via Azure AD, and listing the configured subscription via ARM.
-
If validation succeeds, the account status will change to Connected and you can use the View Resources action to discover Resource Groups, VNets, subnets, and NSGs in the selected region.
The portal does not prompt for a client secret. The federated credential you configured in Step 2 is the only thing that grants USDN access — no long-lived secrets are ever stored on the platform side.
Troubleshooting
Validation Fails with "No matching federated identity record found"
This is AADSTS70021. Azure AD could not find a Federated Credential whose issuer, subject, and audience all match the JWT we sent.
- Confirm the Subject on the federated credential is exactly
usdn:cloud-deploy(no leading slash, no quotes, no trailing whitespace). - Confirm the Audience is exactly
api://AzureADTokenExchange. - Confirm the Issuer URL matches the OIDC issuer USDN gave you, including the scheme and the absence of a trailing slash.
Validation Fails with "Couldn't retrieve verification key from your identity provider"
Azure AD could not fetch the JWKS from our OIDC issuer.
- Verify the issuer URL is reachable over the public internet (Azure AD does not honor private networks).
- Try
curl -fsSL <USDN_OIDC_ISSUER>/.well-known/openid-configurationfrom any host — it should return JSON with a validjwks_uri.
Validation Fails with "Insufficient privileges to complete the operation"
The federated identity authenticated successfully, but the App Registration does not have the RBAC role assignment from Step 3.
- Confirm the Reader role is assigned to the App Registration's service principal at the subscription scope.
- Wait up to 5 minutes for RBAC changes to propagate.
- Re-run the validation from the portal.
Validation Fails with "Subscription not found"
- Confirm the subscription ID entered in the portal matches an active subscription in the same tenant as the App Registration.
- Confirm the App Registration's service principal has at least Reader access to that specific subscription.
Resource Discovery Returns Empty Lists
- Confirm the region selected in the portal matches the region where your VNets and Resource Groups live (Azure resources are region-scoped).
- Confirm the App Registration has read access to the Resource Group containing the resources, not just the subscription.
Security Best Practices
- No secrets on disk — Federated credentials are inherently more secure than client secrets. Never re-introduce a secret-based credential for this App Registration.
- Scope the role assignment — Prefer assigning Reader at the Resource Group scope over the subscription scope when possible.
- Single-tenant App Registration — Always select single tenant in Step 1 unless you have a documented reason to do otherwise.
- Audit federated credentials — Periodically review the federated credentials list in the App Registration and remove entries for issuers you no longer trust.
- Enable Microsoft Entra audit logs — Monitor token exchanges and role-assignment changes in the Microsoft Entra audit log.
Revoking Access
To immediately revoke USDN's access to your Azure subscription:
# Option 1: Remove just the federated credential (the App Registration stays)
az ad app federated-credential list --id "${APP_ID}"
az ad app federated-credential delete --id "${APP_ID}" --federated-credential-id <federated-credential-id>
# Option 2: Remove the role assignment (App Registration can no longer read resources)
az role assignment delete \
--assignee "${APP_ID}" \
--role "Reader" \
--scope "/subscriptions/${SUBSCRIPTION_ID}"
# Option 3: Delete the App Registration entirely
az ad app delete --id "${APP_ID}"
After revoking, the linked account in the USDN portal will show an Error status on the next validation attempt.