AzureAD / microsoft-identity-web

Helps creating protected web apps and web APIs with Microsoft identity platform and Azure AD B2C
MIT License
681 stars 211 forks source link

[Bug] AADB2C90088: The provided grant has not been issued for this endpoint after Reset Password #729

Closed quisitive-crogers closed 3 years ago

quisitive-crogers commented 4 years ago

Which version of Microsoft Identity Web are you using? Note that to get help, you need to run the latest version.

Where is the issue?

Is this a new or an existing app?

This is a new app. I reproduced the error in a clean slate web app.

Repro Included clean slate web app that is exhibiting the behavior. TestApplication.zip

Expected behavior Once user has reset their password, they should be redirected to login screen to log in with the new password.

Actual behavior user is redirected to the MicrosoftIdentity/Account/Error page on the app which results in a 404 error. An exception is logged stating

MSAL.NetCore.4.21.1.0.MsalUiRequiredException: 
    ErrorCode: invalid_grant
Microsoft.Identity.Client.MsalUiRequiredException: AADB2C90088: The provided grant has not been issued for this endpoint. Actual Value : B2C_1_SA_SignupSignin and Expected Value : B2C_1_SA_ResetPassword

These are the packages I am referencing


    <PackageReference Include="Microsoft.Identity.Web" Version="1.2.0" />
    <PackageReference Include="Microsoft.Identity.Web.UI" Version="1.2.0" />

Possible solution

Additional context / logs / screenshots Add any other context about the problem here, such as logs and screenshots.

jennyf19 commented 4 years ago

@quisitive-crogers thanks for the repro. I tried w/our templates, and was not able to repro it. I would suggest building the app from one of the templates, so we can ensure all the correct pieces are there, and then let us know if the issue still repros.

dotnet new mvc2 --auth IndividualB2C

quisitive-crogers commented 4 years ago

@jennyf19

I have narrowed it down by comparing with the template you suggested. It is one of these two that is causing the problem.

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
             .AddMicrosoftIdentityWebApp(Configuration, "AzureAdB2C")
    -->   .EnableTokenAcquisitionToCallDownstreamApi(new string[] { "https://randomtenant.onmicrosoft.com/myapp-uat/access" })
    -->   .AddInMemoryTokenCaches();

I am assuming it has something to do with token validation, but I am unable to track it down.

quisitive-crogers commented 4 years ago

Upon further debugging the flow is as such... the user is not yet logged in, as evidenced by the fact that context.Principal is null. Any thoughts here?

Specifically, line 152 of TokenAcquisition.cs is grabbing the userFlow from the context.Principal (which is null because the user has not yet authenticated having just left the reset password screen). Because that is null, it defaults to the DefaultUserFlow, which appears to be the SignUpSignInPolicyId. That is then apparently compared to the actual authority that is returned, which is the ResetPasswordPolicyId. Since they don't match, it throws the exception.

I would honestly expect the redirect to the sign in screen to happen before any attempt to get a downstream api token.

Incidentally, I was able to reproduce this with the bae template you provided earlier.

jennyf19 commented 4 years ago

@quisitive-crogers thanks for the additional info, like i said i wasn't able to repro it, but will look into this more. Seems related to this issue but we've since fixed it. I'll take a look. thanks again.

quisitive-crogers commented 4 years ago

@jennyf19 thanks. This is heading into UAT next week, so I need to come up with a work around. Is there an example of how to manually acquire the API token at the controller level without the middleware?

jennyf19 commented 4 years ago

@quisitive-crogers I tried the template for mvc2 (the one I sent above)...You should have this in the Startup.cs

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C"));
            services.AddControllersWithViews();
           services.AddRazorPages()
                .AddMicrosoftIdentityUI();
        }

and I'm not able to repro the issue still. Are you starting w/the mvc2 web app template and just changing the values in appSettings.json? If not, let's start there and then we can go incrementally. just a thought.

One other thing to try, is in the B2C portal, you can test out the user flows there directly to make sure they are set up properly: image

quisitive-crogers commented 4 years ago

@jennyf19 Yes, that much works. The problem appears when I add the DownstreamAPI pieces as shown.


            services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C"))
                .EnableTokenAcquisitionToCallDownstreamApi(new string[] { "https://randomtenant.onmicrosoft.com/myapp-uat/access" })
                .AddInMemoryTokenCaches(); 

I pulled down this repo and referenced it directly and can confirm that this is being thrown by the code here, not by the userflow.

jennyf19 commented 4 years ago

@quisitive-crogers ok. thanks for confirming. did you try this template: dotnet new webapi2 --auth IndividualB2C?

quisitive-crogers commented 4 years ago

@jennyf19 yup. I can confirm that the problem occurs when using that template.

quisitive-crogers commented 4 years ago

@jennyf19 Thinking on this a bit and testing with another app in the same organization that is working, I see that one difference is that the userflow that is working is the old style and the one I am using is the new recommended style. I don't know if that makes a difference.

For now, I am going to follow the steps here to see if I can manually retrieve the API tokens on demand.

jennyf19 commented 4 years ago

@quisitive-crogers what is the "new recommended style"? Can you share a link to a doc?

quisitive-crogers commented 4 years ago

This is what I mean. I will try creating a new password reset userflow in the "standard" fashion tomorrow to see if that works and report back.

image

jennyf19 commented 4 years ago

@quisitive-crogers oh, interesting. I'll check w/our B2C team as well. I wasn't aware of changes made there. Thanks for noticing that, you're right, that could be the issue. I'll check back tomorrow w/you.

quisitive-crogers commented 4 years ago

@jennyf19 I just tested against user flow built on that "standard" variant and everything operates as it should. I suppose for now, that is my best workaround, but I would be interested in seeing if this does get fixed in the future.

jennyf19 commented 4 years ago

@quisitive-crogers thanks for the update. Will continue to sort this out w/the b2c team on our end. Will keep you posted.

jennyf19 commented 3 years ago

@quisitive-crogers I'm not able to repro this w/the new policy (recommended), and we had someone from B2C try as well, and they are not able to repro. If you're still having the issue w/the recommended version, maybe send me an email and I can get you in contact w/someone from B2C to help you out. jeferrie@microsoft.com

Going to close, as cannot repro, but feel free to reopen &/or send the email.

xavier-90 commented 3 years ago

@jennyf19 I can reproduce this & have sent you an email with further details.

jennyf19 commented 3 years ago

@xavier-90 The issue is that a client secret is included w/the web app, but there is no call to a downstream web API. Because the client secret is included in the appsettings.json, it’s implied that a call to a downstream API will happen, so we request an auth code from AAD B2C, which then invokes MSAL .NET to redeem that code for an access token. But an access token isn't needed, as there is no call to a downstream web API. Need the id_token, which has information about the signed in user.

By removing/commenting out the client secret in appsettings.json, I was able to redirect correctly to the initial starting page because I only received the id_token, and not the code + id_token.

Closing as by design, but we will update the wiki. thanks for your help w/this one!

xavier-90 commented 3 years ago

@jennyf19 I do occasionally use Microsoft.Graph "downstream" hence the client secret in the AzureAdB2C section. To avoid triggering the default behaviour I have now moved the secret to a separate section of appsettings.json.

Thank you for your support in getting to the bottom of this one!