
本文介绍如何使用 go 语言构建基于 openid connect 协议的单点登录框架,对接 azure active Directory(azure ad),实现安全、标准、可扩展的用户身份认证。
在 go 生态中实现 Azure AD 单点登录(SSO),推荐采用 OpenID Connect(OIDC) ——这是 OAuth 2.0 的身份层扩展,也是 Azure AD 官方首选且最简明的现代认证方案。相比已逐步弃用的 WS-Fed 或 SAML-P,OIDC 基于 jsON 和 httpS,天然适配 Go 的轻量级 Web 服务架构,且拥有成熟的标准库支持。
✅ 核心步骤概览
- 在 Azure Portal 注册应用:获取 Client ID、Client Secret 和 Tenant ID;配置重定向 URI(如 http://localhost:8080/callback);启用 ID Token 发放(需在「Token configuration」中添加 ID token)。
- 选择 OIDC 客户端库:推荐使用 coreos/go-oidc(社区维护良好,支持 PKCE 可选)或更轻量的 oauth2 + 手动验证 ID Token。
- 实现认证流程:
? 示例代码(基于 go-oidc)
package main import ( "context" "fmt" "log" "net/http" "time" "github.com/coreos/go-oidc" "golang.org/x/oauth2" ) var ( provider *oidc.Provider oauth2Config *oauth2.Config ) func init() { ctx := context.Background() var err error // 初始化 OIDC Provider(注意替换为你的 tenant ID) provider, err = oidc.NewProvider(ctx, "https://login.microsoftonline.com/YOUR_TENANT_ID/v2.0") if err != nil { log.Fatal(err) } // 配置 OAuth2 客户端(从 Azure app Registration 获取) oauth2Config = &oauth2.Config{ ClientID: "YOUR_CLIENT_ID", ClientSecret: "YOUR_CLIENT_SECRET", RedirectURL: "http://localhost:8080/callback", Endpoint: provider.Endpoint(), Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, } } func loginHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, oauth2Config.AuthCodeURL("state", oauth2.accessTypeOnline), http.StatusFound) } func callbackHandler(w http.ResponseWriter, r *http.Request) { ctx := r.Context() code := r.URL.Query().Get("code") if code == "" { http.Error(w, "missing code", http.StatusbadRequest) return } // 交换 code 获取 token oauth2Token, err := oauth2Config.Exchange(ctx, code) if err != nil { http.Error(w, "failed to exchange code", http.StatusInternalServerError) return } // 解析并验证 ID Token rawIDToken, ok := oauth2Token.Extra("id_token").(string) if !ok { http.Error(w, "no id_token in response", http.StatusInternalServerError) return } idToken, err := provider.Verifier(&oidc.Config{ClientID: oauth2Config.ClientID}).Verify(ctx, rawIDToken) if err != nil { http.Error(w, "failed to verify id_token", http.StatusInternalServerError) return } // 提取用户信息 var claims struct { Email string `json:"email"` Name string `json:"name"` } if err := idToken.Claims(&claims); err != nil { http.Error(w, "failed to parse claims", http.StatusInternalServerError) return } fmt.Fprintf(w, "✅ Logged in as %s (%s)", claims.Name, claims.Email) } func main() { http.HandleFunc("/login", loginHandler) http.HandleFunc("/callback", callbackHandler) log.Println("Server starting on :8080") log.Fatal(http.ListenAndServe(":8080", nil)) }
⚠️ 关键注意事项
- 安全性:务必启用 PKCE(推荐 S256 code challenge)以防范授权码劫持,尤其在公共客户端场景;生产环境必须使用 HTTPS 并校验 issuer(应为 https://login.microsoftonline.com/{tenant-id}/v2.0)。
- 租户配置:开发阶段可用 common(多租户)端点,但生产建议锁定 tenant-id 以提升安全与性能。
- Token 刷新:若需长期访问 Graph API,请保存 refresh_token 并妥善加密存储;ID Token 不可刷新,需重新登录获取新身份上下文。
- 错误处理:Azure AD 返回的错误(如 login_required, interaction_required)需前端友好提示,并引导用户重新鉴权。
通过以上方式,你即可构建一个符合企业级标准、易于维护、与 Azure AD 深度集成的 Go SSO 框架——无需自研协议解析,专注业务逻辑,安全交由标准与云平台保障。