Share via

ASP.NET Core Blazor WASM Standalone with Entra ID and ASP.NET Core API

Ross 0 Reputation points
2026-05-06T00:32:32.21+00:00

I am trying to follow the following articles.

  1. https://docs.azure.cn/en-us/entra/identity-platform/tutorial-web-api-dotnet-core-build-app
  2. https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/standalone-with-microsoft-entra-id?view=aspnetcore-9.0

The client will connect to ME-ID. I can connect to the API and retrieve data that is marked Allow Anonymous. I can retrieve User Claims, Access token and Access token claims.

My problem is that when I try to access a an Authorized end point I get a 403 response.I feel like I am missing something. Is there a working example anywhere that I can look at to compare?

Ross McLeod

Microsoft Security | Microsoft Entra | Microsoft Entra ID

1 answer

Sort by: Most helpful
  1. Q&A Assist
    2026-05-06T00:32:50.39+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    A 403 from an authorized API endpoint in this setup almost always comes from one of three configuration gaps:

    1. The API’s scope isn’t being requested by the Blazor WebAssembly app.
    2. The API isn’t configured to accept the audience/scope in the access token.
    3. The app registration or redirect URI configuration is incomplete or mismatched.

    Use the following checks based on the Blazor WebAssembly + Microsoft Entra ID guidance.

    1. 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 is api://{SERVER API APP CLIENT ID} and a scope like API.Access is added.
    • Record the App ID URI and scope name.
    1. 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.

    1. 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.
    1. Confirm the SPA redirect URI and platform configuration In the client app registration:
    • Under AuthenticationPlatform configurationsSingle-page application:
      • Ensure https://localhost/authentication/login-callback is present as a redirect URI.
      • Ensure Implicit grantAccess tokens and ID tokens are not selected, as implicit grant is not recommended for Blazor apps using MSAL v2.0 or later.
    1. Validate the API’s token validation configuration On the ASP.NET Core API side, ensure the JWT bearer configuration matches the token being sent:
    • Authority should match the tenant (e.g., https://login.microsoftonline.com/{TENANT ID} or the appropriate instance/tenant).
    • Audience (or ValidAudience) 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.

    1. 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).

    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.

    1. 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-localhost addresses.

    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:

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.