Microsoft Entra ID
Provider for Microsoft Entra ID. Fully compliant with OIDC, with support for group overage and multi-tenant apps.
Config Options
The provider is OIDC-compliant, so all the OIDC parameters are honored. Additional provider-specific configuration parameters are:
Flag | Toml Field | Type | Description | Default |
---|---|---|---|---|
--entra-id-allowed-tenant | entra_id_allowed_tenants | string | list | List of allowed tenants. In case of multi-tenant apps, incoming tokens are issued by different issuers and OIDC issuer verification needs to be disabled. When not specified, all tenants are allowed. Redundant for single-tenant apps (regular ID token validation matches the issuer). | |
--entra-id-federated-token-auth | entra_id_federated_token_auth | boolean | Enable oAuth2 client authentication with federated token projected by Entra Workload Identity plugin, instead of client secret. | false |
Configure App registration
To begin, create an App registration, set a redirect URI, and generate a secret. All account types are supported, including single-tenant, multi-tenant, multi-tenant with Microsoft accounts, and Microsoft accounts only.
See Azure Portal example
See Terraform example
resource "azuread_application" "auth" {
display_name = "oauth2-proxy"
sign_in_audience = "AzureADMyOrg" # Others are also supported
web {
redirect_uris = [
"https://podinfo.lakis.tech/oauth2/callback",
]
}
// We don't specify any required API permissions - we allow user consent only
}
resource "azuread_service_principal" "sp" {
client_id = azuread_application.auth.client_id
app_role_assignment_required = false
}
resource "azuread_service_principal_password" "pass" {
service_principal_id = azuread_service_principal.sp.id
}
Configure groups
If you want to make use of groups, you can configure groups claim to be present in ID Tokens issued by the App registration.
See Azure Portal example
See Terraform example
resource "azuread_application" "auth" {
display_name = "oauth2-proxy"
sign_in_audience = "AzureADMyOrg"
group_membership_claims = [
"SecurityGroup"
]
web {
redirect_uris = [
"https://podinfo.lakis.tech/oauth2/callback",
]
}
}
resource "azuread_service_principal" "sp" {
client_id = azuread_application.auth.client_id
app_role_assignment_required = false
}
resource "azuread_service_principal_password" "pass" {
service_principal_id = azuread_service_principal.sp.id
}
Scopes and claims
For single-tenant and multi-tenant apps without groups, the only required scope is openid
(See: Scopes and permissions).
To make use of groups - for example use allowed_groups
setting or authorize based on groups inside your service - you need to enable groups claims in the App Registration. When enabled, list of groups is present in the issued ID token. No additional scopes are required besides openid
. This works up to 200 groups.
When user has more than 200 group memberships, OAuth2-Proxy attempts to retrieve the complete list from Microsoft Graph API's transitiveMemberOf
. Endpoint requires User.Read
scope (delegated permission). This permission can be by default consented by user during first login. Set scope to openid User.Read
to request user consent. Without proper scope, user with 200+ groups will authenticate with 0 groups. See: group overages.
Alternatively to user consent, both openid
and User.Read
permissions can be consented by admistrator. Then, user is not asked for consent on the first login, and group overage works with openid
scope only. Admin consent can also be required for some tenants. It can be granted with azuread_service_principal_delegated_permission_grant terraform resource.
For personal microsoft accounts, required scope is openid profile email
.
See: Overview of permissions and consent in the Microsoft identity platform.
Multi-tenant apps
To authenticate apps from multiple tenants (including personal Microsoft accounts), set the common OIDC issuer url and disable verification:
oidc_issuer_url=https://login.microsoftonline.com/common/v2.0
insecure_oidc_skip_issuer_verification=true
insecure_oidc_skip_issuer_verification
setting is required to disable following checks:
- Startup check for matching issuer URL returned from discovery document with
oidc_issuer_url
setting. Required, as document'sissuer
field doesn't equal tohttps://login.microsoftonline.com/common/v2.0
. See OIDC Discovery 4.3. - Matching ID token's
issuer
claim withoidc_issuer_url
setting during ID token validation. Required to support tokens issued by diffrerent tenants. See OIDC Core 3.1.3.7.
To provide additional security, Entra ID provider performs check on the ID token's issuer
claim to match the https://login.microsoftonline.com/{tenant-id}/v2.0
template.
Workload Identity
Provider supports authentication with federated token, without need of using client secret. Following conditions have to be met:
- Cluster has public OIDC provider URL. For major cloud providers, it can be enabled with a single flag, for example for Azure Kubernetes Service deployed with Terraform, it's
oidc_issuer_enabled
. - Workload Identity admission webhook is deployed on the cluster. For AKS, it can be enabled with a flag (
workload_identity_enabled
in Terraform resource), for clusters outside of Azure, it can be installed from helm chart. - Appropriate federated credential is added to application registration.
See federated credential terraform example
resource "azuread_application_federated_identity_credential" "fedcred" {
application_id = azuread_application.application.id # ID of your application
display_name = "federation-cred"
description = "Workload identity for oauth2-proxy"
audiences = ["api://AzureADTokenExchange"] # Fixed value
issuer = "https://cluster-oidc-issuer-url..."
subject = "system:serviceaccount:oauth2-proxy-namespace-name:oauth2-proxy-sa-name" # set proper NS and SA name
}
- Kubernetes service account associated with oauth2-proxy deployment, is annotated with
azure.workload.identity/client-id: <app-registration-client-id>
- oauth2-proxy pod is labeled with
azure.workload.identity/use: "true"
- oauth2-proxy is configured with
entra_id_federated_token_auth
set totrue
.
client_secret
setting can be omitted when using federated token authentication.
See: Azure Workload Identity documentation.
Example configurations
Single-tenant app without groups (groups claim not enabled). Consider using generic OIDC provider:
provider="entra-id"
oidc_issuer_url="https://login.microsoftonline.com/<tenant-id>/v2.0"
client_id="<client-id>"
client_secret="<client-secret>"
scope="openid"
Single-tenant app with up to 200 groups (groups claim enabled). Consider using generic OIDC provider:
provider="entra-id"
oidc_issuer_url="https://login.microsoftonline.com/<tenant-id>/v2.0"
client_id="<client-id>"
client_secret="<client-secret>"
scope="openid"
allowed_groups=["ac51800c-2679-4ecb-8130-636380a3b491"]
Single-tenant app with more than 200 groups:
provider="entra-id"
oidc_issuer_url="https://login.microsoftonline.com/<tenant-id>/v2.0"
client_id="<client-id>"
client_secret="<client-secret>"
scope="openid User.Read"
allowed_groups=["968b4844-d5e7-4e18-a834-59927959369f"]
Single-tenant app with more than 200 groups and workload identity enabled:
provider="entra-id"
oidc_issuer_url="https://login.microsoftonline.com/<tenant-id>/v2.0"
client_id="<client-id>"
scope="openid User.Read"
allowed_groups=["968b4844-d5e7-4e18-a834-59927959369f"]
entra_id_federated_token_auth=true
Multi-tenant app with Microsoft personal accounts & one Entra tenant allowed, with group overage considered:
provider="entra-id"
oidc_issuer_url="https://login.microsoftonline.com/common/v2.0"
client_id="<client-id>"
client_secret="<client-secret>"
insecure_oidc_skip_issuer_verification=true
scope="openid profile email User.Read"
entra_id_allowed_tenant=["9188040d-6c67-4c5b-b112-36a304b66dad","<my-tenant-id>"] # Allow only <my-tenant-id> and Personal MS Accounts tenant
email_domains="*"