2016-07-08 12 views
5

SurveyMonkey APIとやりとりするローカルのJavaベースのクライアントを作成しようとしています。リダイレクトサーバなしでOAuth 2.0を使用することはできますか?

SurveyMonkeyには、あまり慣れていないOAuth 2.0を使用して、長寿命のアクセストークンが必要です。 、私はSurveyMonkeyと対話する単純なJavaクライアントを作成するため

が可能です:

私は時間のためにこれをグーグルでてきた、と私は答えはノーだと思いますが、私はちょうどことを確認したいです一部のクラウドに自分のリダイレクトサーバーを設定しないでください

OAuth 2.0で生成されたベアラトークンを受信できるようにするためには、自分のオンラインサービスを必須と思っています。 SurveyMonkeyにベアラトークンをクライアントに直接送信させることはできないのでしょうか?

そして、私はどこかで自分のカスタムサーブレットを設定し、REDIRECT_URIとしてそれを使用した場合、次のように、正しい流れは次のようになります。 とSurveyMonkeyから

  1. のJavaクライアントの要求ベアラ・トークン、 redirect_uriは私自身のカスタムサーブレットURLです。
  2. SurveyMonkeyはカスタムサーブレットURLにトークンを送信します。
  3. トークンが利用可能になるまでJavaクライアントがカスタムサーブレットのURLをポーリングしますか?

これは間違いありませんか?

+0

それは任意の助けである場合、私は知らないが、Googleの認証のために、私は私でリダイレクトURLを取得:(=新しいLocalServerReceiver \t VerificationCodeReceiver受信機)。 receiver = Preconditions.checkNotNull(receiver); 文字列redirectUri = receiver.getRedirectUri(); – c0der

答えて

6

OAuthフローの全般的なポイントは、ユーザー(データにアクセスしているクライアント)がユーザーにデータへのアクセス権を与える必要があるということです。

authentication instructionsを参照してください。あなたはページを承認のOAuthにユーザーを送信する必要があります。

https://api.surveymonkey.net/oauth/authorize?api_key<your_key>&client_id=<your_client_id>&response_type=code&redirect_uri=<your_redirect_uri> 

これは、あなたが(元へのアクセスを要求している自分のアカウントの部分にそれらを伝えるユーザーにページが表示されますそれらの応答を参照してください、彼らの調査を参照してください。等)。ユーザーがそのページで[承認]をクリックすることで承認されると、SurveyMonkeyはリダイレクトURIとして設定したものに自動的に移動します(上のURLのURLがアプリの設定で設定したものと一致することを確認してください) 。

あなたのリダイレクトURLがhttps://example.com/surveymonkey/oauthだったのであれば、SurveyMonkeyはコードでそのURLにユーザーをリダイレクトします:

https://example.com/surveymonkey/oauth?code=<auth_code>

あなたはそのコードを取り、その後、実行してアクセストークンのためにそれを交換する必要があります次のポストのparamsとhttps://api.surveymonkey.net/oauth/token?api_key=<your_api_key>へのPOSTリクエスト:

client_secret=<your_secret> 
code=<auth_code_you_just_got> 
redirect_uri=<same_redirect_uri_as_before> 
grant_type=authorization_code 

これは、あなたがそのユーザーのアカウントのデータにアクセスするためのアクセストークンを使用することができ、アクセストークンを返します。ユーザーにアクセスするために使用するアクセストークンをユーザーに与えないでください。ポーリングや何もする必要はありません。

