如何通过Google OAuth2获取用户邮箱且无需完整profile权限?
如何在最小权限下获取Google OAuth用户邮箱地址
核心解决方案
要在不申请完整profile或Gmail权限的前提下获取用户邮箱,只需使用OpenID Connect + 邮箱只读权限的组合,直接解析ID Token即可拿到邮箱,无需调用Gmail API。
具体步骤
调整OAuth权限范围
将原Scopes替换为最小必要的两个权限:openid:触发OpenID Flow,让Google返回ID Tokenhttps://www.googleapis.com/auth/userinfo.email:仅申请读取用户邮箱的权限
解析ID Token提取邮箱
调用Exchange后,返回的tok.IDToken是JWT格式字符串,解析后即可从email字段获取用户邮箱。
修改后的完整代码示例
import ( "context" "fmt" "net/http" "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" "golang.org/x/oauth2" "golang.org/x/oauth2/google" ) var ( ctx = context.Background() oauthConfig = &oauth2.Config{ ClientID: "...", // 替换为你的ClientID ClientSecret: "...", // 替换为你的ClientSecret RedirectURL: "...", // 替换为你的回调地址 Scopes: []string{ "openid", "https://www.googleapis.com/auth/userinfo.email", }, Endpoint: google.Endpoint, } ) // 生成授权跳转URL的Handler(示例) func authHandler(c *gin.Context) { url := oauthConfig.AuthCodeURL("state-token", oauth2.AccessTypeOffline) c.Redirect(http.StatusTemporaryRedirect, url) } // 回调地址的Handler func redirectHandler(c *gin.Context) { code := c.Query("code") tok, err := oauthConfig.Exchange(ctx, code) if err != nil { c.AbortWithError(http.StatusInternalServerError, err) return } // 解析ID Token token, err := jwt.Parse(tok.IDToken, func(token *jwt.Token) (interface{}, error) { // 验证签名算法,生产环境建议补充签名、issuer等完整校验 if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return nil, nil }) if err != nil { c.AbortWithError(http.StatusInternalServerError, err) return } // 提取邮箱字段 if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { email := claims["email"].(string) c.JSON(http.StatusOK, gin.H{"user_email": email}) } else { c.AbortWithStatus(http.StatusUnauthorized) } } // 省略main函数等其他代码
关键说明
- 原代码使用Gmail API属于过度授权,上述两个轻量权限即可满足需求
- 必须包含
openidscope才能触发Google返回ID Token,仅加userinfo.email无法获取ID Token - 生产环境解析ID Token时,需严格验证签名、issuer(
https://accounts.google.com)、过期时间等字段,保障安全性
内容的提问来源于stack exchange,提问作者dow
相关产品推荐
相关产品推荐

