Go SDK
github.com/Bin-hy/yufu-sdk-go 是 yufu Runtime SDK 的 Go 参考实现:一个轻量、
无额外依赖的 HTTP / OIDC 客户端。
包含:Discovery 与 issuer 校验、授权码 + PKCE(S256)、state / nonce 生成、code 兑换与
refresh token 轮换(single-flight)、UserInfo、JWKS 缓存与 RS256 校验、access token 校验
(typ=at+jwt、iss、aud、exp、nbf)、ID Token 校验、内省、撤销、RP 发起退出、
后通道 logout token 校验,以及带 request_id 与 Retry-After 的类型化错误。
不包含:M2M / client_credentials、权限同步、/enforce、旧 RBAC、管理控制台 API。
go get github.com/Bin-hy/yufu-sdk-goSDK 仍在服务端仓库内时,使用 replace:
require github.com/Bin-hy/yufu-sdk-go v0.0.0
replace github.com/Bin-hy/yufu-sdk-go => /path/to/cobot-for/sdk/goclient, err := yufu.New(yufu.Config{ Issuer: "https://id.example.com", ClientID: "web", ClientSecret: os.Getenv("OIDC_CLIENT_SECRET"), RedirectURI: "https://app.example.com/callback", Scopes: []string{"openid", "profile", "email"},})if err != nil { return err}defer client.Close()
auth, err := client.AuthorizeURL(yufu.AuthorizeOptions{})if err != nil { return err}// 把 auth.State、auth.Nonce、auth.CodeVerifier 存入用户会话,// 然后让浏览器跳转到 auth.URL。
tokens, err := client.ExchangeCode(ctx, code, auth.CodeVerifier)if err != nil { return err}idClaims, err := client.VerifyIDToken(ctx, tokens.IDToken, auth.Nonce)if err != nil { return err}accessClaims, err := client.VerifyAccessToken(ctx, tokens.AccessToken, "urn:app:production")if err != nil { return err}profile, err := client.UserInfo(ctx, tokens.AccessToken)Access Token 的 audience 是应用注册的 access audience,不是 OIDC client id。
资源服务器必须把期望的 audience 传给 VerifyAccessToken。
reader, err := yufu.New(yufu.Config{ Issuer: "https://id.example.com", ClientID: os.Getenv("READER_CLIENT_ID"), ClientSecret: os.Getenv("READER_CLIENT_SECRET"),})if err != nil { return err}
claims, err := reader.VerifyAccessToken(ctx, bearerToken, "urn:app:production")if err != nil { return err}introspection, err := reader.Introspect(ctx, bearerToken, yufu.TokenTypeAccessToken)if err != nil { return err}if !introspection.Active || introspection.Subject != claims.Subject { return errors.New("token is not active or subject changed")}SDK 在本地校验 JWT;内省是额外的在线检查,新鲜度策略由应用决定。
claims, err := client.VerifyLogoutToken(ctx, logoutToken)if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return}// 按 claims.SID 与 claims.Subject 删除本地会话。// 持久化 claims.JTI 以保证投递幂等。VerifyLogoutToken 强制校验 typ=logout+jwt、aud=client_id、后通道事件、jti、
sid 或 sub、不含 nonce,且有效期不超过 120 秒。
- 仅 RS256;小于 2048 位的 RSA 密钥被拒绝。
kid必填;遇到未知kid时刷新 JWKS。- access token 必须
typ=at+jwt;ID token 必须typ=JWT或无typ; logout token 必须typ=logout+jwt。 iss必须与配置的 issuer 完全一致。- access token 的
aud必填,且必须与调用方期望值一致。