logto服务端必须启用oidc discovery endpoint,即确保logto_enable_oidc_discovery为true;go客户端须用oidc.newprovider自动发现配置,按租户独立初始化provider并缓存;校验token时需严格匹配resource indicator或跳过clientid检查并验证azp与tid;租户识别应依赖token中的tid声明而非请求头。

Logto 服务端配置必须启用 OIDC Discovery Endpoint
Logto 默认开启 OIDC 发现端点(/.well-known/openid-configuration),但如果你用的是自托管 Logto(v1.0+),需确认 LOGTO_ENABLE_OIDC_DISCOVERY 环境变量为 true(Docker Compose 部署时默认已设)。否则 Go 客户端调用 oidc.NewProvider 会报错:failed to get provider config: 404 Not Found。
验证方式:直接 curl 你的 Logto 实例地址,例如:curl https://logto.example.com/.well-known/openid-configuration。返回 JSON 且含 issuer、jwks_uri、authorization_endpoint 字段才算就绪。
Go 中使用 github.com/coreos/go-oidc/v3 正确初始化 Provider
别直接 new 一个 oidc.Provider,必须用 oidc.NewProvider 触发自动发现——它会读取 /.well-known/openid-configuration 并缓存结果。手动拼接 URL 或硬编码 JWKS URI 在多租户场景下极易出错(比如租户切换后仍用旧 issuer)。
-
issuerURL必须与 Logto 控制台中「租户」的Issuer值完全一致(注意末尾斜杠:Logto 的issuer值带/,如https://logto.example.com/tenant-a/) - 每个租户需独立初始化
*oidc.Provider实例,不能复用——因为Provider内部缓存了 issuer 和 JWKS,混用会导致 token 校验失败 - 建议用 map[string]*oidc.Provider 缓存各租户 provider,key 用租户 ID(不是域名),避免每次请求都重新 discovery
示例片段:
provider, err := oidc.NewProvider(ctx, "https://logto.example.com/tenant-a/")
if err != nil {
return nil, fmt.Errorf("failed to init OIDC provider for tenant-a: %w", err)
}
解析 token 时必须校验 azp 和 aud 字段
Logto 发放的 Access Token 是 JWT,但默认不设 aud;若你在 Logto 应用配置里没显式设置 Resource Indicator(即 API Resource ID),则 aud 字段为空,oidc.IDTokenVerifier 会因校验失败而拒绝 token。
解决方法只有两个:
- 在 Logto 控制台为每个租户的应用配置一个唯一
Resource Indicator(例如api.tenant-a.example.com),并确保 Go 代码中 verifier 的ExpectedAudience与之严格匹配 - 或改用
verifier := provider.Verifier(&oidc.Config{SkipClientIDCheck: true})并自行校验azp(Logto 填的是应用 client ID)和租户上下文是否一致
漏掉这步,你会看到错误:token is not valid for this client 或静默失败(token 解析成功但未校验租户归属)。
租户路由识别不能只靠 Host 或 Path,要结合 Logto Token 中的 tid 声明
Logto 在 ID Token 和 Access Token 中都注入了 tid(tenant ID)字段(前提是租户启用了 multi-tenancy 模式)。不要依赖 HTTP 请求头或子域名来判断租户——攻击者可伪造 Host 头绕过鉴权。
正确做法:
- 从 token payload 中提取
tid字段(用rawToken.Payload()解析后取值) - 用该
tid查找对应租户的*oidc.Provider实例(见第二部分) - 再用该 provider 的 verifier 校验 token 签名和时效
如果 Logto 版本低于 v1.12,tid 可能不在 Access Token 中,此时必须用 ID Token(即要求前端传 id_token_hint 或走 Authorization Code Flow 获取 ID Token)。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











