Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Middleware throws System.UnauthorizedAccessException, causes 500 error for users #1716

Closed
3 of 8 tasks
MattKotsenas opened this issue Apr 22, 2022 · 1 comment · Fixed by #1717
Closed
3 of 8 tasks
Assignees
Milestone

Comments

@MattKotsenas
Copy link
Contributor

MattKotsenas commented Apr 22, 2022

Which version of Microsoft Identity Web are you using?
1.22.3 (but from code inspection will also repro on the latest version)

Where is the issue?

  • Web app
    • Sign-in users
    • Sign-in users and call web APIs
  • Web API
    • Protected web APIs (validating tokens)
    • Protected web APIs (validating scopes)
    • Protected web APIs call downstream web APIs
  • Token cache serialization
    • In-memory caches
    • Session caches
    • Distributed caches

Is this a new or an existing app?
This is an existing app that we're building; I haven't upgraded Microsoft Identity Web, but started seeing this issue.

Repro
There isn't an obvious code repro here, in our particular case we believe it was from trying to run our app without yet granting admin consent for the required roles.

Expected behavior
Like with other bad tokens or configuration issues (like a missing tid or tenantId claim) I would expect the middleware pipeline to return a 401 Unauthorized

Actual behavior
The JwtBearerHandler will throw an UnauthorizedAccessException that looks like this:

System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token.
  at Microsoft.Identity.Web.MicrosoftIdentityWebApiAuthenticationBuilderExtensions.<>c__DisplayClass3_1.<<AddMicrosoftIdentityWebApiImplementation>b__1>d.MoveNext()
  at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
  at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
  at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
  at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
  at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)

which results in an unhandled exception in the auth middleware pipeline, which in turn results in a 500 error for the user.

Possible solution
A workaround for users hitting this issue today is to add the following into your IServiceCollection:

services.Configure<JwtBearerOptions>(scheme, options =>
{
    options.Events ??= new JwtBearerEvents();

    var tokenValidatedHandler = options.Events.OnTokenValidated;
    options.Events.OnTokenValidated = async context =>
    {
        try
        {
            await tokenValidatedHandler(context).ConfigureAwait(false);
        }
        catch (UnauthorizedAccessException e)
        {
            context.Fail(e);
        }
    };
});

This converts the unhandled exception into a handled auth failure that automatically does the appropriate Challenge response (at the expense of an exception throw / catch in a possible hot path).

Since other configuration issues (as mentioned in the "Expected Behavior" section) result in 401s, I would expect this issue to behave similarly.

I'll post a PR shortly with a proposed solution.

@jennyf19
Copy link
Collaborator

Included in 1.24.1

@jennyf19 jennyf19 added this to the 1.24.1 milestone Apr 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants