A web app built in .Net Core 3.1 calling a protected custom web API built in .Net Core 3.1 too. Both web app and web api is using the one registered app in ADB2C tenant. That registered app has scope and redirect URIs. Access token and ID token is enabled too. Sign-in user flow is created and configured for local identity and MS identity. Using the default UI page for sign-in but plans to customize it later. Both web api and web app is also using azure key vault for some confidential values.
The issue is that after signing in from the Sign-in page using either local identity or MS identity, the browser is just looping continuously. Sometimes the error is something like "the resource you are looking for has been removed or changed".
Below are my configurations and codes:
Azure App Settings and appsettings.json of Web App or client
"AzureAdB2C": {
"Scopes": "user_access",
"Instance": "https://{tenant}.b2clogin.com",
"ClientId": "{the registered app client ID}",
"Domain": "{tenant}.onmicrosoft.com",
"SignedOutCallbackPath": "/{signin policy}/oauth2/v2.0/logout/",
"SignUpSignInPolicyId": "{signin policy}",
"ClientSecret": "{the registered app client secret}"
},
Web App Startup >> ConfigureServices
services.AddDistributedMemoryCache();
.....
.....
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
// Handling SameSite cookie according to https://docs.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-3.1
options.HandleSameSiteCookieCompatibility();
});
services
.AddMicrosoftIdentityWebAppAuthentication(Configuration, Constants.AzureAdB2C)
.EnableTokenAcquisitionToCallDownstreamApi(new string[] { "user_access" })
//.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
services.AddAuthorization(options =>
{
var groups = new Groups(Configuration);
options.AddPolicy("IsAdmin", policy =>
policy.RequireClaim(Groups.ClaimName, groups.Admin));
options.AddPolicy("IsUser", policy =>
policy.RequireClaim(Groups.ClaimName, groups.User));
options.AddPolicy("GeneralAccess", policy =>
policy.RequireClaim(Groups.ClaimName, groups.User, groups.Admin));
options.FallbackPolicy = options.GetPolicy("GeneralAccess");
});
services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
services.AddRazorPages();
//Deployment Mode
var deploymentMode = Configuration.GetSection("DeploymentMode");
services.Configure<DeploymentMode>(deploymentMode);
//Set Session Timeout. Default is 20 minutes.
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
});
//services.AddSession(options =>
//{
// options.Cookie.HttpOnly = true;
// options.Cookie.IsEssential = true;
//});
services.AddMvc().AddSessionStateTempDataProvider();
services.AddSession();
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Latest);
//Configuring appsettings section AzureAdB2C, into IOptions
services.AddOptions();
services.Configure<OpenIdConnectOptions>(Configuration.GetSection("AzureAdB2C"));
Web App Controller(s)
[Authorize]
//[Authorize(Policy = "GeneralAccess")]
//[RequiredScope(RequiredScopesConfigurationKey = "AzureAdB2C:Scopes")]
public class HomeController : Controller {
...
...
}
Web App Service for token acquisition
....
HttpResponseMessage response = null;
string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(requiredScopes);
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
....