Azure B2C单点登录(SSO)未按预期工作

Azure B2C单点登录(SSO)未按预期工作,azure,azure-active-directory,azure-ad-b2c,Azure,Azure Active Directory,Azure Ad B2c,我现在正在Azure B2c上工作。我正在尝试实现单点登录(SSO)多应用程序。我还在多个应用程序上共享相同的登录配置文件,但它不起作用 我用多个应用程序创建了租户。单个应用程序可以使用预期的索赔信息登录。但我期待着登录一个应用程序应该自动登录其他应用程序。此时,每个请求登录系统的应用程序都会出现。根据Microsoft文档,会话行为应该在应用程序之间共享 这是我的登录档案 https://login.microsoftonline.com/te/tenantname.onmicrosoft.c

我现在正在Azure B2c上工作。我正在尝试实现单点登录(SSO)多应用程序。我还在多个应用程序上共享相同的登录配置文件,但它不起作用

我用多个应用程序创建了租户。单个应用程序可以使用预期的索赔信息登录。但我期待着登录一个应用程序应该自动登录其他应用程序。此时,每个请求登录系统的应用程序都会出现。根据Microsoft文档,会话行为应该在应用程序之间共享

这是我的登录档案

https://login.microsoftonline.com/te/tenantname.onmicrosoft.com/b2c_1_signin/oauth2/v2.0/authorize?
    client_id=3ef6aa38-2d21-4ee9-9bf8-8bceb5cfe64b
    &redirect_uri=https://localhost:44351/signin-oidc
    &response_type=id_token
    &scope=openid profile
    &response_mode=form_post
    &nonce=636928196846064501.OGRlYjM0NjgtZDJlYi00M2UxLTk5YzQtM2MxM
    &state=CfDJ8EfHCTrLjBNKqHfPd-IQcycV6rNTyFU3zZeqHtwCOoO5tRFUx_5xLhFlvuFi_y9HbC_rhNEGL4qss5sG986p4zZCU
    &x-client-SKU=ID_NETSTANDARD1_4
    &x-client-ver=5.2.0.0
启动类&OpenIdConnect中间件

    services.AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddAzureAdB2C(options => Configuration.Bind("Authentication:AzureAdB2C", options))
            .AddCookie(options => {
                options.LoginPath = "/Session/Unauthorized/";
                options.AccessDeniedPath = "/Session/Forbidden/";
            });

OpeidConnect Middleware
public static class AzureAdB2CAuthenticationBuilderExtensions
    {
        public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder)
            => builder.AddAzureAdB2C(_ =>
            {
            });
        public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder, Action<AzureAdB2COptions> configureOptions)
        {
            builder.Services.Configure(configureOptions);
            builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, OpenIdConnectOptionsSetup>();
            builder.AddOpenIdConnect();
            return builder;
        }
        public class OpenIdConnectOptionsSetup : IConfigureNamedOptions<OpenIdConnectOptions>
        {
            private readonly IMemoryCache _cache;

            public OpenIdConnectOptionsSetup(IOptions<AzureAdB2COptions> b2cOptions, IMemoryCache cache)
            {
                _cache = cache;
                AzureAdB2COptions = b2cOptions.Value;

        }

            public AzureAdB2COptions AzureAdB2COptions { get; set; }

            public void Configure(string name, OpenIdConnectOptions options)
            {
                options.ClientId = AzureAdB2COptions.ClientId;
                options.Authority = AzureAdB2COptions.Authority;
                options.UseTokenLifetime = true;
                options.TokenValidationParameters = new TokenValidationParameters() { NameClaimType = "name" };

                options.Events = new OpenIdConnectEvents()
                {
                    OnRedirectToIdentityProvider = OnRedirectToIdentityProvider,
                    OnRemoteFailure = OnRemoteFailure,
                    OnAuthorizationCodeReceived = OnAuthorizationCodeReceived
                };
            }

            public void Configure(OpenIdConnectOptions options)
            {
                Configure(Options.DefaultName, options);
            }

            public Task OnRedirectToIdentityProvider(RedirectContext context)
            {
                var defaultPolicy = AzureAdB2COptions.DefaultPolicy;
                if (context.Properties.Items.TryGetValue(AzureAdB2COptions.PolicyAuthenticationProperty, out var policy) &&
                    !policy.Equals(defaultPolicy))
                {
                    context.ProtocolMessage.Scope = OpenIdConnectScope.OpenIdProfile;
                    context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken;
                    context.ProtocolMessage.IssuerAddress = context.ProtocolMessage.IssuerAddress.ToLower().Replace(defaultPolicy.ToLower(), policy.ToLower());
                    context.Properties.Items.Remove(AzureAdB2COptions.PolicyAuthenticationProperty);
                }
                else if (!string.IsNullOrEmpty(AzureAdB2COptions.ApiUrl))
                {
                    context.ProtocolMessage.Scope += $" offline_access {AzureAdB2COptions.ApiScopes}";
                    context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.CodeIdToken;
                }
                return Task.FromResult(0);
            }

            public Task OnRemoteFailure(RemoteFailureContext context)
            {
                context.HandleResponse();
                // Handle the error code that Azure AD B2C throws when trying to reset a password from the login page 
                // because password reset is not supported by a "sign-up or sign-in policy"
                if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("AADB2C90118"))
                {
                    // If the user clicked the reset password link, redirect to the reset password route
                    context.Response.Redirect("/Session/ResetPassword");
                }
                else if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("access_denied"))
                {
                    context.Response.Redirect("/");
                }
                else
                {
                    context.Response.Redirect("/Home/Error?message=" + context.Failure.Message);
                }
                return Task.FromResult(0);
            }

            public async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
            {
                // Use MSAL to swap the code for an access token
                // Extract the code from the response notification
                var code = context.ProtocolMessage.Code;

                string signedInUserID = context.Principal.FindFirst(ClaimTypes.NameIdentifier).Value;
                TokenCache userTokenCache = new MSALSessionCache(signedInUserID, context.HttpContext).GetMsalCacheInstance();
                ConfidentialClientApplication cca = new ConfidentialClientApplication(AzureAdB2COptions.ClientId, AzureAdB2COptions.Authority, AzureAdB2COptions.RedirectUri, new ClientCredential(AzureAdB2COptions.ClientSecret), userTokenCache, null);
                try
                {
                    AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, AzureAdB2COptions.ApiScopes.Split(' '));


                    context.HandleCodeRedemption(result.AccessToken, result.IdToken);
                }
                catch (Exception ex)
                {
                    //TODO: Handle
                    throw;
                }
            }
        }
    }
services.AddAuthentication(sharedOptions=>
{
sharedOptions.DefaultScheme=CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme=OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAdB2C(选项=>Configuration.Bind(“身份验证:AzureAdB2C”,选项))
.AddCookie(选项=>{
options.LoginPath=“/Session/Unauthorized/”;
options.AccessDeniedPath=“/Session/probidden/”;
});
OpeidConnect中间件
公共静态类AzureAdB2CAuthenticationBuilderExtensions
{
公共静态身份验证生成器AddAzureAdB2C(此身份验证生成器)
=>builder.AddAzureAdB2C(=>
{
});
公共静态身份验证生成器AddAzureAdB2C(此身份验证生成器,操作配置选项)
{
builder.Services.Configure(配置选项);
builder.Services.AddSingleton();
AddOpenIdConnect();
返回生成器;
}
公共类OpenIDConnectOptions设置:IConfigureNamedOptions
{
专用只读IMemoryCache\u缓存;
公共OpenIDConnectOptions设置(IOptions B2COPIONS、IMemoryCache缓存)
{
_缓存=缓存;
azureadb2copions=b2copions.Value;
}
公共azureadb2copions azureadb2copions{get;set;}
public void配置(字符串名称、OpenIdConnectOptions选项)
{
options.ClientId=azureadb2copions.ClientId;
options.Authority=azureadb2copions.Authority;
options.UseTokenLifetime=true;
options.TokenValidationParameters=新的TokenValidationParameters(){NameClaimType=“name”};
options.Events=new OpenIdConnectEvents()
{
OnRedirectToIdentityProvider=OnRedirectToIdentityProvider,
OnRemoteFailure=OnRemoteFailure,
OnAuthorizationCodeReceived=OnAuthorizationCodeReceived
};
}
public void配置(OpenIdConnectOptions选项)
{
配置(Options.DefaultName,Options);
}
公共任务OnRedirectToIdentityProvider(重定向上下文)
{
var defaultPolicy=azureadb2copions.defaultPolicy;
if(context.Properties.Items.TryGetValue(AzureAdB2COptions.PolicyAuthenticationProperty,out var策略)&&
!policy.Equals(defaultPolicy))
{
context.ProtocolMessage.Scope=OpenIdConnectScope.OpenIdProfile;
context.ProtocolMessage.ResponseType=OpenIdConnectResponseType.IdToken;
context.ProtocolMessage.IssuerAddress=context.ProtocolMessage.IssuerAddress.ToLower().Replace(defaultPolicy.ToLower(),policy.ToLower());
context.Properties.Items.Remove(azureadb2copions.PolicyAuthenticationProperty);
}
如果(!string.IsNullOrEmpty(azureadb2copions.ApiUrl))为else
{
context.ProtocolMessage.Scope+=$“脱机访问{azureadb2copions.ApiScopes}”;
context.ProtocolMessage.ResponseType=OpenIdConnectResponseType.CodeIdToken;
}
返回Task.FromResult(0);
}
RemoteFailure上的公共任务(RemoteFailureContext上下文)
{
context.HandleResponse();
//处理Azure AD B2C在尝试从登录页面重置密码时抛出的错误代码
//因为“注册或登录策略”不支持密码重置
if(context.Failure是OpenIdConnectProtocolException&&context.Failure.Message.Contains(“AADB2C90118”))
{
//如果用户单击了重置密码链接,则重定向到重置密码路由
重定向(“/Session/ResetPassword”);
}
else if(context.Failure是OpenIdConnectProtocolException&&context.Failure.Message.Contains(“拒绝访问”))
{
context.Response.Redirect(“/”);
}
其他的
{
context.Response.Redirect(“/Home/Error-message=“+context.Failure.message”);
}
返回Task.FromResult(0);
}
AuthorizationCodeReceived上的公共异步任务(AuthorizationCodeReceivedContext上下文)
{
//使用MSAL将代码交换为访问令牌
//从响应通知中提取代码
var code=context.ProtocolMessage.code;
string signedInUserID=context.Principal.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache=新的MSALSessionCache(SignedUserId,context.HttpContext).GetMsalCacheInstance();
机密客户端应用程序cca=新的机密客户端应用程序(azureadb2copions.ClientId,Azure)