Is it possible to use OAuth 2.0 without a redirect server?

前端 未结 3 1655
心在旅途
心在旅途 2020-12-05 04:24

I\'m trying to create a local Java-based client that interacts with the SurveyMonkey API.

SurveyMonkey requires a long-lived access token using OAuth 2.0, which I\'m

3条回答
  •  无人及你
    2020-12-05 04:55

    You do need to implement something that will act as the redirect_uri, which does not necessarily need to be hosted somewhere else than your client (as you say, in some cloud).

    I am not very familiar with Java and Servelets, but if I assume correctly, it would be something that could handle http://localhost:some_port. In that case, the flow that you describe is correct.

    I implemented the same flow successfully in C#. Here is the class that implements that flow. I hope it helps.

    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 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>();
            formData.Add(new KeyValuePair("client_secret", _clientSecret));
            formData.Add(new KeyValuePair("code", code));
            formData.Add(new KeyValuePair("redirect_uri", _redirectUri));
            formData.Add(new KeyValuePair("grant_type", GrantType));
            formData.Add(new KeyValuePair("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 tokenInfo = JsonConvert.DeserializeObject>(data);
            return(tokenInfo["access_token"]);
        }
    }
    

提交回复
热议问题