23

Google+ API を使用して、認証済みユーザーの情報にアクセスしようとしています。サンプルの 1 つからいくつかのコードをコピーしましたが、正常に動作します (以下)。

「RefreshToken」プロパティをキャプチャしてprovider.RefreshToken()(とりわけ)使用してみましたが、常に400 Bad Request応答が得られます。

誰かがこれを機能させる方法を知っていますか、またはいくつかのサンプルを見つけることができる場所を知っていますか? Googleコードサイトはこれをカバーしていないようです:-(

class Program
{
    private const string Scope = "https://www.googleapis.com/auth/plus.me";

    static void Main(string[] args)
    {
        var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
        provider.ClientIdentifier = "BLAH";
        provider.ClientSecret = "BLAH";
        var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthentication);

        var plus = new PlusService(auth);
        plus.Key = "BLAH";
        var me = plus.People.Get("me").Fetch();
        Console.WriteLine(me.DisplayName);
    }

    private static IAuthorizationState GetAuthentication(NativeApplicationClient arg)
    {
        // Get the auth URL:
        IAuthorizationState state = new AuthorizationState(new[] { Scope });
        state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
        Uri authUri = arg.RequestUserAuthorization(state);

        // Request authorization from the user (by opening a browser window):
        Process.Start(authUri.ToString());
        Console.Write("  Authorization Code: ");
        string authCode = Console.ReadLine();
        Console.WriteLine();

        // Retrieve the access token by using the authorization code:
        return arg.ProcessUserAuthorization(authCode, state);
    }
}
4

5 に答える 5

20

ここに例があります。RefreshToken という文字列設定を追加して System.Security を参照するか、リフレッシュ トークンを安全に保存する別の方法を見つけてください。

    private static byte[] aditionalEntropy = { 1, 2, 3, 4, 5 };

    private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
    {
        // Get the auth URL:
        IAuthorizationState state = new AuthorizationState(new[] { PlusService.Scopes.PlusMe.GetStringValue() });
        state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);

        string refreshToken = LoadRefreshToken();
        if (!String.IsNullOrWhiteSpace(refreshToken))
        {
            state.RefreshToken = refreshToken;

            if (arg.RefreshToken(state))
                return state;
        }

        Uri authUri = arg.RequestUserAuthorization(state);

        // Request authorization from the user (by opening a browser window):
        Process.Start(authUri.ToString());
        Console.Write("  Authorization Code: ");
        string authCode = Console.ReadLine();
        Console.WriteLine();

        // Retrieve the access token by using the authorization code:
        var result = arg.ProcessUserAuthorization(authCode, state);

        StoreRefreshToken(state);
        return result;
    }

    private static string LoadRefreshToken()
    {
        return Encoding.Unicode.GetString(ProtectedData.Unprotect(Convert.FromBase64String(Properties.Settings.Default.RefreshToken), aditionalEntropy, DataProtectionScope.CurrentUser));
    }

    private static void StoreRefreshToken(IAuthorizationState state)
    {
        Properties.Settings.Default.RefreshToken = Convert.ToBase64String(ProtectedData.Protect(Encoding.Unicode.GetBytes(state.RefreshToken), aditionalEntropy, DataProtectionScope.CurrentUser));
        Properties.Settings.Default.Save();
    }
于 2011-09-20T17:56:51.023 に答える
11

一般的な考え方は次のとおりです。

  1. ユーザーを Google の認証エンドポイントにリダイレクトします。

  2. 有効期間が短い認証コードを取得します。

  3. Google のトークン エンドポイントを使用して、承認コードを有効期間の長いアクセス トークンにすぐに交換します。Access Token には、有効期限と Refresh Token が付属しています。

  4. アクセス トークンを使用して、Google の API にリクエストを送信します。

アクセス トークンは、有効期限が切れるまで何度でも再利用できます。その後、更新トークンを使用して新しいアクセス トークンを要求できます (新しい有効期限と新しい更新トークンが付属しています)。

以下も参照してください。

于 2011-09-17T13:53:09.530 に答える
3

