Skip to content

Authorization code should always be redeemed with MSAL #3631

@scrocquesel-ml150

Description

@scrocquesel-ml150

Microsoft.Identity.Web Library

Microsoft.Identity.Web

Microsoft.Identity.Web version

4.1.0

Web app

Sign-in users

Web API

Not Applicable

Token cache serialization

Not Applicable

Description

I have configured my web application to use SignedAssertionFromManagedIdentity instead of clientSecret and ResponseType=code.
When redeeming the authorization_code on redirection, the app throws the exception

Microsoft.AspNetCore.Authentication.AuthenticationFailureException: An error was encountered while handling the remote login.
 ---> Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolException: Message contains error: 'invalid_client', error_description: 'AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'. Trace ID: 4fd981cf-1ae9-4f05-9c7b-f0608a8f0700 Correlation ID: eeb1c507-503c-4a69-84d1-42f2f39543cb Timestamp: 2025-11-28 14:53:40Z', error_uri: 'https://login.microsoftonline.com/error?code=7000218'.
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.RedeemAuthorizationCodeAsync(OpenIdConnectMessage tokenEndpointRequest)
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleRemoteAuthenticateAsync()
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

I configured logging level to debug but I don't see relevant traces around the exception that would tell the credential source fails.

With client secret, it works.

My app runs as a docker container inside App Services. The managed identity works ok to retrieve manually an assertion with this endpoint

// add a minimal endpoint, that returns "Hello World!"
app.MapGet("/token", async (ILogger<Program> logger) =>
{
    var fic = new ManagedIdentityClientAssertion("zzz", null, logger);
    var a = await fic.GetSignedAssertionAsync(new Microsoft.Identity.Client.AssertionRequestOptions()
    {
        ClientID = "yyy",
        TokenEndpoint = "https://login.microsoftonline.com/xxx/oauth2/token"
    });
    return a;
});

Reproduction steps

  1. Program.cs
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration);
    var app = builder.Build();
    
    app.MapGet("/protected", () => "Hello").RequireAuthorization(p => p.RequireAuthenticatedUser());
    
    app.Run();
  2. Configuration
{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "xxx",
    "ClientId": "yyy",
    "ResponseType": "code",
    "ClientCredentials": [ 
      {
        "SourceType": "SignedAssertionFromManagedIdentity",
        "ManagedIdentityClientId": "zzz"
      }
    ],
    "CallbackPath": "/signin-oidc"
  }
}
  1. In Entra of tenant Id xxx, create an app registration, declare a FIC with the managed identity zzz. This app registration has a client id yyy.

Error message

No response

Id Web logs

No response

Relevant code snippets

provided above

Regression

No response

Expected behavior

I would expect a more meaningfull exception, or at least some traces. With subscribeToOpenIdConnectMiddlewareDiagnosticsEvents set to true, I do have traces from category Microsoft.Identity.Web but not useful. Otherwise, I don't see any traces from this category.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions