The Problem That Keeps You Spinning
Have you ever integrated Azure AD B2C with an Azure App Service, only to find yourself trapped in an endless authentication redirect loop? You click login, get redirected to B2C, authenticate successfully, and then… back to the login page. Again. And again. And again.
If you’ve experienced this frustration, you’re not alone. This is one of the most common pitfalls when integrating Azure AD B2C custom policies with Azure App Service’s built-in authentication (Easy Auth). In this article, I’ll walk you through why this happens and how to fix it permanently.
Understanding the Root Cause
The infinite redirect loop typically occurs due to a mismatch between the OpenID Connect flow type and the response mode configured in your authentication setup. Specifically, the problem arises when using:
- Hybrid Flow: response_type=code+id_token
- Form Post Response Mode: response_mode=form_post
While this configuration works perfectly with many authentication scenarios, Azure App Service’s Easy Auth V2 doesn’t support the form_post response mode when used with Azure AD B2C custom policies. This incompatibility creates the dreaded redirect loop.
Why Does This Happen?
When you use response_mode=form_post:
- The B2C service tries to POST the authentication response back to your App Service
- Easy Auth expects the response via query parameters (not form post)
- The POST is rejected or mishandled
- Easy Auth redirects back to B2C to try again
- Repeat steps 1–4 infinitely
The Solution: Authorization Code Flow with Query Response Mode
The fix is elegantly simple: switch to the Authorization Code Flow with query response mode. This configuration is fully compatible with Easy Auth and follows modern OAuth 2.0 best practices.
What Needs to Change
Before (Problematic Configuration):
response_type=code+id_token
response_mode=form_post
After (Working Configuration):
response_type=code
response_mode=query
Implementation Guide
Step 1: Understanding App Service Authentication V2
Azure App Service provides built-in authentication through the authsettingsV2 configuration. This JSON-based configuration controls how your app handles authentication with various identity providers, including Azure AD B2C.
Step 2: Updating the Configuration
You can update the authentication configuration using the Azure REST API. Here’s the key section that needs modification:
{
"properties": {
"identityProviders": {
"azureActiveDirectory": {
"enabled": true,
"login": {
"loginParameters": [
"response_type=code",
"response_mode=query"
]
},
"registration": {
"clientId": "<your-b2c-client-id>",
"clientSecretSettingName": "B2C_CLIENT_SECRET",
"openIdIssuer": "https://<your-b2c-tenant>.b2clogin.com/<your-b2c-tenant>.onmicrosoft.com/<your-policy-name>/v2.0"
},
"validation": {
"allowedAudiences": [
"<your-b2c-client-id>"
]
}
}
},
"platform": {
"enabled": true
},
"globalValidation": {
"requireAuthentication": true,
"unauthenticatedClientAction": "RedirectToLoginPage"
},
"login": {
"tokenStore": {
"enabled": true
}
}
}
}Step 3: Automating the Fix with PowerShell
To make this repeatable and less error-prone, I created a PowerShell script that automates the entire process:
param(
[Parameter(Mandatory=$true)]
[string]$ResourceGroup,
[Parameter(Mandatory=$true)]
[string]$AppName,
[Parameter(Mandatory=$true)]
[string]$SubscriptionId
)
Write-Host "Fixing B2C authentication configuration for App Service: $AppName" -ForegroundColor Cyan
# Set the subscription context
az account set --subscription $SubscriptionId
# Get current configuration and backup
Write-Host "Backing up current configuration..." -ForegroundColor Yellow
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$backupFile = "auth-config-backup-$timestamp.json"
az rest --method GET `
--url "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Web/sites/$AppName/config/authsettingsV2/list?api-version=2022-03-01" `
--output json | Out-File $backupFile
Write-Host "Current configuration backed up to: $backupFile" -ForegroundColor Green
# Apply the fix
Write-Host "Applying authentication configuration fix..." -ForegroundColor Yellow
$authConfig = @{
properties = @{
identityProviders = @{
azureActiveDirectory = @{
enabled = $true
login = @{
loginParameters = @(
"response_type=code",
"response_mode=query"
)
}
}
}
}
} | ConvertTo-Json -Depth 10$authConfig | az rest --method PUT `
--url "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Web/sites/$AppName/config/authsettingsV2?api-version=2022-03-01" `
--body '@-'
Write-Host "Configuration updated successfully!" -ForegroundColor Green
# Restart the app service
Write-Host "Restarting App Service to apply changes..." -ForegroundColor Yellow
az webapp restart --resource-group $ResourceGroup --name $AppName
Write-Host "Done! Please test authentication in an incognito window." -ForegroundColor Green
Write-Host "Remember to clear browser cache/cookies before testing." -ForegroundColor Yellow
Step 4: Executing the Fix
Run the script with your environment parameters:
.\fix-b2c-auth.ps1 `
-ResourceGroup "your-resource-group" `
-AppName "your-app-service-name" `
-SubscriptionId "your-subscription-id"
Step 5: Verification
After applying the fix:
- Restart your App Service (the script does this automatically)
- Clear browser cache and cookies completely
- Test in an incognito/private window
- Navigate to your app URL
- You should now successfully authenticate without loops!
Verifying the Configuration
You can verify the configuration was applied correctly using the Azure CLI:
az rest --method GET \
--url "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/sites/<app-name>/config/authsettingsV2/list?api-version=2022-03-01"
Look for the loginParameters section under azureActiveDirectory.login. It should show:
"loginParameters": [
"response_type=code",
"response_mode=query"
]
Additional Considerations
B2C App Registration Configuration
Ensure your Azure AD B2C app registration has the correct redirect URI configured:
https://<your-app-name>.azurewebsites.net/.auth/login/aad/callback
Client Secret Management
Store your B2C client secret in App Service application settings (not in the configuration directly):
- Go to App Service → Configuration → Application settings
- Add a setting named B2C_CLIENT_SECRET
- Reference it in authsettingsV2 using clientSecretSettingName
Security Best Practices
- ✅ Use authorization code flow (more secure than implicit flow)
- ✅ Enable token store for token refresh capabilities
- ✅ Use query response mode for App Service compatibility
- ✅ Store secrets in application settings, not configuration files
- ✅ Always backup configurations before making changes
Common Pitfalls to Avoid
- Using the hostname instead of app name: When running Azure CLI commands, use the App Service name (e.g., myapp), not the hostname (e.g., myapp-abc123.azurewebsites.net)
- Wrong subscription context: Ensure you’re working in the correct Azure subscription before making changes
- Not restarting the app: Configuration changes require an app restart to take effect
- Browser cache: Old authentication cookies can cause issues; always test in incognito mode after changes
- Incomplete configuration: Ensure all required fields are present: clientId, openIdIssuer, allowedAudiences
Troubleshooting
If you still experience issues after applying the fix:
Check App Service Logs
az webapp log tail --resource-group <resource-group> --name <app-name>
Verify B2C Configuration
- Confirm the B2C custom policy is published and active
- Verify redirect URIs match exactly (including .auth/login/aad/callback)
- Check that the client secret hasn’t expired
Test the OpenID Configuration
Visit your B2C OpenID configuration endpoint:
https://<tenant>.b2clogin.com/<tenant>.onmicrosoft.com/<policy>/v2.0/.well-known/openid-configuration
Verify that response_types_supported includes code and response_modes_supported includes query.
Why This Solution Works
The authorization code flow with query response mode is:
- Compatible: Fully supported by Azure App Service Easy Auth
- Secure: Follows OAuth 2.0 and OpenID Connect best practices
- Modern: Recommended by Microsoft for new implementations
- Reliable: Eliminates the redirect loop completely
By using query parameters instead of form post, the authentication response is delivered in a format that Easy Auth can properly process, breaking the redirect loop.
Conclusion
The Azure AD B2C infinite redirect loop is a common issue with a straightforward solution. By switching from hybrid flow with form post to authorization code flow with query response mode, you can eliminate this problem while maintaining secure authentication.
The key takeaways:
- Understand the incompatibility between form_post and Easy Auth
- Use authorization code flow (response_type=code)
- Use query response mode (response_mode=query)
- Automate the fix with scripts for consistency
- Always test in incognito after configuration changes
Additional Resources
- Azure App Service Authentication Documentation
- Azure AD B2C Custom Policies
- OAuth 2.0 Authorization Code Flow
- OpenID Connect Specification
This article is based on real-world troubleshooting and implementation experience. The solution has been tested and verified in production environments.
Solving the Azure AD B2C Infinite Redirect Loop with App Service Authentication was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.