A test repository demonstrating Microsoft Flexible Federated Identity Credentials between GitHub Actions and Azure. This repo shows how a single federated credential can trust all GitHub Actions runs across an entire GitHub organization—without storing any secrets.
Flexible Federated Identity Credentials are a preview feature of Microsoft Entra Workload ID that extend the classic federated credential model with expression-based claim matching.
| Classic Federated Credential | Flexible Federated Credential | |
|---|---|---|
| Matching | Exact subject match (e.g., one branch, one environment) | Expression-based matching (e.g., all repos in an org, any branch) |
| Credentials required | One per workflow/branch/environment combination | One credential can cover many workflows |
| Limit per identity | 20 credentials per app/managed identity | Significantly higher limits |
| New claims supported | sub, iss, aud only |
Custom claims beyond sub, iss, aud |
- A GitHub Actions workflow requests a short-lived OIDC token from GitHub's token provider (
https://token.actions.githubusercontent.com). - The token contains claims such as
sub(repository + ref),repository,ref,workflow, and others. - Azure Entra evaluates the token against the
claimsMatchingExpressiondefined on the federated credential. - If the expression matches, Azure issues an access token that the workflow uses to call Azure APIs—no long-lived secret is ever stored or transmitted.
This pattern eliminates the need to rotate credentials and greatly reduces the risk of secret leakage.
FlexFedCredTest/
├── .github/
│ └── workflows/
│ └── azure-login.yml # GitHub Actions workflow that logs in to Azure
├── scripts/
│ └── Setup-FlexFedCred.ps1 # PowerShell setup script (one-time infrastructure provisioning)
└── README.md
A PowerShell 7 script that performs the complete end-to-end setup:
- Creates an Azure AD App Registration (default display name:
app-msxorg-github). - Ensures a Service Principal exists for the App Registration in the tenant.
- Configures a Flexible Federated Identity Credential on the App Registration via the Microsoft Graph API with the expression:
This single credential trusts any GitHub Actions workflow running from any repository in the MSXOrg organization.
claims['sub'] matches 'repo:MSXOrg/*' - Stores the required Azure secrets (
AZURE_CLIENT_ID,AZURE_TENANT_ID,AZURE_SUBSCRIPTION_ID) as organization-level GitHub secrets so every repository in the org can consume them.
Important: Flexible federated identity credentials are only supported on application objects (App Registrations), not on User-Assigned Managed Identities. See the Microsoft Entra documentation for details.
A GitHub Actions workflow that validates the setup by logging in to Azure using the flexible federated credential and printing Azure subscription information. It runs on every push to main and can also be triggered manually.
- Azure
- An active Azure subscription.
- The
Az.AccountsandAz.ResourcesPowerShell modules installed and authenticated (Connect-AzAccount). - The authenticated identity must have permission to create App Registrations and Service Principals (e.g., Application Administrator role in the tenant).
- GitHub
- The
GitHubPowerShell module installed (Install-Module -Name GitHub). - Authenticated to GitHub with permissions to manage organization secrets (
Connect-GitHub).
- The
- PowerShell 7.4 or later.
Run the setup script once to provision all required Azure and GitHub resources:
# Clone the repo and navigate to it
cd FlexFedCredTest
# Log in to Azure and GitHub first
Connect-AzAccount
Connect-GitHub
# Run the setup script with defaults
./scripts/Setup-FlexFedCred.ps1| Parameter | Default | Description |
|---|---|---|
-AppRegistrationName |
app-msxorg-github |
Display name of the Azure AD App Registration to create |
-FederatedCredentialName |
github-msxorg-all-repos |
Name of the federated identity credential |
-GitHubOrganization |
MSXOrg |
GitHub organization whose workflows should be trusted |
Example with custom values:
./scripts/Setup-FlexFedCred.ps1 -AppRegistrationName 'app-custom' -GitHubOrganization 'MyOrg'Once the setup script has run, any workflow in the organization can authenticate to Azure using the stored organization secrets:
permissions:
id-token: write # Required to request the OIDC token
contents: read
steps:
- name: Log in to Azure
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}Note: The
id-token: writepermission is mandatory for OIDC-based login. Without it, GitHub will not issue an OIDC token to the workflow.
After a successful login, subsequent steps can use the Azure CLI, Azure PowerShell, or any Azure SDK directly—all backed by the service principal's permissions.
The service principal is created with no role assignments by default. After running the setup script, grant it the roles it needs:
New-AzRoleAssignment `
-ObjectId "<ServicePrincipalObjectId from setup output>" `
-RoleDefinitionName Contributor `
-Scope "/subscriptions/<SubscriptionId>"Scope the role as narrowly as possible (resource group or individual resource) to follow the principle of least privilege.