1

すでにSEでこれらの線に沿っていくつかの質問がありますが、私は関連があると思われるものを見つけることができるすべてを読みました、そして私はまだそこに完全ではありません。

認証コードを取得したので、アクセストークンと更新トークンに交換する必要があります。ただし、Googleは驚くほど非特定のエラー「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);
    }

2パラメータPost()メソッドは、コンテンツのバイトへの変換、content-lengthの追加などを処理し、応答のコンテンツがとして返された場合でも返しますWebException。興味があれば含めることができます。

認証コードは正しく見えます。これは私が見た他のコードと似ています。62文字で、「4/」で始まります。Google APIコンソールから慎重にコピーしたクライアントID、シークレット、リダイレクトURL 。アプリは「その他」のアプリとして登録されており、Windowsマシンから接続しています。

これとこの投稿に従って、私は変更なしでURLエンコードを試みませんでした。 OAuth Playgroundは、URLエンコードが正しいことを示しています。

この投稿この投稿ごとに、プロパティは1行に連結されます。

この投稿によると、承認リクエストを試しapproval_prompt=forceましたが、新しい認証コードはうまく機能しませんでした。認証コードは期限切れになりますか?通常、数秒以内に新しいコードを使用しています。

Googleドキュメントこの投稿によると、私はコンテンツタイプ「application/x-www-form-encoded」を使用しています。

私の承認リクエストはスコープ「https://www.googleapis.com/auth/analytics.readonly」に対するものです。

この投稿によると、パラメータに先頭の疑問符はありません。

Google .NET OAuthライブラリがあります、簡単に機能させることができませんでした。選択肢があれば、約50,000行のコードを調べたいと思っています。私は、カーゴカルトスタイルの図書館の束を盲目的にコピーするよりも、ゼロからきれいなものを書くことを好みます。

4

1 に答える 1

6

それを見つけた。トークンの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;
    }
于 2013-02-15T20:16:05.240 に答える