예제 #1
0
        private string ComputeChallenge(AuthenticatorChallenge challenge, string apiKey)
        {
            if (string.IsNullOrEmpty(challenge.RSAExponent) || string.IsNullOrEmpty(challenge.RSAModulus) || string.IsNullOrEmpty(challenge.Challenge))
            {
                throw new InvalidOperationException("Invalid authentication information");
            }

            var apiKeyParts = ExtractApiKeyAndSecret(apiKey);
            var apiKeyName  = apiKeyParts[0].Trim();
            var apiSecret   = apiKeyParts[1].Trim();

            var data = OAuthHelper.DictionaryToString(new Dictionary <string, string>
            {
                { OAuthHelper.Keys.RSAExponent, challenge.RSAExponent },
                { OAuthHelper.Keys.RSAModulus, challenge.RSAModulus },
                {
                    OAuthHelper.Keys.EncryptedData,
                    OAuthHelper.EncryptAsymmetric(OAuthHelper.ParseBytes(challenge.RSAExponent),
                                                  OAuthHelper.ParseBytes(challenge.RSAModulus),
                                                  OAuthHelper.DictionaryToString(new Dictionary <string, string>
                    {
                        { OAuthHelper.Keys.APIKeyName, apiKeyName },
                        { OAuthHelper.Keys.Challenge, challenge.Challenge },
                        { OAuthHelper.Keys.Response, OAuthHelper.Hash(string.Format("{0};{1}", challenge, apiSecret)) }
                    }))
                }
            });

            return(data);
        }
예제 #2
0
        private Tuple <HttpWebRequest, string> PrepareOAuthRequest(string oauthSource, string serverRSAExponent, string serverRSAModulus, string challenge)
        {
#if !SILVERLIGHT
            var authRequest = (HttpWebRequest)WebRequest.Create(oauthSource);
#else
            var authRequest = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(oauthSource));
#endif
            authRequest.Headers["grant_type"] = "client_credentials";
            authRequest.Accept = "application/json;charset=UTF-8";
            authRequest.Method = "POST";

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

                var apiKeyParts = apiKey.Split(new[] { '/' }, StringSplitOptions.None);

                if (apiKeyParts.Length > 2)
                {
                    apiKeyParts[1] = string.Join("/", apiKeyParts.Skip(1));
                }

                if (apiKeyParts.Length < 2)
                {
                    throw new InvalidOperationException("Invalid API key");
                }

                var apiKeyName = apiKeyParts[0].Trim();
                var apiSecret  = apiKeyParts[1].Trim();


                var 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, apiKeyName },
                            { OAuthHelper.Keys.Challenge, challenge },
                            {
                                OAuthHelper.Keys.Response,
                                OAuthHelper.Hash(string.Format(OAuthHelper.Keys.ResponseFormat, challenge, apiSecret))
                            }
                        }))
                    }
                });

                return(Tuple.Create(authRequest, data));
            }
            authRequest.ContentLength = 0;
            return(Tuple.Create(authRequest, (string)null));
        }
예제 #3
0
        private string ComputeChallenge(RavenJObject challengeJObject, string apiKey)

        {
            if (challengeJObject == null)
            {
                throw new InvalidDataException("Got null json object in ComputeChallenge");
            }

            serverRSAExponent = challengeJObject.Value <string>(OAuthHelper.Keys.RSAExponent);
            serverRSAModulus  = challengeJObject.Value <string>(OAuthHelper.Keys.RSAModulus);
            challenge         = challengeJObject.Value <string>(OAuthHelper.Keys.Challenge);

            if (string.IsNullOrEmpty(serverRSAExponent) || string.IsNullOrEmpty(serverRSAModulus) || string.IsNullOrEmpty(challenge))
            {
                throw new InvalidOperationException("Invalid authentication information");
            }

            var apiKeyParts = ExtractApiKeyAndSecret(apiKey);
            var apiKeyName  = apiKeyParts[0].Trim();
            var apiSecret   = apiKeyParts[1].Trim();

            var data = OAuthHelper.DictionaryToString(new Dictionary <string, string>
            {
                { OAuthHelper.Keys.RSAExponent, serverRSAExponent },
                { OAuthHelper.Keys.RSAModulus, serverRSAModulus },
                {
                    OAuthHelper.Keys.EncryptedData,
                    OAuthHelper.EncryptAsymmetric(OAuthHelper.ParseBytes(serverRSAExponent),
                                                  OAuthHelper.ParseBytes(serverRSAModulus),
                                                  OAuthHelper.DictionaryToString(new Dictionary <string, string>
                    {
                        { OAuthHelper.Keys.APIKeyName, apiKeyName },
                        { OAuthHelper.Keys.Challenge, challenge },
                        { OAuthHelper.Keys.Response, OAuthHelper.Hash(string.Format(OAuthHelper.Keys.ResponseFormat, challenge, apiSecret)) }
                    }))
                }
            });

            return(data);
        }
예제 #4
0
        public async Task <Action <HttpClient> > DoOAuthRequestAsync(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++;

#if !SILVERLIGHT && !NETFX_CORE
                var handler = new WebRequestHandler();
#else
                var handler = new HttpClientHandler();
#endif

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

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

                    var apiKeyParts = apiKey.Split(new[] { '/' }, StringSplitOptions.None);
                    if (apiKeyParts.Length > 2)
                    {
                        apiKeyParts[1] = string.Join("/", apiKeyParts.Skip(1));
                    }
                    if (apiKeyParts.Length < 2)
                    {
                        throw new InvalidOperationException("Invalid API key");
                    }

                    var apiKeyName = apiKeyParts[0].Trim();
                    var apiSecret  = apiKeyParts[1].Trim();

                    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, apiKeyName },
                                { OAuthHelper.Keys.Challenge, challenge },
                                { OAuthHelper.Keys.Response, OAuthHelper.Hash(string.Format(OAuthHelper.Keys.ResponseFormat, challenge, apiSecret)) }
                            }))
                        }
                    });
                }

                var requestUri = oauthSource
#if SILVERLIGHT
                                 .NoCache()
#endif
                ;

                var response = await httpClient.PostAsync(requestUri, data != null?(HttpContent) new CompressedStringContent(data, true) : new StringContent(""))
                               .AddUrlIfFaulting(new Uri(requestUri))
                               .ConvertSecurityExceptionToServerNotFound();

                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())
                    using (var reader = new StreamReader(stream))
                    {
                        CurrentOauthToken = reader.ReadToEnd();


#if SILVERLIGHT
                        BrowserCookieToAllowUserToUseStandardRequests(baseUrl, reader.ReadToEnd());
#endif
                        return((Action <HttpClient>)(SetAuthorization));
                    }
            }
        }