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

求IdentityServer4与Asp.net Core 2.0的Backchannel登出示例

很高兴听到你已经顺利搞定了IdentityServer4和ASP.NET Core 2.0的Front Channel登出!针对你问的Backchannel登出实现,我来给你一个可运行的示例,还有关于BackChannelLogoutUri的明确说明:

Backchannel登出完整实现步骤

1. IdentityServer4客户端配置

首先在IDS4的客户端配置中,指定BackChannelLogoutUri和相关属性:

new Client
{
    ClientId = "your-client-app-id",
    ClientName = "Your Client Application",
    // 基础配置(授权类型、重定向URI等)
    AllowedGrantTypes = GrantTypes.Code,
    RedirectUris = new List<string> { "https://your-client-app.com/signin-oidc" },
    PostLogoutRedirectUris = new List<string> { "https://your-client-app.com/signout-callback-oidc" },
    ClientSecret = new Secret("your-client-secret".Sha256()),
    
    // Backchannel登出核心配置
    BackChannelLogoutUri = "https://your-client-app.com/api/signout-backchannel",
    BackChannelLogoutSessionRequired = true, // 可选,默认true,仅当用户有活跃会话时触发登出
    AllowOfflineAccess = true // 如果需要持久化会话,开启这个
}

这里的BackChannelLogoutUri就是你的ASP.NET Core客户端接收IDS4登出通知的接口地址,接下来我们要在客户端实现这个接口。

2. ASP.NET Core 2.0客户端端处理

2.1 配置认证服务

在Startup.cs的ConfigureServices中,确保OpenID Connect认证支持Backchannel登出的事件处理:

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;

public void ConfigureServices(IServiceCollection services)
{
    // 添加身份认证
    services.AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect(options =>
    {
        options.Authority = "https://your-ids4-server-url";
        options.ClientId = "your-client-app-id";
        options.ClientSecret = "your-client-secret";
        options.ResponseType = "code";
        options.SaveTokens = true;
        
        // 处理远程登出事件,清除本地用户会话
        options.Events = new OpenIdConnectEvents
        {
            OnRemoteSignOut = async context =>
            {
                await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                context.HandleResponse();
            }
        };
    });

    // 其他服务配置...
    services.AddControllersWithViews();
}

2.2 实现Backchannel登出接收接口

创建一个API控制器来接收IDS4发送的logout_token,并完成会话清理:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;

[Route("api/[controller]")]
[ApiController]
public class SignoutBackchannelController : ControllerBase
{
    private readonly SignInManager<IdentityUser> _signInManager;
    private readonly IConfiguration _configuration;

    public SignoutBackchannelController(SignInManager<IdentityUser> signInManager, IConfiguration configuration)
    {
        _signInManager = signInManager;
        _configuration = configuration;
    }

    [HttpPost]
    public async Task<IActionResult> Post([FromForm] string logout_token)
    {
        if (string.IsNullOrWhiteSpace(logout_token))
        {
            return BadRequest("Logout token is missing");
        }

        // 验证logout_token的有效性(关键步骤,防止恶意请求)
        var validationParams = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = _configuration["Auth:Authority"], // 从配置文件读取IDS4地址
            ValidateAudience = true,
            ValidAudience = _configuration["Auth:ClientId"], // 读取客户端ID
            ValidateLifetime = true,
            // 从IDS4的元数据端点获取公钥,或者直接配置
            IssuerSigningKeys = await GetIdentityServerSigningKeysAsync()
        };

        try
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            tokenHandler.ValidateToken(logout_token, validationParams, out var validatedToken);

            // 提取会话ID(sid声明)
            var jwtToken = validatedToken as JwtSecurityToken;
            var sessionId = jwtToken?.Claims.FirstOrDefault(c => c.Type == "sid")?.Value;

            if (!string.IsNullOrWhiteSpace(sessionId))
            {
                // 清除当前会话对应的用户登录状态
                // 如果是多实例部署,需要确保会话状态共享(比如使用Redis分布式缓存)
                await _signInManager.SignOutAsync();
            }

            return Ok();
        }
        catch (SecurityTokenException ex)
        {
            return BadRequest($"Invalid logout token: {ex.Message}");
        }
    }

    // 辅助方法:从IDS4元数据端点获取签名公钥
    private async Task<IEnumerable<SecurityKey>> GetIdentityServerSigningKeysAsync()
    {
        var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
            $"{_configuration["Auth:Authority"]}/.well-known/openid-configuration",
            new OpenIdConnectConfigurationRetriever());

        var config = await configurationManager.GetConfigurationAsync(CancellationToken.None);
        return config.SigningKeys;
    }
}

3. 关键注意事项

  • Token验证不可省略:必须验证logout_token的签发者、受众、有效期和签名,避免恶意请求导致的非法登出。
  • 会话状态共享:如果你的客户端是多实例部署,需要使用分布式会话存储(比如Redis),这样Backchannel登出通知能在所有实例上生效。
  • IDS4的Backchannel行为:当用户在IDS4发起全局登出时,IDS4会遍历所有配置了BackChannelLogoutUri的客户端,发送POST请求携带logout_token,触发客户端的会话清理。

关于BackChannelLogoutUri的指向

简单来说,这个URI就是你在ASP.NET Core客户端中实现的那个POST接口地址,也就是上面示例中的https://your-client-app.com/api/signout-backchannel,IDS4会通过这个地址把登出通知发送给你的客户端。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:38:48