当我不尝试使用隐式流时,Azure AD B2C 错误 AADB2C90057

Azure AD B2C error AADB2C90057 when I am NOT trying to use the implicit flow

我正在使用 ASP.NET Core 3.1 和 Azure AD B2C。我的目标是将 Authorization Code Flow 用于我的整个网络应用程序,但文档并不直接。

我按照此处给出的说明进行操作:Web app that signs in users: Code configuration

然而,当我尝试访问我的网站时,出现以下错误:

[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)

在我的应用程序注册中,我没有启用隐式授权的两个选项中的任何一个(访问令牌和 ID 令牌)。

同样,我的目标是在任何地方都使用授权代码流。

知道为什么我收到消息说我的应用程序应该配置为允许隐式流吗?我应该如何配置它以使用授权代码流?

如果您想安全地将用户登录到 Web 应用程序,我们应该使用 OpenId Connect 协议。 response_type 需要包含 id_token。所以我们需要启用Implicit Grant。详情请参考document and the document

关于如何在.net core web app中实现OpenId connect,我们可以使用sdk Microsoft.AspNetCore.Authentication.AzureADB2C.UI。详细步骤如下

  1. Register a web application in Azure AD B2C tenant

  2. 在 Web 应用程序中实施 Azure AD B2C 身份验证

    一个。在 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。在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。实现登录和退出。 sdk 已经帮我们实现了登录和退出的方法。所以我们可以直接使用它。例如

    我的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>
    
  3. 测试


更新

如果您想使用授权代码流程,请更改 startup.cs 代码如下。

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();
        }

之后 services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme).AddAzureADB2C( ....

只需添加

        services.Configure<OpenIdConnectOptions>(AzureADB2CDefaults.OpenIdScheme, options =>
        {
            options.ResponseType = OpenIdConnectResponseType.Code;
            options.Scope.Add(options.ClientId);
        });