A cloud-based identity and access management service for securing user authentication and resource access
A 403 from an authorized API endpoint in this setup almost always comes from one of three configuration gaps:
- The API’s scope isn’t being requested by the Blazor WebAssembly app.
- The API isn’t configured to accept the audience/scope in the access token.
- The app registration or redirect URI configuration is incomplete or mismatched.
Use the following checks based on the Blazor WebAssembly + Microsoft Entra ID guidance.
- Confirm the API is exposed with a scope
- In the API’s Microsoft Entra app registration, under Expose an API, ensure an App ID URI and at least one scope (for example,
API.Access) are defined, similar to the hosted scenario where the App ID URI isapi://{SERVER API APP CLIENT ID}and a scope likeAPI.Accessis added. - Record the App ID URI and scope name.
- Ensure the Blazor WASM app requests the API scope The Blazor WebAssembly template does not automatically request an access token for a secure API.
In Program.cs (or equivalent), after AddMsalAuthentication, add the API scope to DefaultAccessTokenScopes:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
// Request API access token as part of sign-in
options.ProviderOptions.DefaultAccessTokenScopes.Add("api://{SERVER-API-CLIENT-ID}/API.Access");
});
Replace the scope string with the actual App ID URI and scope name from the API registration. This ensures the access token presented to the API contains the correct scp claim.
- Verify Blazor WASM Entra configuration
In
wwwroot/appsettings.json, confirm the Entra settings match the client app registration:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/{TENANT ID}",
"ClientId": "{CLIENT ID}",
"ValidateAuthority": true
}
}
-
{TENANT ID}must be the Directory (tenant) ID. -
{CLIENT ID}must be the Application (client) ID of the Blazor client app.
- Confirm the SPA redirect URI and platform configuration In the client app registration:
- Under Authentication → Platform configurations → Single-page application:
- Ensure
https://localhost/authentication/login-callbackis present as a redirect URI. - Ensure Implicit grant → Access tokens and ID tokens are not selected, as implicit grant is not recommended for Blazor apps using MSAL v2.0 or later.
- Ensure
- Validate the API’s token validation configuration On the ASP.NET Core API side, ensure the JWT bearer configuration matches the token being sent:
-
Authorityshould match the tenant (e.g.,https://login.microsoftonline.com/{TENANT ID}or the appropriate instance/tenant). -
Audience(orValidAudience) should match the API’s App ID URI or client ID, depending on how the API is configured.
If the API expects a different audience or scope than what the Blazor app is requesting, the API will reject the token and return 403.
- Use logs and network traces to pinpoint the issue If configuration appears correct:
- Enable client-side authentication logging for Blazor WebAssembly as described in Client-side authentication logging in the Blazor logging guidance.
- Use browser developer tools (Network tab) to inspect the call to the API:
- Confirm the
Authorization: Bearer <token>header is present. - Decode the access token and verify:
-
aud(audience) matches the API. -
scp(scopes) includes the API scope (for example,API.Access).
-
- Confirm the
If the scope or audience is missing or incorrect, adjust DefaultAccessTokenScopes in the Blazor app and/or the API’s Expose an API and JWT bearer configuration.
- Common misconfigurations that lead to 403 From the documented common errors:
- Missing or incorrect Authority, Tenant ID, Client ID, or Redirect URI in the client.
- Incorrect request scopes (not adding the API scope to
DefaultAccessTokenScopes). - Incorrect or missing server API permissions (API not exposed with a scope, or client not granted that scope).
- Running the app at a different port than configured in redirect URIs for non-
localhostaddresses.
Correcting the API scope exposure and ensuring the Blazor WASM app requests that scope via DefaultAccessTokenScopes typically resolves 403 responses when anonymous endpoints work but authorized ones do not.
References: