Go Verifier SDK 集成教程
本文档说明如何在 Go 业务后端中使用官方 codebird-go-sdk 验证来自前端的 Access Token,并基于结构化 AuthContext 做鉴权。
目标读者:
- Go API 服务工程师
- 第三方后端开发工程师
- 需要读取用户 / 组织 / 租户上下文的资源服务器
这个 SDK 负责什么
Go Verifier SDK 负责:
- OIDC Discovery
- JWKS 拉取与缓存
- JWT 签名验证
- 标准 OIDC claims 解析
- Code Bird Cloud 组织 claims 解析
- 结构化
AuthContext输出
它不负责:
- 发起用户登录
- 主动申请用户 Token
- 替第三方做框架级路由跳转
适用场景
- React SPA 登录后调用 Go API
- 其他前端框架调用 Go 资源服务
- 需要读取
organization_id、organization_roles、organization_is_admin - 需要从 token 中读取轻量用户身份
安装
bash
go get github.com/lshaofan/codebird-go-sdk@latest版本策略见:
第 1 步:创建 Verifier
go
verifier, err := codebird.NewVerifier(codebird.Config{
Issuer: "https://auth.codebird.cloud",
Audience: "https://api.example.com",
})
if err != nil {
log.Fatalf("failed to create verifier: %v", err)
}参数说明
| 参数 | 含义 | 最佳实践 |
|---|---|---|
Issuer | 认证中心地址 | 与前端 CodeBirdProvider.endpoint 完全一致 |
Audience | 当前业务 API 的资源标识 | 与前端 defaultResource 完全一致 |
JWKSTTL | JWKS 缓存时间 | 生产环境可按默认或结合网关策略调整 |
ClockSkew | 时钟偏移容忍窗口 | 只有跨系统时钟偏差明显时才需要调大 |
最关键的一条:
text
Go Audience == React defaultResource第 2 步:解析 Bearer Token
go
token, err := codebird.ParseBearerToken(r.Header.Get("Authorization"))
if err != nil {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}推荐先统一把这一步收在中间件或公共 helper 中,不要在每个 Handler 里散落一遍。
第 3 步:验证 Access Token
go
authCtx, err := verifier.VerifyAccessToken(r.Context(), token)
if err != nil {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}验证成功后,你会得到结构化的 AuthContext。
第 4 步:读取 AuthContext
常用字段:
go
userID := authCtx.Subject
username := authCtx.Username
email := authCtx.Email
organizationID := authCtx.OrganizationID
organizationIDs := authCtx.OrganizationIDs
organizationRoles := authCtx.OrganizationRoles
organizationIsAdmin := authCtx.OrganizationIsAdmin当前推荐理解方式
organization_id:当前登录上下文组织organization_roles:角色字符串数组的结构化结果organization_is_admin:当前组织管理员布尔值
管理员身份判断不要再自己猜:
- 不要根据
organization_roles中是否包含admin推断管理员身份 - 请直接使用
organization_is_admin
第 5 步:做业务鉴权
当前推荐写法是基于 AuthContext 的 helper 做判断。
判断 audience
go
if !authCtx.HasAudience("https://api.example.com") {
http.Error(w, "forbidden", http.StatusForbidden)
return
}判断组织归属
go
if !authCtx.HasOrganization("org_123") {
http.Error(w, "forbidden", http.StatusForbidden)
return
}判断组织角色
go
if !authCtx.HasOrganizationRole("org_123", "admin") {
http.Error(w, "forbidden", http.StatusForbidden)
return
}获取某个组织的角色列表
go
roles := authCtx.RolesForOrganization("org_123")推荐的中间件模式
官方不绑定 Gin / Echo / Fiber,但推荐项目方自己封一层很薄的中间件。
Gin 示例
go
func AuthMiddleware(verifier *codebird.Verifier) gin.HandlerFunc {
return func(c *gin.Context) {
token, err := codebird.ParseBearerToken(c.GetHeader("Authorization"))
if err != nil {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"message": "unauthorized"})
return
}
authCtx, err := verifier.VerifyAccessToken(c.Request.Context(), token)
if err != nil {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"message": "unauthorized"})
return
}
c.Set("auth_ctx", authCtx)
c.Next()
}
}然后在业务 Handler 中只做业务判断,不重复做签名验证。
轻量 claims 与实时上下文
这一步很关键。
Token claims 适合做什么
- 判断当前请求携带的 token 是否有效
- 读取轻量用户身份
- 读取当前组织上下文
- 读取组织角色
Token claims 不适合做什么
- 判断用户是否仍属于某组织
- 判断管理员标记是否刚被后台改动
- 判断组织关系是否已经实时变更
这类场景请改用实时接口:
当前 Go SDK 也已经支持获取实时会话上下文,推荐搭配使用。
什么时候应该调用实时会话上下文
推荐在下面这些场景使用:
- 页面需要渲染用户最新昵称、手机号、头像
- 用户组织关系可能在使用中被管理员修改
- 你需要“当前数据库状态”,而不是“登录时 claims 快照”
- 你需要顶层
tenant.slug来生成终端用户 URL
实时上下文里当前标准返回:
tenant.idtenant.slugtenant.nameorganization.is_admin
前后端协同最佳实践
如果前端用 React SDK,推荐这样配合:
前端负责
- 登录
- callback
- token 自动续期
getAccessToken()getSessionContext()
Go 后端负责
ParseBearerToken()VerifyAccessToken()- 基于
AuthContext做接口鉴权 - 需要最新数据库状态时,再调用实时会话上下文
这样职责最清晰,也最容易排查问题。
当前常见错误
错误 1:前端 defaultResource 与后端 Audience 不一致
表现通常是:
- 后端 401
- 前端重复续期
- token
aud看起来不对
错误 2:把 claims 当作实时权限数据
这会导致:
- 用户已被移出组织,但业务仍放行
- 用户管理员状态已变化,但服务仍按旧状态处理
错误 3:后端自己手拆 organization_roles
不推荐。
SDK 已经提供结构化 AuthContext 和 helper,不需要再自己解析原始 claims。
联调清单
前后端联调时至少确认:
Issuer与前端endpoint一致Audience与前端defaultResource一致- Bearer Token 确实来自 Code Bird Cloud
- API 服务端时钟没有明显漂移
- 对组织级判权使用
AuthContexthelper,而不是字符串手拆
