服务器端C#实现Google登录获取用户信息遇invalid_grant错误
解决Google授权码交换令牌时的「invalid_grant: Malformed auth code」异常
核心问题排查与修复步骤
解码授权码
前端返回的授权码大概率被URL编码(比如包含%2F这类转义字符),直接传入ExchangeCodeForTokenAsync会触发格式错误。服务器端必须先解码:string decodedCode = System.Web.HttpUtility.UrlDecode(code);严格匹配redirect_uri
服务器端传入的redirect_uri必须和前端发起Google授权请求时的URI完全一致:- 若前端用的是
postmessage(SPA场景),服务器端必须传"postmessage",不能随意替换为后端回调URI; - 注意大小写、结尾斜杠等细节,Google对URI匹配要求严格。
- 若前端用的是
替换废弃的Google+ API
你代码中使用的PlusService及相关Scope已被Google废弃,必须替换为当前有效的服务和权限:- Scope替换为
https://www.googleapis.com/auth/userinfo.email、https://www.googleapis.com/auth/userinfo.profile; - 使用
PeopleService替代PlusService获取用户信息。
- Scope替换为
避免异步方法阻塞调用
不要用.Result阻塞ExchangeCodeForTokenAsync,改用await异步调用(需将方法标记为async),防止死锁。
修正后的完整代码示例
// 初始化授权流,使用当前有效的Scope IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow( new GoogleAuthorizationCodeFlow.Initializer { ClientSecrets = Secrets, Scopes = new[] { "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" } }); // 解码授权码(关键步骤) string decodedCode = System.Web.HttpUtility.UrlDecode(code); // 异步交换令牌,避免阻塞 TokenResponse _token = await flow.ExchangeCodeForTokenAsync( "", decodedCode, "postmessage", // 和前端授权时的redirect_uri完全一致 CancellationToken.None); context.Session["authState"] = _token; // 验证令牌 Oauth2Service oauthService = new Oauth2Service( new Google.Apis.Services.BaseClientService.Initializer()); Tokeninfo tokenInfo = oauthService.Tokeninfo().SetAccessToken(_token.AccessToken).Execute(); if (tokenInfo.VerifiedEmail.HasValue && tokenInfo.VerifiedEmail.Value) { UserCredential credential = new UserCredential(flow, "me", _token); // 使用PeopleService替代废弃的PlusService PeopleService peopleService = new PeopleService( new Google.Apis.Services.BaseClientService.Initializer() { ApplicationName = "Your app name", HttpClientInitializer = credential }); // 获取用户基本信息(指定需要的字段) Person userProfile = peopleService.People.Get("people/me") .SetPersonFields("names,emailAddresses") .Execute(); }
额外注意事项
- 授权码只能使用一次,重复调用会触发
invalid_grant错误; - 若使用后端回调URI而非
postmessage,需确保该URI已添加到Google Cloud项目的「OAuth 2.0客户端ID」的「已授权重定向URI」列表中。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

