Azure-Samples / active-directory-aspnetcore-webapp-openidconnect-v2

An ASP.NET Core Web App which lets sign-in users (including in your org, many orgs, orgs + personal accounts, sovereign clouds) and call Web APIs (including Microsoft Graph)
MIT License
1.38k stars 994 forks source link

How to silently renew Id Token using AddMicrosoftIdentityWebAppAuthentication to Call Downstream API #638

Closed mschaefer-gresham closed 1 year ago

mschaefer-gresham commented 1 year ago

Please provide us with the following information:

This issue is for a: (mark with an x)

- [ ] bug report -> please search issues before submitting
- [ ] feature request
- [ x] documentation issue or request
- [ ] regression (a behavior that used to work and stopped in a new release)

The issue was found for the following scenario:

Please add an 'x' for the scenario(s) where you found an issue

  1. Web app that signs in users
    1. [ ] with a work and school account in your organization: 1-WebApp-OIDC/1-1-MyOrg
    2. [ ] with any work and school account: /1-WebApp-OIDC/1-2-AnyOrg
    3. [ ] with any work or school account or Microsoft personal account: 1-WebApp-OIDC/1-3-AnyOrgOrPersonal
    4. [ ] with users in National or sovereign clouds 1-WebApp-OIDC/1-4-Sovereign
    5. [ ] with B2C users 1-WebApp-OIDC/1-5-B2C
  2. Web app that calls Microsoft Graph
    1. [ ] Calling graph with the Microsoft Graph SDK: 2-WebApp-graph-user/2-1-Call-MSGraph
    2. [ ] With specific token caches: 2-WebApp-graph-user/2-2-TokenCache
    3. [ ] Calling Microsoft Graph in national clouds: 2-WebApp-graph-user/2-4-Sovereign-Call-MSGraph
  3. [ ] Web app calling several APIs 3-WebApp-multi-APIs
  4. [ ] Web app calling your own Web API
    1. [ ] with a work and school account in your organization: 4-WebApp-your-API/4-1-MyOrg
    2. [x ] with B2C users: 4-WebApp-your-API/4-2-B2C
    3. [ ] with any work and school account: 4-WebApp-your-API/4-3-AnyOrg
  5. Web app restricting users
    1. [ ] by Roles: 5-WebApp-AuthZ/5-1-Roles
    2. [ ] by Groups: 5-WebApp-AuthZ/5-2-Groups
  6. [ ] Deployment to Azure
  7. [ ] Other (please describe)

Repro-ing the issue

I am trying to implement the BFF-Gateway pattern (no tokens in the browser) to be used with a React SPA. The BFF is using AddMicrosoftIdentityWebAppAuthentication to handle login and issue a cookie to the SPA. And it is using YARP to proxy api requests to a downstream api. I'm using Azure B2C. Everything works perfectly until the BFF id_token expires in 1 hour. At that point, fetching the downstream api access token via tokenAcquisition.GetAccessTokenForUserAsync (which is called in a piece of middleware) fails:

var scope = _configuration["CallApi:ScopeForAccessToken"];
var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new[] { scope });
ctx.Request.Headers.Add("Authorization", "Bearer " + accessToken);

Exception:

IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent. 

ResponseBody: {"error":"invalid_grant","error_description":"AADB2C90085: The service has encountered an internal error. Please reauthenticate and try again.\r\nCorrelation ID: 622d6bd6-d06e-4142-86f2-b30a7a17b3b5\r\nTimestamp: 2022-11-25 09:31:23Z\r\n"} 

This is effectively the same as Call Downstream API Without The Helper Class example and this sample, except that I'm acquiring the access token in middleware, not a controller, so the downstream YARP requests contain the access token. BTW I get the same error if I do this inside a controller per this example. And I see no soluton to this in the sample.

There is a similar question here which references this sample, but for the B2C sample I see no solution to this problem.

I also found this sample and this explanation. But this uses Microsoft.Owin to configure auth, not AddMicrosoftIdentityWebAppAuthentication. This looks promising, but is a departure from most examples I see that use Microsoft.Identity.Web.

Can you please point to the correct soluton? I need call to be able to call _tokenAcquisition.GetAccessTokenForUserAsync after the id token expires without asking the user to reauthenticate and/or the SPA to having to reload.

Any log messages given by the failure

OS and Version?

macOS Ventura

Versions

of ASP.NET Core (7), of MSAL.NET

Attempting to troubleshooting yourself:

Mention any other details that might be useful


Thanks! We'll be in touch soon.

kalyankrishna1 commented 1 year ago

You do not "Renew" and id-token without a user not being in front of your system. Your scenario might be addressed by this sample -> Share the MSAL token cache between a web app and a background console worker app

mschaefer-gresham commented 1 year ago

@kalyankrishna1 thanks for the response. Can you clarify what you mean by "without a user being in front of your system"?

Could incremental consent and conditional access be used to solve this problem?