private static void ExtractContent(string responseBody, FacebookClient facebookClient)
        {
            const string accessTokenKey = "access_token=";
            const string expiresKey = "expires=";

            Condition.Requires(responseBody).IsNotNullOrEmpty();
            Condition.Requires(facebookClient).IsNotNull();

            var data = responseBody.Split(new[] {'&'}, StringSplitOptions.RemoveEmptyEntries);
            Condition.Requires(data).IsNotNull().HasLength(2);
            int foundItems = 0;
            foreach (var content in data)
            {
                // What do we have?
                if (content.StartsWith(accessTokenKey))
                {
                    facebookClient.AccessToken = ExtractContent(content, accessTokenKey);
                    foundItems++;
                }
                else if (content.StartsWith(expiresKey))
                {
                    facebookClient.ExpiresOn =
                        DateTime.UtcNow.AddSeconds(Convert.ToInt32(ExtractContent(content, expiresKey)));
                    foundItems++;
                }
            }

            // Check to make sure we've correctly extracted all the required data.
            Condition.Requires(foundItems).IsEqualTo(2);
        }
        private FacebookClient TryGetFacebook(NameValueCollection parameters, string existingState)
        {
            Condition.Requires(parameters).IsNotNull().IsLongerThan(0);
            Condition.Requires(existingState).IsNotNull();

            // Is this a facebook callback?
            var code = parameters["code"];
            var state = parameters["state"];

            if (!string.IsNullOrEmpty(code) &&
                !string.IsNullOrEmpty(state))
            {
                // CSRF (state) check.
                if (state != existingState)
                {
                    throw new InvalidOperationException("The states do not match. It's possible that you may be a victim of a CSRF.");
                }

                // Now ask Facebook for a Token.
                var facebookClient = new FacebookClient
                           {
                               Code = code,
                               State = state
                           };

                FacebookProvider.RetrieveAccessToken(facebookClient);
                return facebookClient;
            }

            // Maybe we have an error?
            var errorReason = parameters["error_reason"];
            var error = parameters["error"];
            var errorDescription = parameters["error_description"];
            if (!string.IsNullOrEmpty(errorReason) &&
                !string.IsNullOrEmpty(error) &&
                !string.IsNullOrEmpty(errorDescription))
            {
                return new FacebookClient
                           {
                               ErrorReason = errorReason,
                               Error = error,
                               ErrorDescription = errorDescription
                           };
            }

            // Nope. Didn't auth with Facebook.
            return null;
        }
            public void GivenAMissingExpiresParam_RetrieveAccessToken_ThrowsAnException()
            {
                // Arrange.
                var mockWebClientWrapper = MoqUtilities.MockedIWebClientWrapper(new[] { "access_token=foo&hi=ohnoes", null });
                var facebookProvider = new FacebookProvider("a", "b", new Uri("http://www.google.com"),
                                                            mockWebClientWrapper.Object);
                var facebookClient = new FacebookClient
                {
                    Code = "aa",
                    State = "bb"
                };

                // Act.
                var result = Assert.Throws<ArgumentException>(() => facebookProvider.RetrieveAccessToken(facebookClient));

                // Assert.
                Assert.NotNull(result);
                Assert.Equal("value should be equal to 2. The actual value is 1.\r\nParameter name: value", result.Message);
            }
            public void GivenSomeInvalidResult_RetrieveAccessToken_ThrowsAnException()
            {
                // Arrange.
                var mockWebClientWrapper = MoqUtilities.MockedIWebClientWrapper(new [] { "asds", null});
                var facebookProvider = new FacebookProvider("a", "b", new Uri("http://www.google.com"),
                                                            mockWebClientWrapper.Object);
                var facebookClient = new FacebookClient
                {
                    Code = "aa",
                    State = "bb"
                };

                // Act.
                var result = Assert.Throws<ArgumentException>(() => facebookProvider.RetrieveAccessToken(facebookClient));

                // Assert.
                Assert.NotNull(result);
                Assert.Equal("value should contain 2 elements. value contains currently 1 element.\r\nParameter name: value", result.Message);
            }
        public void RetrieveAccessToken(FacebookClient facebookClient)
        {
            Condition.Requires(facebookClient).IsNotNull();
            Condition.Requires(facebookClient.Code).IsNotNullOrEmpty();

            var tokenUri = string.Format(TokenUri, ClientId, RedirectUri, ClientSecret, facebookClient.Code);
            var responseBody = WebClient.DownloadString(tokenUri);

            if (string.IsNullOrEmpty(responseBody))
            {
                throw new InvalidOperationException("No access token was received from Facebook.");
            }

            // Extract the relevant data.
            ExtractContent(responseBody, facebookClient);

            // Grab the user's information.
            facebookClient.UserInformation = RetrieveUserInformation(facebookClient.AccessToken);
        }
            public void GivenValidCredentials_RetrieveAccessToken_ReturnsAnAccessTokenAndUserInformation()
            {
                // Arrange.
                var mockWebClientWrapper = MoqUtilities.MockedIWebClientWrapper();
                var facebookProvider = new FacebookProvider("a", "b", new Uri("http://www.google.com"),
                                                            mockWebClientWrapper.Object);
                var facebookClient = new FacebookClient
                                     {
                                         Code = "aa",
                                         State = "bb"
                                     };

                // Act.
                facebookProvider.RetrieveAccessToken(facebookClient);

                // Assert.
                Assert.NotNull(facebookClient);
                Assert.NotNull(facebookClient.AccessToken);
                Assert.NotNull(facebookClient.Code);
                Assert.NotNull(facebookClient.UserInformation);
                Assert.True(facebookClient.UserInformation.Id > 0);
                Assert.NotNull(facebookClient.UserInformation.FirstName);
                Assert.NotNull(facebookClient.UserInformation.LastName);
            }
            public void GivenSomethingWeirdHappenedWhileTryingToRetrieveMeData_RetrieveAccessToken_ThrowsAnException()
            {
                // Arrange.
                var mockWebClientWrapper = MoqUtilities.MockedIWebClientWrapper(new[] { "access_token=foo&expires=1", "ohcrap" });
                var facebookProvider = new FacebookProvider("a", "b", new Uri("http://www.google.com"),
                                                            mockWebClientWrapper.Object);
                var facebookClient = new FacebookClient
                {
                    Code = "aa",
                    State = "bb"
                };

                // Act.
                var result = Assert.Throws<InvalidOperationException>(() => facebookProvider.RetrieveAccessToken(facebookClient));

                // Assert.
                Assert.NotNull(result);
                Assert.Equal("Failed to deserialize the json user information result from Facebook.", result.Message);
            }