自分のアカウントにアクセスしている場合は、アプリの設定ページにあるアクセストークンを使用できます。それ以外の場合は、自分のリダイレクトサーバーを設定せずにユーザーのアクセストークンを取得する方法はありません(ただし、すべてのユーザーが同じグループに属している必要はありません。 SurveyMonkeyは、ユーザーがコードを送信するとコードを送信する場所が必要です。コードを要求するだけではありません。

+0

あなたの最後の提案は、設定パネルに関する:私はこれと同様の回避策を試みてきましたが、うまくいかないようです。 「私のアプリケーション」セクションの「アクセストークン」がプライベートアプリに使用できるベアラトークンであると仮定するのは正しいですか? – Tovi7

+1

@ Tovi7はい、ベアラのアプリを使って、アプリのオーナーと同じアカウントにアクセスできます。これは、アプリがどのステータスになっているかにかかわらず、常にアプリオーナーのアカウントにアクセスするために使用することができます(無効の場合を除きます)。 –

+0

また、興味がある場合には、グループ内のユーザー(ケース:プライベートアプリ)または独自のアカウント(client_credentials grant_type)のアクセストークンを取得する方法があります。変更の通知を受けるには、https://github.com/SurveyMonkey/public_api_docsでドキュメントをご覧ください。 –

5

はい、コールバックURLなしでOAuth2を使用することは可能です。 RFC6749にはいくつかのフローが導入されています。 ImplicitAuthorization Codeのグラントタイプでは、リダイレクトURIが必要です。ただし、Resource Owner Password Credentials付与タイプはありません。

リダイレクトURIを必要としない限定デバイス(https://tools.ietf.org/html/draft-ietf-oauth-device-flow)に別の許可タイプを導入しようとするIETFドラフトがあります。

いずれの場合でも、上記の助成金タイプがあなたのニーズに合わない場合、custom grant typeを作成することはできません。

2

doは、redirect_uriとして機能するものを実装する必要があります。これは、クラウド以外のどこかでホストする必要はありません。

私はJavaとServeletsに慣れていませんが、私が正しく推測すれば、それはhttp://localhost:some_portを処理できるものです。その場合、記述するフローは正しいです。

C#で同じフローを正常に実装しました。ここにそのフローを実装するクラスがあります。私はそれが助けて欲しい

class OAuth2Negotiator 
{ 
    private HttpListener _listener = null; 
    private string _accessToken = null; 
    private string _errorResult = null; 
    private string _apiKey = null; 
    private string _clientSecret = null; 
    private string _redirectUri = null; 

    public OAuth2Negotiator(string apiKey, string address, string clientSecret) 
    { 
     _apiKey = apiKey; 
     _redirectUri = address.TrimEnd('/'); 
     _clientSecret = clientSecret; 

     _listener = new HttpListener(); 
     _listener.Prefixes.Add(address + "/"); 
     _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous; 
    } 

    public string GetToken() 
    { 
     var url = string.Format(@"https://api.surveymonkey.net/oauth/authorize?redirect_uri={0}&client_id=sm_sunsoftdemo&response_type=code&api_key=svtx8maxmjmqavpavdd5sg5p", 
       HttpUtility.UrlEncode(@"http://localhost:60403")); 
     System.Diagnostics.Process.Start(url); 

     _listener.Start(); 
     AsyncContext.Run(() => ListenLoop(_listener)); 
     _listener.Stop(); 

     if (!string.IsNullOrEmpty(_errorResult)) 
      throw new Exception(_errorResult); 
     return _accessToken; 
    } 

    private async void ListenLoop(HttpListener listener) 
    { 
     while (true) 
     { 
      var context = await listener.GetContextAsync(); 
      var query = context.Request.QueryString; 
      if (context.Request.Url.ToString().EndsWith("favicon.ico")) 
      { 
       context.Response.StatusCode = (int)HttpStatusCode.NotFound; 
       context.Response.Close(); 
      } 
      else if (query != null && query.Count > 0) 
      { 
       if (!string.IsNullOrEmpty(query["code"])) 
       { 
        _accessToken = await SendCodeAsync(query["code"]); 
        break; 
       } 
       else if (!string.IsNullOrEmpty(query["error"])) 
       { 
        _errorResult = string.Format("{0}: {1}", query["error"], query["error_description"]); 
        break; 
       } 
      } 
     } 
    } 

    private async Task<string> SendCodeAsync(string code) 
    { 
     var GrantType = "authorization_code"; 
     //client_secret, code, redirect_uri and grant_type. The grant type must be set to “authorization_code” 
     var client = new HttpClient(); 
     client.BaseAddress = new Uri("https://api.surveymonkey.net"); 
     var request = new HttpRequestMessage(HttpMethod.Post, string.Format("/oauth/token?api_key={0}", _apiKey)); 

     var formData = new List<KeyValuePair<string, string>>(); 
     formData.Add(new KeyValuePair<string, string>("client_secret", _clientSecret)); 
     formData.Add(new KeyValuePair<string, string>("code", code)); 
     formData.Add(new KeyValuePair<string, string>("redirect_uri", _redirectUri)); 
     formData.Add(new KeyValuePair<string, string>("grant_type", GrantType)); 
     formData.Add(new KeyValuePair<string, string>("client_id", "sm_sunsoftdemo")); 

     request.Content = new FormUrlEncodedContent(formData); 
     var response = await client.SendAsync(request); 
     if (!response.IsSuccessStatusCode) 
     { 
      _errorResult = string.Format("Status {0}: {1}", response.StatusCode.ToString(), response.ReasonPhrase.ToString()); 
      return null; 
     } 

     var data = await response.Content.ReadAsStringAsync(); 
     if (data == null) 
      return null; 
     Dictionary<string, string> tokenInfo = JsonConvert.DeserializeObject<Dictionary<string, string>>(data); 
     return(tokenInfo["access_token"]); 
    } 
} 
関連する問題