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

如何实现Kratos与Microsoft Azure的单点登出功能?

解决Azure AD前端登出同步Kratos会话的问题

核心思路

Azure AD前端登出请求携带的sid是Azure侧的会话ID,需要先在Kratos中建立该sid与Kratos用户会话的关联,再通过Kratos管理员API安全删除对应会话。

步骤1:配置Kratos捕获Azure AD的sid Claim

在Kratos的OIDC身份提供商配置中,确保获取并存储Azure AD返回的sid Claim。修改Kratos的OIDC provider配置(通常在identity.schema.json或对应OIDC配置文件中):

{
  "id": "microsoft",
  "provider": "oidc",
  "config": {
    "issuer_url": "https://login.microsoftonline.com/[tenant-id]/v2.0",
    "client_id": "[your-client-id]",
    "client_secret": "[your-client-secret]",
    "scopes": ["openid", "profile", "email"],
    "claims": {
      "sid": {
        "mapping": "traits.microsoft.sid",
        "required": true
      }
    }
  }
}

配置完成后,Kratos会将Azure的sid存储到用户的traits.microsoft.sid字段中。

步骤2:用Go后端处理Azure的前端登出请求

在你的Go服务中创建接口(比如/auth/azure/logout)接收Azure的GET请求,提取sid参数后执行会话删除操作:

import (
  "context"
  "fmt"
  "net/http"
  "github.com/ory/kratos-client-go"
)

func handleAzureFrontchannelLogout(w http.ResponseWriter, r *http.Request) {
  // 提取Azure传入的sid参数
  sid := r.URL.Query().Get("sid")
  if sid == "" {
    w.WriteHeader(http.StatusBadRequest)
    return
  }

  // 初始化Kratos Admin客户端
  config := kratos.NewConfiguration()
  config.Servers = []kratos.ServerConfiguration{{URL: "http://kratos-host:4433"}}
  client := kratos.NewAPIClient(config)
  
  // 携带Kratos Admin Token,绕过CSRF验证
  adminCtx := context.WithValue(r.Context(), kratos.ContextAPIKey, kratos.APIKey{
    Key: "[your-kratos-admin-token]", // 从Kratos配置中获取ADMIN_TOKEN
  })

  // 查询匹配sid的Kratos用户
  listParams := client.IdentityApi.ListIdentities(adminCtx)
  listParams = listParams.TraitsQuery(fmt.Sprintf("traits.microsoft.sid=\"%s\"", sid))
  identities, _, err := client.IdentityApi.ListIdentitiesExecute(listParams)
  if err != nil || len(identities) == 0 {
    w.WriteHeader(http.StatusNotFound)
    return
  }

  // 删除该用户的所有Kratos会话
  for _, identity := range identities {
    sessions, _, err := client.SessionApi.ListSessionsForIdentity(adminCtx, identity.Id).Execute()
    if err != nil {
      continue
    }

    for _, session := range sessions {
      _, err := client.SessionApi.DeleteSession(adminCtx, session.Id).Execute()
      if err != nil {
        // 此处可添加错误日志记录
      }
    }
  }

  // 返回200给Azure,确认登出处理完成
  w.WriteHeader(http.StatusOK)
}

关键注意事项

  • 必须使用Kratos的Admin API并携带管理员Token,这样可以绕过CSRF验证(管理员接口无需CSRF Token)。
  • 如果用户存在多设备登录的情况,上述逻辑会删除该用户的所有Kratos会话,确保完全同步登出状态。
  • 确保处理登出请求的Go接口可以被Azure的iframe请求访问(无CORS限制)。

替代方案(无需捕获sid)

如果不想配置Kratos存储sid,可以通过Azure用户的固定sub(主题ID)关联用户:

  1. Kratos默认会将Azure用户的sub存储在identity.credentials.oauth2[].subject中。
  2. 查询用户时通过credentials.oauth2.subject筛选,再删除该用户的所有会话。这种方式会删除用户所有Kratos会话,而非仅关联当前Azure sid的会话。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:35:26