Authentication Troubleshooting
Architecture
- •Browser → MSAL.js (PKCE flow) → JWT with
Chat.ReadWritescope - •Frontend → Backend (JWT Bearer token)
- •Backend → Azure AI Foundry (ManagedIdentityCredential)
Common Issues
| Issue | Cause | Fix |
|---|---|---|
401 on /api/* | Token missing scope | Verify Chat.ReadWrite scope in token |
ManagedIdentityCredential error locally | Wrong environment | Set ASPNETCORE_ENVIRONMENT=Development |
| Token popup blocked | Browser settings | Allow popups for localhost |
| Silent token fails | No cached token | Fallback to popup (handled by useAuth) |
Backend: JWT Validation
Accepts both audience formats:
csharp
options.TokenValidationParameters.ValidAudiences = new[]
{
builder.Configuration["AzureAd:ClientId"],
$"api://{builder.Configuration["AzureAd:ClientId"]}"
};
Backend: Credential Strategy
csharp
TokenCredential credential = env.IsDevelopment()
? new ChainedTokenCredential(
new AzureCliCredential(),
new AzureDeveloperCliCredential()) // Supports 'azd auth login'
: new ManagedIdentityCredential();
Local development: Requires az login or azd auth login to work.
Why ChainedTokenCredential: Avoids DefaultAzureCredential's unpredictable "fail fast" mode. Provides explicit, debuggable credential chain.
Frontend: MSAL Pattern
typescript
// Always try silent first
try {
const { accessToken } = await instance.acquireTokenSilent({
...tokenRequest,
account: accounts[0]
});
return accessToken;
} catch {
// Fallback to popup
const { accessToken } = await instance.acquireTokenPopup(tokenRequest);
return accessToken;
}
Debugging Steps
- •Check token contents: https://jwt.ms
- •Verify scope: Token should have
Chat.ReadWrite - •Check audience: Should match client ID or
api://{clientId} - •Verify Entra app: Check redirect URIs in Azure Portal
Environment Variables
Frontend (.env.local):
code
VITE_ENTRA_SPA_CLIENT_ID=... VITE_ENTRA_TENANT_ID=...
Backend (.env):
code
AzureAd__ClientId=... AzureAd__TenantId=...
Regenerate: Run azd up to recreate Entra app and .env files.
Related Skills
- •writing-csharp-code - Backend JWT validation and credential patterns
- •writing-typescript-code - Frontend MSAL integration and useAuth hook
- •deploying-to-azure - Entra app provisioning and RBAC configuration