agentsclimarketplace

Azure ad sso

Skill bg-szy/TOP-SKILLS/skills/claude-code-skills/azure-ad-sso

全球最大的 Claude Code 技能聚合库 · 收录 3900+ 来自 12+ 来源的技能,提供在线搜索与趋势分析看板 / The world's largest Claude Code skill aggregation hub — 3900+ skills from 12+ sources with online search and trend dashboard

Install
npx -y skills add bg-szy/TOP-SKILLS --skill azure-ad-sso

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Azure AD OAuth2/OIDC SSO integration for Kubernetes applications. Use when implementing Single Sign-On, configuring Azure AD App Registrations, restricting access by groups, or integrating tools (DefectDojo, Grafana, ArgoCD, Harbor, SonarQube) with Azure AD authentication.

SKILL.md

11.6 KB, as published. Nobody here has run it

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

ApplicationProviderRedirect URI PatternGroup Sync
DefectDojoazuread-tenant-oauth2/complete/azuread-tenant-oauth2/Yes
Grafanaazuread/login/azureadYes
ArgoCDmicrosoft (Dex)/api/dex/callbackYes
Harboroidc/c/oidc/callbackYes
SonarQubesaml or oidc/oauth2/callback/samlYes
OAuth2 Proxyazure/oauth2/callbackYes
Keycloakoidc/realms/{realm}/broker/azure/endpointYes

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="<application>-<environment>"
REDIRECT_URI="https://<app-domain>/complete/<provider>/"

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-<App>-Admin" --query id -o tsv)

# 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 "<keyvault-name>" \
  --name "<app>-azuread-client-secret" \
  --value "$SECRET"

Secret Management

SecretProviderClass Template

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: <app>-secrets
  namespace: <namespace>
spec:
  provider: azure
  parameters:
    usePodIdentity: "false"
    useVMManagedIdentity: "true"
    userAssignedIdentityID: "<managed-identity-client-id>"
    keyvaultName: "<keyvault-name>"
    tenantId: "<azure-tenant-id>"
    objects: |
      array:
        - |
          objectName: <app>-azuread-client-secret
          objectType: secret
          objectAlias: AZURE_AD_CLIENT_SECRET
  secretObjects:
    - secretName: <app>-azure-ad
      type: Opaque
      data:
        - objectName: AZURE_AD_CLIENT_SECRET
          key: client-secret

Pod Volume Mount

volumes:
  - name: secrets-store
    csi:
      driver: secrets-store.csi.k8s.io
      readOnly: true
      volumeAttributes:
        secretProviderClass: "<app>-secrets"

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: "<client-id>"
  - name: DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID
    value: "<tenant-id>"
  - name: DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET
    valueFrom:
      secretKeyRef:
        name: defectdojo
        key: DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET
  # Group sync
  - name: DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_GET_GROUPS
    value: "True"
  - name: DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_CLEANUP_GROUPS
    value: "True"
  - name: DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_GROUPS_FILTER
    value: "^G-Usuarios-DefectDojo-.*"
  # CRITICAL: For apps behind reverse proxy
  - name: DD_SECURE_PROXY_SSL_HEADER
    value: "True"

Grafana

grafana.ini:
  auth.azuread:
    enabled: true
    name: Azure AD
    allow_sign_up: true
    client_id: "<client-id>"
    client_secret: "${GF_AUTH_AZUREAD_CLIENT_SECRET}"
    scopes: openid email profile
    auth_url: https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize
    token_url: https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
    allowed_groups: "<admin-group-id> <viewer-group-id>"
    role_attribute_path: contains(groups[*], '<admin-group-id>') && 'Admin' || 'Viewer'

ArgoCD (via Dex)

configs:
  cm:
    dex.config: |
      connectors:
        - type: microsoft
          id: microsoft
          name: Azure AD
          config:
            clientID: "<client-id>"
            clientSecret: $dex.azure.clientSecret
            tenant: "<tenant-id>"
            redirectURI: https://<argocd-domain>/api/dex/callback
            groups:
              - <admin-group-id>
  rbac:
    policy.csv: |
      g, <admin-group-id>, role:admin

Harbor

externalURL: https://harbor.<domain>
core:
  oidc:
    name: "azure"
    endpoint: "https://login.microsoftonline.com/<tenant-id>/v2.0"
    clientId: "<client-id>"
    clientSecret: "<from-secret>"
    scope: "openid,profile,email"
    groupsClaim: "groups"
    adminGroup: "<admin-group-id>"
    autoOnboard: true

Troubleshooting

Error Reference

Error CodeDescriptionSolution
AADSTS50011Reply URL mismatchVerify exact redirect URI including trailing slash
AADSTS50105User not assignedAdd user/group to Enterprise App assignments
AADSTS700016App not foundCheck client ID and tenant ID
AADSTS7000218Secret expiredRotate secret in Key Vault, restart pods
AADSTS90102Invalid redirect_uriCheck DD_SECURE_PROXY_SSL_HEADER=True for reverse proxy
AADSTS65001Consent not grantedRun 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 <app-id> --query groupMembershipClaims

# Check API permissions
az ad app permission list --id <app-id>

# Verify group exists and user is member
az ad group member check --group "<group-name>" --member-id "<user-object-id>"

Secret not syncing from Key Vault

# Check SecretProviderClass
kubectl describe secretproviderclass <name> -n <namespace>

# Check CSI driver pods
kubectl get pods -n kube-system | grep secrets-store

# Check managed identity access
az keyvault show --name <vault> --query properties.accessPolicies

Diagnostic Commands

# Test OAuth redirect
curl -sS -k -D - -o /dev/null "https://<app>/login/<provider>/" 2>&1 | grep -i location

# Check environment variables in pod
kubectl exec -n <ns> deploy/<app> -c <container> -- env | grep -i azure

# Decode JWT token (after login, from browser dev tools)
# Use https://jwt.io to decode and verify claims

Security Best Practices

  1. Never hardcode secrets - Always use Key Vault + CSI Driver
  2. Use managed identities - Avoid service principal credentials
  3. Restrict access by group - Enable appRoleAssignmentRequired=true
  4. Rotate secrets - Set calendar reminders before expiration
  5. Use HTTPS only - All redirect URIs must use HTTPS
  6. Single tenant - Never use multi-tenant for internal apps
  7. Audit logging - Enable Azure AD sign-in logs

Environment Reference

EnvironmentKey VaultManaged IdentityTenant ID
example-app-devkv-example-dev-hlg<WORKLOAD_IDENTITY_CLIENT_ID><TENANT_ID>
example-app-hubkv-example-default<WORKLOAD_IDENTITY_CLIENT_ID><TENANT_ID>
example-app-prdkv-example-prd<WORKLOAD_IDENTITY_CLIENT_ID><TENANT_ID>

Detailed Reference

For complete implementation examples:


Gotchas

  • Group claims default to objectId, not name — enable optionalClaims: groups: SecurityGroup AND set token version 2 in the manifest, or apps that match by name see nothing.
  • Token scopes: https://graph.microsoft.com/.default scope grants admin-consented permissions only; User.Read.All on a delegated token still requires admin consent at first use.
  • OIDC redirect URIs require EXACT match — trailing slash mismatch returns AADSTS50011 with a vague error that looks like a network issue.
  • Group-claims overage at 200 groups: users in >200 groups get NO group claims (overage). Switch to Graph query for membership lookup.
  • App-token lifetime policies are per-app — default 1 hour. Long batch jobs hitting hour-2 silently 401 unless you wrap every call with refresh-on-401.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.