2016-07-08 3 views
5

SurveyMonkey API와 상호 작용하는 로컬 Java 기반 클라이언트를 만들려고합니다.리디렉션 서버없이 OAuth 2.0을 사용할 수 있습니까?

SurveyMonkey에는 익숙하지 않은 OAuth 2.0을 사용하여 수명이 긴 액세스 토큰이 필요합니다. 내게는 서베이 몽키와 상호 작용하는 간단한 자바 클라이언트를 작성하는

가 가능 :

나는 시간이 인터넷 검색을 봤는데, 나는 대답이 '아니오'생각하지만, 난 그냥 확인하려면 일부 클라우드에 자체 리디렉션 서버를 설정하지 않고?

OAuth 2.0에서 생성 된 무기명 토큰을 수신하려면 내 온라인 서비스가 꼭 필요하다고 생각합니다. SurveyMonkey가 베어러 토큰을 내 고객에게 직접 보내지 못하게 할 수 있습니까? 어디 선가 내 자신의 사용자 정의 서블릿를 설정하고 redirect_uri로로 사용한다면

는 그리고, 다음 올바른 흐름이 될 것이다 다음과 같이

  1. 자바 클라이언트 요청 베어러 토큰을 서베이 몽키에서, 로 redirect_uri는 내 자신의 사용자 정의 서블릿 URL입니다.
  2. SurveyMonkey가 사용자 정의 서블릿 URL로 토큰을 보냅니다.
  3. 자바 클라이언트는 토큰을 사용할 수있을 때까지 사용자 정의 서블릿 URL을 폴링합니까?

이 정보가 맞습니까?

+0

이 어떤 도움이 있다면 모르겠지만, 구글 인증을 위해 I에 의해 내 리디렉션 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과 앱의 설정에서 지정한 URL이 일치하는지 확인). . 당신의 리디렉션 URL이 https://example.com/surveymonkey/oauth 인 경우

그래서, 서베이 몽키는 코드를 해당 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 예, 무기명의 앱을 사용하여 앱 소유자의 동일한 계정에 액세스 할 수 있습니다. 앱을 사용할 수있는 상태와 상관없이 항상 앱 소유자의 계정에 액세스하는 데 사용할 수 있습니다. 또는 자신의 계정 (client_credentials의 grant_type) : –

+0

또한, 당신이 관심 단지의 경우, 가능성이 그룹 (개인 응용 프로그램의 경우)의 사용자에 대한 액세스 토큰을 얻을 수있는 방법이 될 것입니다. 변경 사항에 대한 알림을 받으려면 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"]); 
    } 
} 
관련 문제