authentication_troubleshooting - mamoorkhan/glasslewis GitHub Wiki
This guide helps you diagnose and fix common authentication issues with Azure Entra External ID integration.
Use this decision tree to quickly identify your issue:
flowchart TD
A[Authentication Issue] --> B{Where does it fail?}
B -->|Login redirect| C[Redirect Issues]
B -->|After login| D[Token Issues]
B -->|API calls| E[CORS/Authorization Issues]
B -->|Local development| F[Configuration Issues]
C --> C1[Check redirect URIs]
D --> D1[Check token configuration]
E --> E1[Check CORS policy]
F --> F1[Check environment setup]
Error Message:
AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application
Causes & Solutions:
-
Redirect URI not registered
# Check current redirect URIs az ad app show --id "your-client-id" --query "spa.redirectUris"
Fix: Add missing URI in Azure Portal:
- App Registration → Authentication → Add URI
- Ensure exact match (including HTTP/HTTPS and trailing slashes)
-
Case sensitivity issues
❌ Wrong: http://localhost:4200/ ✅ Correct: http://localhost:4200
-
Development vs Production URLs
// Check your environment.ts file export const environment = { msalConfig: { auth: { redirectUri: 'http://localhost:4200' // Must match Azure registration } } };
Error Message:
AADSTS65001: The user or administrator has not consented to use the application
Solutions:
-
Grant Admin Consent
- Azure Portal → App Registration → API permissions
- Click "Grant admin consent for [Organization]"
- Verify green checkmarks appear
-
Check API Permissions
Required permissions for client app: ✅ API://your-api-id/Company.Read ✅ API://your-api-id/Company.ReadWrite
-
Verify Scopes in Code
// Angular: Check your MSAL configuration export const environment = { apiConfig: { scopes: ['api://your-api-id/Company.Read'], uri: 'https://localhost:5001/api/v1/' } };
Error Message:
AADSTS700016: Application with identifier 'xxx' was not found in the directory
Solutions:
-
Verify Client ID
# Check if app exists az ad app show --id "your-client-id"
-
Check Tenant Context
- Ensure you're in the correct Azure tenant
- Verify tenant ID in configuration matches app registration tenant
-
Verify Environment Configuration
// Check environment.ts export const environment = { msalConfig: { auth: { clientId: 'correct-client-id-here', authority: 'https://your-tenant.ciamlogin.com/' } } };
- Authentication works but API calls fail
- Browser console shows CORS errors
-
Access-Control-Allow-Origin
errors
-
Update API CORS Configuration
// Program.cs or Startup.cs builder.Services.AddCors(options => { options.AddPolicy("AllowedOrigins", policy => { policy.WithOrigins( "http://localhost:4200", // Local development "https://your-app.azurestaticapps.net" // Production ) .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); }); }); app.UseCors("AllowedOrigins");
-
Check appsettings.json
{ "AllowedOrigins": [ "http://localhost:4200", "https://your-production-domain.com" ] }
-
Verify Angular HTTP Interceptor
// Check if Authorization header is being sent export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // Ensure Bearer token is added const authReq = req.clone({ setHeaders: { Authorization: `Bearer ${this.getToken()}` } }); return next.handle(authReq); } }
Symptoms:
-
401 Unauthorized
responses - "Token has expired" errors
- Authentication seems to work but API calls fail
Solutions:
-
Check Token Expiration
// Angular: Check if token is expired const isExpired = this.msalService.instance.getAllAccounts()[0]?.idTokenClaims?.exp ? Date.now() / 1000 > this.msalService.instance.getAllAccounts()[0].idTokenClaims.exp : true;
-
Implement Token Refresh
// Angular: Acquire token silently async getAccessToken(): Promise<string> { const account = this.msalService.instance.getAllAccounts()[0]; const accessTokenRequest = { scopes: ['api://your-api-id/Company.Read'], account: account }; try { const response = await this.msalService.instance.acquireTokenSilent(accessTokenRequest); return response.accessToken; } catch (error) { // If silent acquisition fails, redirect to login await this.msalService.instance.acquireTokenRedirect(accessTokenRequest); throw error; } }
-
Check API Token Validation
// API: Ensure proper token validation builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
Symptoms:
- Token validates but API returns
401
- "Invalid audience" in API logs
Solutions:
-
Verify API Configuration
// appsettings.json { "AzureAd": { "ClientId": "your-api-client-id", // Must match API app registration "Authority": "https://your-tenant.ciamlogin.com/" } }
-
Check Token Audience
# Decode JWT token to check 'aud' claim # Use jwt.io to decode and verify audience matches your API client ID
Common Issues:
- Wrong client IDs in environment files
- Incorrect authority URLs
- Missing user secrets
Solutions:
-
Verify User Secrets
cd src/GlassLewis.Api dotnet user-secrets list # Should show: # AzureAd:ClientId = your-api-client-id # AzureAd:Authority = https://your-tenant.ciamlogin.com/ # AzureAd:TenantId = your-tenant-id
-
Check Angular Environment
// src/environments/environment.development.ts export const environment = { production: false, apiUrl: 'https://localhost:5001', msalConfig: { auth: { clientId: 'your-client-app-id', // NOT the API client ID authority: 'https://your-tenant.ciamlogin.com/', redirectUri: 'http://localhost:4200' } } };
-
SSL Certificate Issues
# Trust development certificate dotnet dev-certs https --trust # Or run with specific ports dotnet run --urls="https://localhost:5001;http://localhost:5000"
-
Clear Browser Cache
- Clear all cookies and local storage for localhost
- Open browser in incognito/private mode
-
Check Browser Console
// Common console errors: // - "Mixed Content" warnings (HTTP calling HTTPS) // - CORS preflight failures // - Network errors to authority endpoints
Before deploying to production:
-
Update Redirect URIs
Add production URLs to client app registration: ✅ https://your-app.azurestaticapps.net ✅ https://your-custom-domain.com
-
Update CORS Origins
// Update API CORS policy policy.WithOrigins( "https://your-production-domain.com" );
-
Environment Variables
# Verify production environment variables # In Azure App Service → Configuration → Application settings AzureAd__ClientId=your-api-client-id AzureAd__Authority=https://your-tenant.ciamlogin.com/ AzureAd__TenantId=your-tenant-id
What to check:
- Authentication requests to
login.microsoftonline.com
- Token requests to your authority endpoint
- API calls with
Authorization: Bearer
headers - CORS preflight
OPTIONS
requests
Use jwt.io to decode tokens:
Check these claims:
{
"iss": "https://your-tenant.ciamlogin.com/",
"aud": "your-api-client-id",
"scp": "Company.Read Company.ReadWrite",
"sub": "user-id",
"exp": 1234567890
}
Check sign-in logs:
- Azure Portal → Microsoft Entra ID → Sign-in logs
- Filter by your application
- Look for error details and correlation IDs
Enable detailed logging:
// appsettings.Development.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore.Authentication": "Debug",
"Microsoft.AspNetCore.Authorization": "Debug"
}
}
}
Before troubleshooting, verify:
- API app registration exists with correct scopes
- Client app registration has correct redirect URIs
- Admin consent granted for API permissions
- Service principal has correct Azure RBAC permissions
- Client ID matches between Azure and code
- Authority URL format is correct
- API scopes match between client and API apps
- CORS policy includes all necessary origins
- HTTPS certificates valid and trusted
- No proxy or firewall blocking auth endpoints
- Browser allows third-party cookies
- No browser extensions blocking authentication
// API: Add to Program.cs
builder.Logging.AddConsole();
builder.Logging.SetMinimumLevel(LogLevel.Debug);
// Angular: Enable MSAL logging
export const environment = {
msalConfig: {
system: {
loggerOptions: {
loggerCallback: (level: LogLevel, message: string) => {
console.log(`MSAL [${LogLevel[level]}]: ${message}`);
},
logLevel: LogLevel.Verbose
}
}
}
};
Create a minimal test:
// Simple MSAL test
const msalInstance = new PublicClientApplication({
auth: {
clientId: 'your-client-id',
authority: 'https://your-tenant.ciamlogin.com/'
}
});
// Test login
msalInstance.loginRedirect();
- Azure Setup Guide - Complete app registration setup
- Local Development Setup - Development environment configuration
- Common Issues - FAQ and general troubleshooting