You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在IdentityServer4中配置多客户端以禁用单点登录?

如何在IdentityServer4中为特定客户端禁用单点登录(SSO)

当然可以实现!你可以通过调整客户端配置(无论是IdentityServer端的客户端定义,还是客户端应用的OpenID Connect设置),让已登录第一个客户端后,访问第二个客户端时仍需重新登录。下面是具体的实现方案:

方案1:在客户端配置中强制触发重新登录(推荐)

最直接的方式是利用OpenID Connect的prompt=login标准参数,它会告诉IdentityServer忽略当前的用户会话,强制用户重新输入凭据登录。你可以通过两种方式配置:

方式A:在客户端应用的OpenID Connect中间件中设置

如果你使用ASP.NET Core的OpenID Connect中间件,直接在客户端配置里指定Prompt = "login",就能让这个客户端每次请求授权时都强制重新登录:

services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
    options.Authority = "https://your-identityserver-url";
    options.ClientId = "your-second-client-id";
    options.ClientSecret = "your-client-secret";
    options.ResponseType = "code";
    // 核心配置:强制每次都重新登录,禁用SSO
    options.Prompt = "login"; 
});

方式B:在IdentityServer端统一配置客户端规则

如果你希望在IdentityServer端统一管控这个行为,可以给需要禁用SSO的客户端添加自定义标记,再通过中间件自动注入prompt=login参数。

首先修改你的GetClients方法,为目标客户端添加自定义属性:

internal static IEnumerable<Client> GetClients(IEnumerable<RegisteredClient> clients) 
{ 
    return clients.Select(x => 
    { 
        var scopes = x.AllowedScopes.ToList(); 
        scopes.Add(IdentityServerConstants.StandardScopes.OpenId); 
        scopes.Add(IdentityServerConstants.StandardScopes.Profile);
        
        var client = new Client
        {
            ClientId = x.ClientId,
            ClientName = x.ClientName,
            ClientSecrets = { new Secret(x.ClientSecret.Sha256()) },
            AllowedGrantTypes = GrantTypes.Code,
            RedirectUris = x.RedirectUris,
            PostLogoutRedirectUris = x.PostLogoutRedirectUris,
            AllowedScopes = scopes,
            // 添加标记:该客户端需要禁用SSO
            Properties = new Dictionary<string, string>
            {
                ["ForceLogin"] = "true"
            }
        };
        
        // 可选:关闭离线访问,避免刷新令牌绕过重新登录
        if (x.ClientId == "your-second-client-id")
        {
            client.AllowOfflineAccess = false;
        }
        
        return client;
    }); 
}

然后添加一个自定义中间件,在授权请求前检查标记并注入参数:

public class ForceLoginMiddleware
{
    private readonly RequestDelegate _next;

    public ForceLoginMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, IClientStore clientStore)
    {
        if (context.Request.Path.StartsWithSegments("/connect/authorize"))
        {
            var clientId = context.Request.Query["client_id"].FirstOrDefault();
            if (!string.IsNullOrEmpty(clientId))
            {
                var client = await clientStore.FindEnabledClientByIdAsync(clientId);
                if (client != null && client.Properties.TryGetValue("ForceLogin", out var forceLogin) && forceLogin == "true")
                {
                    context.Request.QueryString = context.Request.QueryString.Add("prompt", "login");
                }
            }
        }

        await _next(context);
    }
}

// 在Startup.cs中注册中间件(要放在UseIdentityServer之前)
app.UseMiddleware<ForceLoginMiddleware>();
app.UseIdentityServer();

方案2:隔离客户端应用的认证Cookie

如果只是想让客户端应用的本地会话独立,你可以为每个客户端设置不同的认证Cookie名称,避免客户端之间共享会话:

services.AddAuthentication(options =>
{
    options.DefaultScheme = "SecondClientCookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie("SecondClientCookies", options =>
{
    options.Cookie.Name = "SecondClient.Auth"; // 与第一个客户端的Cookie名称区分开
})
.AddOpenIdConnect("oidc", options =>
{
    // 其他配置...
});

关键提示

  • prompt=login是OpenID Connect的标准参数,能彻底绕过IdentityServer的SSO会话,确保用户必须重新登录。
  • 如果客户端开启了AllowOfflineAccess(获取刷新令牌),记得为禁用SSO的客户端关闭该选项,防止长期有效的刷新令牌绕过重新登录要求。

内容的提问来源于stack exchange,提问作者paranamix2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:24:47