Azure AD SSO Integration Skill Overview
This skill provides comprehensive guidance for implementing Azure AD (Entra ID) OAuth2/OIDC Single Sign-On for applications deployed on Kubernetes clusters, including access restriction by Azure AD groups.
Quick Reference Supported Applications Application Provider Redirect URI Pattern Group Sync DefectDojo azuread-tenant-oauth2 /complete/azuread-tenant-oauth2/ Yes Grafana azuread /login/azuread Yes ArgoCD microsoft (Dex) /api/dex/callback Yes Harbor oidc /c/oidc/callback Yes SonarQube saml or oidc /oauth2/callback/saml Yes OAuth2 Proxy azure /oauth2/callback Yes Keycloak oidc /realms/{realm}/broker/azure/endpoint Yes Authentication Flow Decision ┌─────────────────────────────────────────────────────────────────┐ │ Access Control Decision │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Q: Who should access this application? │ │ │ │ ├─ Everyone in tenant ──► appRoleAssignmentRequired=false │ │ │ │ │ └─ Specific groups ────► appRoleAssignmentRequired=true │ │ + Assign groups to Enterprise App │ │ │ └─────────────────────────────────────────────────────────────────┘
Implementation Workflow Phase 1: Azure AD App Registration
1. Create App Registration
APP_NAME="
APP_ID=$(az ad app create \ --display-name "$APP_NAME" \ --sign-in-audience "AzureADMyOrg" \ --web-redirect-uris "$REDIRECT_URI" \ --query appId -o tsv)
echo "Application (client) ID: $APP_ID"
2. Get Tenant ID
TENANT_ID=$(az account show --query tenantId -o tsv) echo "Directory (tenant) ID: $TENANT_ID"
3. Create Client Secret
SECRET=$(az ad app credential reset \ --id $APP_ID \ --append \ --years 1 \ --query password -o tsv)
echo "Client Secret: $SECRET" # Save immediately!
Phase 2: Enable Group Claims
Enable security group claims in tokens
az ad app update --id $APP_ID --set groupMembershipClaims=SecurityGroup
Add Group.Read.All permission (delegated)
az ad app permission add \ --id $APP_ID \ --api 00000003-0000-0000-c000-000000000000 \ --api-permissions 5f8c59db-677d-491f-a6b8-5f174b11ec1d=Scope
Grant admin consent
az ad app permission admin-consent --id $APP_ID
Phase 3: Restrict Access by Group (CRITICAL)
Get Service Principal object ID
SP_ID=$(az ad sp list --filter "appId eq '$APP_ID'" --query "[0].id" -o tsv)
Enable user assignment requirement
az ad sp update --id $SP_ID --set appRoleAssignmentRequired=true
Get the group ID to restrict access
GROUP_ID=$(az ad group show --group "G-Usuarios-
Assign group to the application (only these users can login)
az rest --method POST \ --uri "https://graph.microsoft.com/v1.0/servicePrincipals/$SP_ID/appRoleAssignments" \ --headers "Content-Type=application/json" \ --body "{ \"principalId\": \"$GROUP_ID\", \"principalType\": \"Group\", \"appRoleId\": \"00000000-0000-0000-0000-000000000000\", \"resourceId\": \"$SP_ID\" }"
Phase 4: Store Secret in Key Vault
az keyvault secret set \
--vault-name "
Secret Management
SecretProviderClass Template
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name:
Pod Volume Mount
volumes:
- name: secrets-store
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "
volumeMounts: - name: secrets-store mountPath: "/mnt/secrets-store" readOnly: true
Application Configurations DefectDojo
Enable SSO
extraEnv:
- name: DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_ENABLED
value: "True"
- name: DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY
value: "
Grafana
grafana.ini:
auth.azuread:
enabled: true
name: Azure AD
allow_sign_up: true
client_id: "
ArgoCD (via Dex)
configs:
cm:
dex.config: |
connectors:
- type: microsoft
id: microsoft
name: Azure AD
config:
clientID: "
Harbor
externalURL: https://harbor.
Troubleshooting Error Reference Error Code Description Solution AADSTS50011 Reply URL mismatch Verify exact redirect URI including trailing slash AADSTS50105 User not assigned Add user/group to Enterprise App assignments AADSTS700016 App not found Check client ID and tenant ID AADSTS7000218 Secret expired Rotate secret in Key Vault, restart pods AADSTS90102 Invalid redirect_uri Check DD_SECURE_PROXY_SSL_HEADER=True for reverse proxy AADSTS65001 Consent not granted Run az ad app permission admin-consent Common Issues Malformed redirect_uri (Django apps behind proxy)
Symptom: redirect_uri=https,%20https://...
Root cause: DD_SECURE_PROXY_SSL_HEADER set incorrectly
Fix:
- name: DD_SECURE_PROXY_SSL_HEADER value: "True" # NOT "HTTP_X_FORWARDED_PROTO,https"
Groups not syncing
Verify group claims enabled
az ad app show --id
Check API permissions
az ad app permission list --id
Verify group exists and user is member
az ad group member check --group "
Secret not syncing from Key Vault
Check SecretProviderClass
kubectl describe secretproviderclass
Check CSI driver pods
kubectl get pods -n kube-system | grep secrets-store
Check managed identity access
az keyvault show --name
Diagnostic Commands
Test OAuth redirect
curl -sS -k -D - -o /dev/null "https://
Check environment variables in pod
kubectl exec -n
Decode JWT token (after login, from browser dev tools)
Use https://jwt.io to decode and verify claims
Security Best Practices Never hardcode secrets - Always use Key Vault + CSI Driver Use managed identities - Avoid service principal credentials Restrict access by group - Enable appRoleAssignmentRequired=true Rotate secrets - Set calendar reminders before expiration Use HTTPS only - All redirect URIs must use HTTPS Single tenant - Never use multi-tenant for internal apps Audit logging - Enable Azure AD sign-in logs Environment Reference Environment Key Vault Managed Identity Tenant ID cafehyna-dev kv-cafehyna-dev-hlg f1a14a8f-6d38-40a0-a935-3cdd91a25f47 3f7a3df4-f85b-4ca8-98d0-08b1034e6567 cafehyna-hub kv-cafehyna-default f1a14a8f-6d38-40a0-a935-3cdd91a25f47 3f7a3df4-f85b-4ca8-98d0-08b1034e6567 cafehyna-prd kv-cafehyna-prd f1a14a8f-6d38-40a0-a935-3cdd91a25f47 3f7a3df4-f85b-4ca8-98d0-08b1034e6567 Detailed Reference
For complete implementation examples:
references/azure-ad-sso-guide.md - Full guide with manifests references/app-configs.md - Application-specific configurations references/troubleshooting.md - Extended troubleshooting guide