Search code examples
asp.net-coreblazorazure-ad-msal.net-8.0microsoft-entra-id

Why does my Entra MSAL flow work for log in, but I get a 404 when logging out?


I am having a strange issue. I am using MSAL 2 with an Entra Customer tenant, and users can log in, but cannot log out.

Here's my sample configuration, which I had to change from the original documentation due to a bug where if you are not a global admin, you cannot login.

"AzureAd": {
    "Authority": "https://55...67.ciamlogin.com/55...67/v2.0",
    "Instance": "https://55...67.ciamlogin.com/55...67/v2.0",
    "Domain": "exampleTenant.onmicrosoft.com",
    "ClientId": "44...56",
    "ClientSecret": "{{omitted}}",
    "ClientCertificates": [
    ],
    // the following is required to handle Continuous Access Evaluation challenges
    "ClientCapabilities": [ "cp1" ],
    "CallbackPath": "/signin-oidc"
  },
  "DownstreamApi": {
    "Scopes": "User.ReadBasic.All user.read email"
  }

My DI Registration:

private static void RegisterAuthentication(IServiceCollection services, IConfiguration configuration)
{

    var authenticatedPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();

    // <ms_docref_add_msal>
    IEnumerable<string>? initialScopes = configuration["DownstreamApi:Scopes"]?.Split(' ');

    services.AddMicrosoftIdentityWebAppAuthentication(configuration, "AzureAd")
        .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
        .AddDownstreamApi("DownstreamApi", configuration.GetSection("DownstreamApi"))
        .AddInMemoryTokenCaches();
    // </ms_docref_add_msal>

    // <ms_docref_add_default_controller_for_sign-in-out>
    services.AddRazorPages().AddMvcOptions(options =>
    {
        options.Filters.Add(new AuthorizeFilter(authenticatedPolicy));
        //filters omitted for brevity
    }).AddMicrosoftIdentityUI();
    // </ms_docref_add_default_controller_for_sign-in-out>

    services.AddCascadingAuthenticationState();
    services.AddAuthorizationBuilder()
        //policies omitted for brevity
        .AddFallbackPolicy(PolicyConstants.MustBeAuthenticated, authenticatedPolicy);
}

And then, for clarity, here's the app configuration

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseWebAssemblyDebugging();
}
else
{
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();
app.UseAntiforgery();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode()
    .AddAdditionalAssemblies(typeof(MyClientApp._Imports).Assembly);

app.Run();

Then, I have a redirect for unauthenticated users to MicrosoftIdentity/Account/SignIn. This works great. Users are sent to login and come back authenticated with claims.

Now I wanted to add a logout link

<a href="MicrosoftIdentity/Account/SignOut" class="ti-dropdown-item">
    <i class="ti ti-logout  text-lg"></i>
    Sign Out
</a>

However, when the redirection happens, MicrosoftIdentity/Account/SignOut throws a 404. I think it's odd that signin works, but signout does not.


Solution

  • OP is facing 404 error when hitting the AAD sign out action.

    Based on the confirmation from OP, lacking of app.AddRouting(); and app.MapControllers(); caused the issue.