【问题标题】:How do I implement Google API refresh token如何实现 Google API 刷新令牌
【发布时间】:2021-07-11 04:04:00
【问题描述】:

我一直在从事一个项目,我必须在 7 个不同的平台上实施 OAuth,但由于某种原因,Google 的 OAuth 流程让我感到困惑。

该项目是在 .NET MVC 中开发的,我正在使用 RestSharp 发出传出 Http 请求。

我正在检索 OAuth 请求以访问 GoogleAnalytics API,并且在第一次尝试时,我获得了一个有效的访问令牌,我可以使用该令牌成功地从用户的 GA 帐户中检索数据。但是,尽管我在身份验证请求 URL 中指定了 access_type=offline,但在令牌过期后尝试刷新令牌时,我看到以下错误:

400 - 错误请求 - { “错误”:“invalid_grant”, "error_description": "错误请求" }

我的请求 URL 如下所示:

https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&scope=https://www.googleapis.com/auth/analytics.readonly&include_granted_scopes=true&response_type=code&state=8f692f0f-b177-4b0b -aa89-a757da9432e3&redirect_uri=https://localhost:44338/GoogleAnalytics&client_id=xxxx

当用户连同代码一起被重定向回来时,我的令牌请求函数被调用:

public OAuth2Token GetToken(string code)
{
    var client = new RestClient(_tokenUri);
    var request = new RestRequest(Method.POST);
    request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
    request.AddParameter("undefined", $"client_id={_clientId}&client_secret={_secret}&code={code}&redirect_uri={_redirectUri}&grant_type=authorization_code", ParameterType.RequestBody);
    var response = client.Execute<OAuth2Token>(request);
    return response.Data;
}

访问和刷新令牌被返回,并存储在数据库中,然后在我的刷新函数中使用,这里的 tokenUri 是https://www.googleapis.com/oauth2/v4/token

public OAuth2Token RefreshToken()
{
    var client = new RestClient(_tokenUri);
    var request = new RestRequest(Method.POST);
    request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
    request.AddParameter("undefined", $"client_id={_clientId}&client_secret={_secret}&refresh_token={_refreshToken}&grant_type=refresh_token", ParameterType.RequestBody);
    var response = client.Execute<OAuth2Token>(request);
    if (!response.IsSuccessful)
        if (response.ErrorException == null)
            throw new Exception(response.Content); 
        else
            throw response.ErrorException;
    return response.Data;
}

还有一点需要注意的是,我这里的 Google App 处于测试模式,并且我已经将用户添加到了测试用户列表中。关于我在这里做错了什么有什么建议吗?

干杯

【问题讨论】:

  • 您有什么理由不使用 google .net 客户端库?
  • @DaImTo 决定是为了代码的可读性和一致性,因为项目中的每个 API 都使用相同的 OAuth2 行业标准,但没有一个共享相同的库。理论上,只要他们遵循标准,这应该无关紧要。

标签: c# oauth-2.0 oauth google-api google-oauth


【解决方案1】:

发帖请求希望看到帖子正文中的值。您将它们作为参数发送。

  request.AddParameter("undefined", $"client_id={_clientId}&client_secret={_secret}&refresh_token={_refreshToken}&grant_type=refresh_token", ParameterType.RequestBody);

您可能应该使用 request.AddBody

 request.AddBody("undefined", $"client_id={_clientId}&client_secret={_secret}&refresh_token={_refreshToken}&grant_type=refresh_token", ParameterType.RequestBody);

详细解释。

让我们从头开始。

Google 授权或者实际上所有的 Oauth2 服务器都会执行所谓的 Oauth dance,这个舞蹈分为三个步骤。

请求同意

您需要的第一个 URL 将导致授权服务器向用户显示同意屏幕。

GET https://accounts.google.com/o/oauth2/auth?client_id={clientid}&redirect_uri={redirectURI}&scope={scope}&response_type=code

这将返回一个授权码注意响应类型是 response_type=code

交换访问令牌和刷新令牌的授权代码。

这个调用是一个 HTTP Post 并且正文是一个 HTTP 请求字符串的形式。

POST https://accounts.google.com/o/oauth2/token
code={AUTHORIZATION CODE}&client_id={ClientId}&client_secret={ClientSecret}&redirect_uri={REDIRECT URI}&grant_type=authorization_code

这里的响应将是 Json 格式,将是一个刷新令牌和一个访问令牌。注意这里的grant_type是授权码。

{
"access_token" : "ya29.1.AADtN_VSBMC2Ga2lhxsTKjVQ_ROco8VbD6h01aj4PcKHLm6qvHbNtn-_BIzXMw",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/J-3zPA8XR1o_cXebV9sDKn_f5MTqaFhKFxH-3PUPiJ4"
}

由于您的访问令牌将在一小时后到期,您需要使用刷新令牌对其进行刷新

刷新访问令牌。

这也是一个 HTTP POST 调用,正文再次采用查询字符串的形式。 注意这里的授权类型是刷新令牌

POST https://accounts.google.com/o/oauth2/token
client_id={CLIENT ID}&client_secret={ClientSecret}&refresh_token={REFRESH TOKEN}&grant_type=refresh_token

那么你就有了一个新的访问令牌。

{
"access_token" : "ya29.1.AADtN_XK16As2ZHlScqOxGtntIlevNcasMSPwGiE3pe5ANZfrmJTcsI3ZtAjv4sDrPDRnQ",
"token_type" : "Bearer",
"expires_in" : 3600
}

【讨论】:

    猜你喜欢
    • 2016-01-26
    • 2022-08-16
    • 2016-08-03
    • 2020-02-06
    • 1970-01-01
    • 2021-05-15
    • 2012-02-15
    • 2014-11-25
    • 2016-12-13
    相关资源
    最近更新 更多