You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

服务器端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获取用户信息。
  • 避免异步方法阻塞调用
    不要用.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 10:34:55