Your enterprise web apps often need to serve both corporate users and customers. Here’s how to configure dual authentication in Azure App Service—without writing a single line of auth middleware.

🔑 Key Features

  • Single-tenant and multi-tenant authentication support
  • Automatic token validation and session management
  • Built-in token store for session persistence
  • Support for custom domains in authentication endpoints
  • Integration with Azure Monitor for auth telemetry

TL;DR

# Clone the repo
git clone https://github.com/taofik-ib/AzureARM-Projects/tree/main/Azure-app-service-Auth

Why This Matters

Modern web applications frequently need to support multiple authentication flows:

User Type Identity Solution Key Benefits
Employees & Partners Microsoft Entra ID • Single sign-on with corporate accounts
• Conditional Access policies
• Group-based authorization
Customers Azure AD B2C • Social login support
• Custom branding
• Progressive user profiling

The challenge? Configuring both providers traditionally requires complex middleware and careful coordination. This guide shows you how to achieve it using pure infrastructure as code.

Prerequisites

  • Azure subscription with Contributor access
  • For B2C setup: A tenant with a sign-up/sign-in user flow
  • App registrations created in both directories

💡 Pro Tip: Store your client secrets in Key Vault and reference them via @Microsoft.KeyVault(...) in your template.

Setting Up Microsoft Entra ID Authentication

1. Set the Parameters

The template’s core configuration starts with the authType parameter. This parameter determines which identity provider to enable, allowing you to toggle between Microsoft Entra ID and Azure AD B2C authentication flows:

"authType": {
    "allowedValues": [
        "AzureAD",
        "AzureADB2C"
    ],
    "type": "string",
    "metadata": {
        "description": "The type of authentication to use. Choose between AzureAD and AzureADB2C."
    }
},

This parameter drives conditional resource provisioning throughout the template, enabling either workforce or customer identity scenarios.

2. Configure the Variables

The ARM template uses variables to construct dynamic values and configure the authentication providers. These variables define the App Service naming convention and set up the OpenID Connect endpoints:

"variables": {
    "webAppPortalName": "[format('{0}-webapp', parameters('webAppName'))]",
    "appServicePlanName": "[format('AppServicePlan-{0}', parameters('webAppName'))]",
    
    // Key configuration: Points to the App Service's V2 auth settings resource
    "authSettingsName": "[concat(parameters('appServiceName'), '/authsettingsV2')]",
    
    // Constructs the OpenID Connect issuer URL for your tenant
    // This forms the base URL for all authentication endpoints
    "OpenIdIssuerUrl": "[concat(environment().authentication.loginEndpoint, '/', parameters('tenantId'), '/v2.0')]",
    
    "azureADSettings": {
        "enabled": "[if(equals(parameters('authType'), 'AzureAD'), true(), false())]",
        "registration": {
            "clientId": "[parameters('clientId')]",
            "clientSecretSettingName": "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET",
            "openIdIssuer": "[variables('OpenIdIssuerUrl')]"
        },
        "login": {
            "disableWWWAuthenticate": false
        },
        "validation": {
            "allowedAudiences": "[parameters('allowedAudiences')]",
            "allowedApplications": "[parameters('allowedApplications')]"
        }
    }
}

3. Add Required Parameters

The parameters file (parameters.json) contains the configuration values needed for your authentication setup. Here’s a breakdown of the essential parameters:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        // Unique name for your App Service
        "webAppName": {
            "value": "AuthAppService01"
        },
        // Authentication type: 'AzureAD' for workforce or 'AzureADB2C' for customer identities
        "authType": {
            "value": "AzureAD"
        },
        // Application (client) ID from your app registration
        "clientId": {
            "value": "Your Client Id"
        },
        // Node.js version for the App Service
        "runtimeVersion": {
            "value": "~1"
        }
    }
}

🔐 Security Best Practices:

  • Store sensitive values like clientSecret in Key Vault
  • Use managed identities for Key Vault access
  • Keep separate parameter files for different environments
  • Enable diagnostic settings for auth logging
  • Configure minimum TLS version 1.2
  • Set up IP restrictions alongside auth

Additional parameters you might need:

  • tenantId: Your Azure AD tenant ID (required for Entra ID)
  • allowedAudiences: List of allowed app IDs that can access your app
  • allowedApplications: Specific applications permitted to access your API
  • b2cTenantName: Your B2C tenant name (required for B2C setup)
  • b2cPolicy: Name of your sign-up/sign-in policy (e.g., “B2C_1_susi”)

These parameters drive the conditional logic in the template, determining which authentication provider to enable and how it should be configured.

Authentication Flows and Endpoints

Default Authentication Flow

App Service URL → /.auth/login/<provider> → Identity Provider → /.auth/login/callback

Custom Domain Authentication

https://your-domain.com → /.auth/login/aad → Entra ID → your-domain.com/.auth/login/callback

Available Authentication Endpoints

  • /.auth/login/<provider> - Initiate login
  • /.auth/logout - Sign out user
  • /.auth/refresh - Refresh access token
  • /.auth/me - Get current user info

Common Issues and Solutions

Issue Solution
Token validation errors Check issuer URL and audience configuration
CORS errors Add allowed origins in authentication settings
Session persistence issues Enable token store and check storage permissions
B2C policy errors Verify policy name and tenant configuration

Advanced Configuration Options

Once you have the basic authentication working, you can enhance your setup with these advanced features:

1. Token Store Configuration

Use this to enable session persistence and configure token lifetime:

"tokenStore": {
    "enabled": true,
    "tokenRefreshExtensionHours": 72,
    "fileSystem": {
        "directory": "/.auth/tokens"
    }
}

2. Custom Domain Support

Configure authentication endpoints with your custom domain:

"identityProviders": {
    "customOpenIdConnectProviders": {
        "name": "your-custom-domain",
        "registration": {
            "openIdConnectConfiguration": {
                "issuer": "https://login.yourdomain.com"
            }
        }
    }
}

3. Advanced Logging

Enable detailed authentication logging for monitoring and troubleshooting:

"diagnosticSettings": {
    "logs": [
        {
            "category": "AppServiceAuthenticationLogs",
            "enabled": true
        }
    ]
}

Security Considerations

  1. Token Configuration

    • Set appropriate token lifetime
    • Configure refresh token behavior
    • Enable token store encryption
  2. Network Security

    • Enable Azure Front Door WAF
    • Configure IP restrictions
    • Set up DDoS protection
  3. Monitoring

    • Enable authentication logging
    • Set up alerts for authentication failures
    • Monitor token usage and expiration

Next Steps

After implementing authentication:

  1. Enhanced Security

    • Implement Conditional Access policies
    • Set up MFA for sensitive operations
    • Configure risk-based authentication
  2. Custom Branding

    • Add company logo to login pages
    • Customize error pages
    • Implement custom domains
  3. Advanced Scenarios

    • Configure hybrid flows
    • Implement step-up authentication
    • Set up claims transformation

Resources