Пример #1
0
 public ErrorResponseException(ErrorResponseException e, string message)
     : base(message)
 {
     response       = e.Response;
     ResponseString = e.ResponseString;
 }
Пример #2
0
        public static async Task <string> GetOAuthToken(string baseUrl, string oauthSource, string apiKey)
        {
            if (oauthSource == null)
            {
                throw new ArgumentNullException("oauthSource");
            }

            string serverRSAExponent = null;
            string serverRSAModulus  = null;
            string challenge         = null;

            // Note that at two tries will be needed in the normal case.
            // The first try will get back a challenge,
            // the second try will try authentication. If something goes wrong server-side though
            // (e.g. the server was just rebooted or the challenge timed out for some reason), we
            // might get a new challenge back, so we try a third time just in case.
            int tries = 0;

            while (true)
            {
                tries++;
                var handler = new HttpClientHandler();

                using (var httpClient = new HttpClient(handler))
                {
                    httpClient.DefaultRequestHeaders.TryAddWithoutValidation("grant_type", "client_credentials");
                    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")
                    {
                        CharSet = "UTF-8"
                    });

                    var data = string.Empty;
                    if (string.IsNullOrEmpty(serverRSAExponent) == false &&
                        string.IsNullOrEmpty(serverRSAModulus) == false &&
                        string.IsNullOrEmpty(challenge) == false)
                    {
                        var exponent = OAuthHelper.ParseBytes(serverRSAExponent);
                        var modulus  = OAuthHelper.ParseBytes(serverRSAModulus);

                        var apiKeyParts = GetApiKeyParts(apiKey);

                        data = OAuthHelper.DictionaryToString(new Dictionary <string, string> {
                            { OAuthHelper.Keys.RSAExponent, serverRSAExponent }, { OAuthHelper.Keys.RSAModulus, serverRSAModulus }, { OAuthHelper.Keys.EncryptedData, OAuthHelper.EncryptAsymmetric(exponent, modulus, OAuthHelper.DictionaryToString(new Dictionary <string, string> {
                                    { OAuthHelper.Keys.APIKeyName, apiKeyParts.ApiKeyName }, { OAuthHelper.Keys.Challenge, challenge }, { OAuthHelper.Keys.Response, OAuthHelper.Hash(string.Format(OAuthHelper.Keys.ResponseFormat, challenge, apiKeyParts.ApiSecret)) }
                                })) }
                        });
                    }

                    var requestUri = oauthSource;
                    var response   = await httpClient.PostAsync(requestUri, new StringContent(data)).AddUrlIfFaulting(new Uri(requestUri)).ConvertSecurityExceptionToServerNotFound().ConfigureAwait(false);

                    if (response.IsSuccessStatusCode == false)
                    {
                        // We've already tried three times and failed
                        if (tries >= 3)
                        {
                            throw ErrorResponseException.FromResponseMessage(response);
                        }

                        if (response.StatusCode != HttpStatusCode.PreconditionFailed)
                        {
                            throw ErrorResponseException.FromResponseMessage(response);
                        }

                        var header = response.Headers.GetFirstValue("WWW-Authenticate");
                        if (header == null || header.StartsWith(OAuthHelper.Keys.WWWAuthenticateHeaderKey) == false)
                        {
                            throw new ErrorResponseException(response, "Got invalid WWW-Authenticate value");
                        }

                        var challengeDictionary = OAuthHelper.ParseDictionary(header.Substring(OAuthHelper.Keys.WWWAuthenticateHeaderKey.Length).Trim());
                        serverRSAExponent = challengeDictionary.GetOrDefault(OAuthHelper.Keys.RSAExponent);
                        serverRSAModulus  = challengeDictionary.GetOrDefault(OAuthHelper.Keys.RSAModulus);
                        challenge         = challengeDictionary.GetOrDefault(OAuthHelper.Keys.Challenge);

                        if (string.IsNullOrEmpty(serverRSAExponent) || string.IsNullOrEmpty(serverRSAModulus) || string.IsNullOrEmpty(challenge))
                        {
                            throw new InvalidOperationException("Invalid response from server, could not parse raven authentication information: " + header);
                        }

                        continue;
                    }

                    using (var stream = await response.GetResponseStreamWithHttpDecompression().ConfigureAwait(false))
                        using (var reader = new StreamReader(stream))
                        {
                            var currentOauthToken = reader.ReadToEnd();
                            return(currentOauthToken);
                        }
                }
            }
        }