Azure AD B2C error AADB2C90057 when I am NOT trying to use the implicit flow
May 2
I am using ASP.NET Core 3.1, and Azure AD B2C. My goal is to use the Authorization Code Flow for my whole web app, but the documentation is not straight forward.
I followed the instructions given here: Web app that signs in users: Code configuration
However when I try to access my website, I get the following error:
[ERR] Message contains error: '"unauthorized_client"', error_description: '"AADB2C90057: The provided application is not configured to allow the 'OAuth' Implicit flow. uri: '"error_uri is null"'. (95c3107f)
In my Application Registration, I did NOT enable any of the two options for the Implicit Grant (Access tokens, and ID tokens).
Again, my goal is to use the Authorization Code Flow everywhere.
Any idea why I am getting the message saying that my app should be configured to allow the Implicit flow? How should I configure it to use the Authorization Code Flow?
1 answer
Accepted answer · original discussion
May 4
If you want to securely sign users into web applications, we should use the OpenId Connect protocol. The response_type needs to contain id_token. So we need to enable Implicit Grant. For more details, please refer to the document and the document
Regarding how to implement OpenId connect in .net core web app, we can use the sdk Microsoft.AspNetCore.Authentication.AzureADB2C.UI. The detailed steps are as below
Implement Azure AD B2C auth in web application
a. add the following settings in the appsettings.json
{ "AzureAdB2C": { "Instance": "https://<your-tenant-name>.b2clogin.com", "ClientId": "<web-app-application-id>", "Domain": "<your-b2c-domain>" "CallbackPath": "/signin-oidc", "SignUpSignInPolicyId": "B2C_1_test", "ResetPasswordPolicyId": "B2C_1_test2", "EditProfilePolicyId": "B2C_1_test1" }, ... }b. add the following code in the Startup.cs
public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme) .AddAzureADB2C(options => Configuration.Bind("AzureAdB2C", options)); services.AddRazorPages(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapControllers(); }); }c. Implement sign in and sign out. The sdk has helped us implement sign-in and sign-out method. So we can directly use it. For example
my login.cshtml
@using System.Security.Principal @using Microsoft.AspNetCore.Authentication.AzureADB2C.UI @using Microsoft.Extensions.Options @inject IOptionsMonitor<AzureADB2COptions> AzureADB2COptions @{ var options = AzureADB2COptions.Get(AzureADB2CDefaults.AuthenticationScheme); } <ul class="navbar-nav"> @if (User.Identity.IsAuthenticated) { <li class="nav-item"> <span class="nav-text text-dark">Hello @User.Identity.Name!</span> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="AzureADB2C" asp-controller="Account" asp-action="SignOut">Sign out</a> </li> } else { <li class="nav-item"> <a class="nav-link text-dark" asp-area="AzureADB2C" asp-controller="Account" asp-action="SignIn">Sign in</a> </li> } </ul>
Update
If you want to use Authorization Code Flow, please change startup.cs code as below.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
.AddAzureADB2C(options => Configuration.Bind("AzureAdB2C", options));
services.Configure<OpenIdConnectOptions>(AzureADB2CDefaults.OpenIdScheme, options =>
{
options.UsePkce = false;
options.ResponseType = "code";
options.Scope.Add("offline_access");
options.Events = new OpenIdConnectEvents()
{
OnAuthorizationCodeReceived = async context => {
var code = context.ProtocolMessage.Code;
var request = context.HttpContext.Request;
string currentUri = UriHelper.BuildAbsolute(
request.Scheme,
request.Host,
request.PathBase,
options.CallbackPath);
IConfidentialClientApplication cca = ConfidentialClientApplicationBuilder.Create(options.ClientId)
.WithB2CAuthority(options.Authority)
.WithRedirectUri(currentUri)
.WithClientSecret(options.ClientSecret)
.Build();
try
{
AuthenticationResult result = await cca.AcquireTokenByAuthorizationCode(options.Scope, code)
.ExecuteAsync();
context.HandleCodeRedemption(result.AccessToken, result.IdToken);
}
catch (Exception ex)
{
//TODO: Handle
throw;
}
}
};
});
services.AddRazorPages();
}
2 question comments
Use comments to ask for clarification. Post a solution as an answer.
May 3
May 3