Home > Mobile >  Bearer Token Fails - Correlation Failed - Cookie Not Found
Bearer Token Fails - Correlation Failed - Cookie Not Found

Time:11-03

I'm trying to implement Microsoft's MSAL with an Angular frontend and Core MVC API.

I've been able to successfully authenticate on the Angular application and call Graph API endpoints. The Angular application uses the following code:

app.module.ts

@NgModule({
    declarations: [...],
    imports: [
        ...
        MsalModule.forRoot(
            new PublicClientApplication({
                auth: {
                    clientId: '47...',
                    authority: 'https://login.microsoftonline.com/6d...',
                    redirectUri: 'https://localhost:4200',
                },
                cache: {
                    cacheLocation: 'localStorage',
                    storeAuthStateInCookie: false
                },
            }),
            {
                interactionType: InteractionType.Redirect,
                authRequest: { scopes: ['user.read'] },
            },
            {
                interactionType: InteractionType.Redirect,
                protectedResourceMap: new Map([
                    ['https://graph.microsoft.com/v1.0/me', ['user.read']],
                    ['https://localhost:44333/Auth/Index', ['user.read']]
                ]),
            },
        ),
        RouterModule,
    ],
    providers: [{
        provide: HTTP_INTERCEPTORS,
        useClass: MsalInterceptor,
        multi: true,
    }],
    bootstrap: [AppComponent, MsalRedirectComponent],
})
export class AppModule {}

I can call the Graph API successfully by using HttpClient with the configured MsalInterceptor

this.http.get('https://graph.microsoft.com/v1.0/me')
    .subscribe(profile => { this.profile = profile; });

Next I attempt to call my own API with similar code

this.http.get('https://localhost:44333/Auth/Index')
    .subscribe(token => { this.token = token; });

However, this requests fails with the following error:

An unhandled exception occurred while processing the request.
    Exception: Correlation failed.
    Unknown location

Exception: An error was encountered while handling the remote login.
    Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()

I'm assuming the issue is somewhere on my API. I've configured Authentication in my .Net 5.0 MVC API like so:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
  services.AddCors();
  services.AddOptions();

  services.AddMvc()
   .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
   .AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);

  services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
   .AddMicrosoftIdentityWebApp(Configuration)
   .EnableTokenAcquisitionToCallDownstreamApi(new[] { "user.read" })
   .AddInMemoryTokenCaches();
}

appsettings.json

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "TenantId": "6d...",
    "ClientId": "47...",
    "ClientSecret": "..."
  },
}

AuthController.cs

namespace Auth.Services
{
  [Route("{controller}/{action}")]
  [Authorize]
  public class AuthController : Controller
  {
    private readonly ITokenAcquisition tokenAcquisition;
    public AuthController(ITokenAcquisition tokenAcquisition) => this.tokenAcquisition = tokenAcquisition;

    [HttpGet]
    public async Task<IActionResult> Index()
    {
      var scopes = new string[] { "user.read" };
      var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
      //...
      return Ok(...);
    }
  }
}

It doesn't seem like the application ever reaches the controller. None of the breakpoints are ever hit and when I examine the Events, there are two exceptions that are thrown:

Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler: Warning: '.AspNetCore.Correlation.XXX' cookie not found.    
System.Exception: An error was encountered while handling the remote login.
 ---> System.Exception: Correlation failed.
   --- 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.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) 

The part that has me interested is the "cookie not found" exception. I'm not sending a cookie but rather a Bearer Token.

HTTP Request

My guess is there is something lacking in the configuration of my API that would tell the middleware to look for the Bearer token rather than a cookie. However, when I attempted to configure the middleware to use AddJwtBearer(...) I ended up with a whole new slew of errors. So the question is, what am I missing to get the authentication MSAL token I have from the Angular frontend to work on the API backend?

CodePudding user response:

@weichch's comment set me down the right path, however the example uses obsolete code. All I needed to do was change my Startup.cs file to resemble the following:

public void ConfigureServices(IServiceCollection services)
{
  services.AddCors();
  services.AddOptions();

  services.AddMvc()
   .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
   .AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);

  // Note: the middleware is Api not App... I accidentally called App, and it took
  // me a minute to realize my mistake.
  services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
  services.AddControllers();
}

I also had an error in my Angular application that needed to be corrected. The scope for my API needed to be changed to my registered API in Azure Portal 'api://47.../access_as_user' Before the scope was changed, I was getting a "Bearer error="invalid_token", error_description="The signature is invalid"" error. So, app.module.ts came to resemble the following:

@NgModule({
    declarations: [...],
    imports: [
        ...
        MsalModule.forRoot(
            new PublicClientApplication({
                auth: {
                    clientId: '47...',
                    authority: 'https://login.microsoftonline.com/6d...',
                    redirectUri: 'https://localhost:4200',
                },
                cache: {
                    cacheLocation: 'localStorage',
                    storeAuthStateInCookie: false
                },
            }),
            {
                interactionType: InteractionType.Redirect,
                // !!! Changed Here !!!
                authRequest: { scopes: ['user.read', 'api://47.../access_as_user'] },
            },
            {
                interactionType: InteractionType.Redirect,
                protectedResourceMap: new Map([
                    ['https://graph.microsoft.com/v1.0/me', ['user.read']],
                    // !!! Changed Here !!!
                    ['https://localhost:44333/Auth/Index', ['api://47.../access_as_user']]
                ]),
            },
        ),
        RouterModule,
    ],
    providers: [{
        provide: HTTP_INTERCEPTORS,
        useClass: MsalInterceptor,
        multi: true,
    }],
    bootstrap: [AppComponent, MsalRedirectComponent],
})
export class AppModule {}
  • Related