// this is how you get tokens obtained by the OIDC middleware
        //private Task<string> GetAccessTokenAsync()
        //{
        //    return httpContextAccessor.HttpContext.GetTokenAsync("access_token");
        //}

        // this is how you get tokens with MSAL
        private async Task <string> GetAccessTokenAsync()
        {
            try
            {
                var principal = httpContextAccessor.HttpContext.User;

                var tokenCache = new DistributedTokenCache(distributedCache, principal.FindFirst(Constants.ObjectIdClaimType).Value).GetMSALCache();
                var client     = new ConfidentialClientApplication(authOptions.ClientId,
                                                                   authOptions.GetAuthority(principal.FindFirst(Constants.AcrClaimType).Value),
                                                                   "https://app", // it's not really needed
                                                                   new ClientCredential(authOptions.ClientSecret),
                                                                   tokenCache,
                                                                   null);

                var account = (await client.GetAccountsAsync()).FirstOrDefault();

                var result = await client.AcquireTokenSilentAsync(new[] { $"{authOptions.ApiIdentifier}/read_values" },
                                                                  account);

                return(result.IdToken);
            }
            catch (MsalUiRequiredException)
            {
                throw new ReauthenticationRequiredException();
            }
        }
        private static OpenIdConnectEvents CreateOpenIdConnectEventHandlers(B2CAuthenticationOptions authOptions, B2CPolicies policies, IDistributedCache distributedCache)
        {
            return(new OpenIdConnectEvents
            {
                OnRedirectToIdentityProvider = context => SetIssuerAddressAsync(context, policies.SignInOrSignUpPolicy),
                OnRedirectToIdentityProviderForSignOut = context => SetIssuerAddressForSignOutAsync(context, policies.SignInOrSignUpPolicy),
                OnAuthorizationCodeReceived = async context =>
                {
                    try
                    {
                        var principal = context.Principal;

                        var userTokenCache = new DistributedTokenCache(distributedCache, principal.FindFirst(Constants.ObjectIdClaimType).Value).GetMSALCache();
                        var client = new ConfidentialClientApplication(authOptions.ClientId,
                                                                       authOptions.GetAuthority(principal.FindFirst(Constants.AcrClaimType).Value),
                                                                       "https://app", // it's not really needed
                                                                       new ClientCredential(authOptions.ClientSecret),
                                                                       userTokenCache,
                                                                       null);

                        var result = await client.AcquireTokenByAuthorizationCodeAsync(context.TokenEndpointRequest.Code,
                                                                                       new[] { $"{authOptions.ApiIdentifier}/read_values" });

                        context.HandleCodeRedemption(result.AccessToken, result.IdToken);
                    }
                    catch (Exception ex)
                    {
                        context.Fail(ex);
                    }
                },
                OnAuthenticationFailed = context =>
                {
                    context.Fail(context.Exception);
                    return Task.FromResult(0);
                },
                OnMessageReceived = context =>
                {
                    if (!string.IsNullOrEmpty(context.ProtocolMessage.Error) &&
                        !string.IsNullOrEmpty(context.ProtocolMessage.ErrorDescription))
                    {
                        if (context.ProtocolMessage.ErrorDescription.StartsWith("AADB2C90091")) // cancel profile editing
                        {
                            context.HandleResponse();
                            context.Response.Redirect("/");
                        }
                        else if (context.ProtocolMessage.ErrorDescription.StartsWith("AADB2C90118")) // forgot password
                        {
                            context.HandleResponse();
                            context.Response.Redirect("/Account/ResetPassword");
                        }
                    }

                    return Task.FromResult(0);
                }
            });
        }