【问题标题】:Connecting to Google via OAuth 2, "invalid_request" when requesting an access token通过 OAuth 2 连接到 Google,请求访问令牌时出现“invalid_request”
【发布时间】:2013-02-14 20:56:54
【问题描述】:

在 SE 上已经有几个类似的问题,但我已经阅读了所有我能找到的似乎相关的内容,但我仍然不完全在那里。

我得到了一个验证码,所以现在我需要用它来交换一个访问令牌和一个刷新令牌。然而,谷歌返回奇妙的非特定错误“invalid_request”。这是我的代码:

private const string  BaseAccessTokenUrl = "https://accounts.google.com/o/oauth2/token";
private const string  ContentType        = "application/x-www-form-urlencoded";

public static string  GetRefreshToken(string clientId, string clientSecret, string authCode)
    {
    Dictionary<string, string>  parameters = new Dictionary<string, string>
        {
        { "code",          authCode },
        { "client_id",     clientId },
        { "client_secret", clientSecret },
        { "redirect_uri",  "http://localhost" },
        { "grant_type",    "authorization_code" }
        };
    string  rawJson = WebUtilities.Post(BaseAccessTokenUrl, parameters, ContentType);
    return rawJson;  // TODO: Parse out the actual refresh token
    }

我的Post() 方法对参数键和值进行 URL 编码并将它们连接起来:

public static string  Post(string uri, Dictionary<string, string> properties, string contentType = "application/x-www-form-urlencoded")
    {
    string  content = String.Join("&", from kvp in properties select UrlEncode(kvp.Key) + "=" + UrlEncode(kvp.Value) );
    return Post(uri, content);
    }

双参数Post() 方法只是处理将内容转换为字节、添加内容长度等,然后返回响应的内容,即使它以WebException 的形式出现。如果有任何兴趣,我可以包含它。

授权码看起来不错,和我见过的其他类似:62 个字符,以“4/”开头。我从the Google API Console 仔细复制的客户端 ID、密码和重定向 URL。该应用程序已注册为“其他”应用程序,并且我正在从 Windows 计算机进行连接。

根据thisthis post,我尝试过不进行 URL 编码,但没有任何变化。 The OAuth Playground 表明 URL 编码是正确的。

根据this postthis one,属性被连接在一行中。

根据this post,我在授权请求中尝试了approval_prompt=force,但新的授权码并没有更好的工作。验证码会过期吗?我通常会在几秒钟内使用新代码。

根据the Google docsthis post,我使用的是内容类型“application/x-www-form-encoded”。

我的授权请求是针对范围“https://www.googleapis.com/auth/analytics.readonly”的。

根据this post,参数中没有前导问号。

一个 Google .NET OAuth 库,但我无法让它轻松运行,如果我有选择的话,大约 50,000 行代码比我想研究的要多.我更喜欢从头开始写一些干净的东西,而不是盲目地复制一堆库,货物崇拜风格。

【问题讨论】:

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


    【解决方案1】:

    找到了。用于请求令牌的redirect_uri 需要与获取授权码时使用的匹配。这是我获取授权码的工作代码:

    private const string  BaseAuthorizationUrl = "https://accounts.google.com/o/oauth2/auth";
    public string  GetAuthorizationUrl(string clientId, IEnumerable<string> scopes)
        {
        var  parameters = new Dictionary<string, string>
            {
            { "response_type",   "code" },
            { "client_id",       clientId },
            { "redirect_uri",    RedirectUrl },
            { "scope",           String.Join(" ", scopes) },
            { "approval_prompt", "auto" }
            };
        return WebUtilities.BuildUrl(BaseAuthorizationUrl, parameters);
        }
    

    ...这是我获取访问令牌和刷新令牌的代码:

    private const string  BaseAccessTokenUrl = "https://accounts.google.com/o/oauth2/token";
    public void  GetTokens(string clientId, string clientSecret, string authorizationCode, out string accessToken, out string refreshToken)
        {
        var  parameters = new Dictionary<string, string>
            {
            { "code",          authorizationCode },
            { "redirect_uri",  RedirectUrl },  // Must match that used when authorizing an app
            { "client_id",     clientId },
            { "scope",         String.Empty },
            { "client_secret", clientSecret },
            { "grant_type",    "authorization_code" }
            };
        string   rawJson    = WebUtilities.Post(BaseAccessTokenUrl, parameters, "application/x-www-form-urlencoded");
        dynamic  parsedJson = JsonUtilities.DeserializeObject(rawJson);
        accessToken  = parsedJson.access_token;
        refreshToken = parsedJson.refresh_token;
        }
    

    ...这是获取新访问令牌的代码:

    public string  GetAccessToken(string clientId, string clientSecret, string refreshToken)
        {
        var  parameters = new Dictionary<string, string>
            {
            { "client_id",     clientId },
            { "client_secret", clientSecret },
            { "refresh_token", refreshToken },
            { "grant_type",    "refresh_token" }
            };
        string   rawJson    = WebUtilities.Post(BaseAccessTokenUrl, parameters, "application/x-www-form-urlencoded");
        dynamic  parsedJson = JsonUtilities.DeserializeObject(rawJson);
        return parsedJson.access_token;
        }
    

    【讨论】:

    • 我仍然有同样的问题,我正在从原始 C++ 中尝试它。总是 invalid_request。
    • @Michael:如果您想提出更具体的问题,我可以提供帮助。可以这么说,您是否回顾了文献?那里有很多问题和答案(OAuth 很痛苦,你不是唯一一个!)。
    • 我终于找到了。由于诸如“无效请求”之类的愚蠢错误消息而无法检测到的常见拼写错误。感谢您的努力。
    • @Michael 你的拼写错误是什么?收到相同的“invalid_request”愚蠢消息
    猜你喜欢
    • 2012-09-29
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 2022-01-13
    • 2013-02-24
    • 2011-01-19
    • 2014-08-10
    • 2018-10-28
    相关资源
    最近更新 更多