また、「オフライン」認証を機能させる(つまり、更新トークンを使用して認証を取得する)ことに問題があり400 Bad request、OPのコードに似たコードでHTTP応答を取得しました。ただし、-メソッドの行client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(this.clientSecret);で動作するようになりましたAuthenticate。これは、動作するコードを取得するために不可欠です。この行により、clientSecret が (HTTP 基本認証パラメーターとしてではなく) POST パラメーターとしてサーバーに送信されるように強制されると思います。

このソリューションは、クライアント ID、クライアント シークレット、および更新トークンを既に取得していることを前提としています。コードにアクセス トークンを入力する必要がないことに注意してください。(短期間の access-code は、行で長期間の refresh-token を送信するときに、Google サーバーから「内部で」取得client.RefreshAuthorization(state);されます。この access-token は、変数の一部として格納されauth、そこから使用されます「ボンネットの下で」API呼び出しを承認します。)

Google カレンダーにアクセスするための Google API v3 で動作するコード例:

class SomeClass
{

    private string clientID         = "XXXXXXXXX.apps.googleusercontent.com";
    private string clientSecret     = "MY_CLIENT_SECRET";
    private string refreshToken     = "MY_REFRESH_TOKEN";
    private string primaryCal       = "MY_GMAIL_ADDRESS";

    private void button2_Click_1(object sender, EventArgs e)
    {
        try
        {
            NativeApplicationClient client = new NativeApplicationClient(GoogleAuthenticationServer.Description, this.clientID, this.clientSecret);
            OAuth2Authenticator<NativeApplicationClient> auth = new OAuth2Authenticator<NativeApplicationClient>(client, Authenticate);

            // Authenticated and ready for API calls...

            // EITHER Calendar API calls (tested):
            CalendarService cal = new CalendarService(auth);
            EventsResource.ListRequest listrequest = cal.Events.List(this.primaryCal);
            Google.Apis.Calendar.v3.Data.Events events = listrequest.Fetch();
            // iterate the events and show them here.

            // OR Plus API calls (not tested) - copied from OP's code:
            var plus = new PlusService(auth);
            plus.Key = "BLAH";  // don't know what this line does.
            var me = plus.People.Get("me").Fetch();
            Console.WriteLine(me.DisplayName);

            // OR some other API calls...
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error while communicating with Google servers. Try again(?). The error was:\r\n" + ex.Message + "\r\n\r\nInner exception:\r\n" + ex.InnerException.Message);
        }
    }

    private IAuthorizationState Authenticate(NativeApplicationClient client)
    {
        IAuthorizationState state = new AuthorizationState(new string[] { }) { RefreshToken = this.refreshToken };

        // IMPORTANT - does not work without:
        client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(this.clientSecret);

        client.RefreshAuthorization(state);
        return state;
    }
}
于 2012-08-27T12:00:07.393 に答える
2

Google.NETクライアントAPIのサンプルソリューションの「SampleHelper」プロジェクトを確認することをお勧めします。

このファイルは、Windows保護データを使用して更新トークンを保存する方法と、ユーザーが手動で入力する代わりにローカルループバックサーバーとさまざまな手法を使用してアクセスコードをキャプチャする方法の両方を示しています。

この認証方法を使用するライブラリのサンプルの1つは、以下にあります。

于 2011-09-21T08:34:35.777 に答える
2

OAuth 2.0 仕様はまだ完成しておらず、これらのエラーが発生する原因となるさまざまなクライアントやサービスにわたって、仕様の実装が散在しています。ほとんどの場合、あなたはすべてを正しく行っていますが、使用している DotNetOpenAuth バージョンは、Google が現在実装しているものとは異なる OAuth 2.0 のドラフトを実装しています。仕様がまだ確定していないため、どちらの部分も「正しい」わけではありませんが、互換性は悪夢のようなものです。

使用している DotNetOpenAuth のバージョンが最新であることを確認できます (それが役立つ場合は、それが役立つ場合があります)。ただし、最終的には、仕様が完成し、全員が正しく実装するまでじっと待つか、Google ドキュメントを読む必要がある場合があります。あなた自身 (おそらく OAuth 2.0 のバージョンを説明している) を作成し、ドラフト バージョンを具体的に対象とするものを実装します。

于 2011-09-18T21:26:52.893 に答える