Exemplo n.º 1
0
        public void Login_External_Using_Correct_Credentials()
        {
            Web.Models.User loginRequest = new Web.Models.User()
            {
                IsInternalUser = false,
                Password       = "******",
                UserName       = "******"
            };
            var loginResponse = _accountController.Login(loginRequest);

            Assert.IsNotNull(loginResponse);
            Assert.IsInstanceOfType(loginResponse, typeof(ViewResult));
        }
Exemplo n.º 2
0
        public ActionResult Login()
        {
            try
            {
                string error = Request["error"];
                if (!String.IsNullOrEmpty(error))
                {
                    ViewBag.ErrorMessage = Request["error_description"];
                }
                else
                {
                    string code = Request["code"];
                    // when we get redirected here by Forms Authentication we'll
                    // have a ReturnUrl indicating the page we came from
                    string returnUrl = Request.QueryString["ReturnUrl"];

                    if (String.IsNullOrEmpty(code))
                    {
                        // CSRF protection
                        var hashBytes = new MD5CryptoServiceProvider().ComputeHash(Guid.NewGuid().ToByteArray());
                        string state = Convert.ToBase64String(hashBytes);
                        Session["state"] = state;

                        // add the return Url to the state parameter so Facebook can send it all back to us
                        if (!String.IsNullOrEmpty(returnUrl))
                        {
                            state += returnUrl;
                        }

                        // good programmers encode strings before passing them to a query string
                        state = Url.Encode(state);

                        // don't forget to change the "scope" values listed below
                        // to something appropriate for your facebook application
                        // facebook warns not to get greedy as users may deny access
                        string redirectUrl = "http://www.facebook.com/dialog/oauth?client_id=" + AppId +
                                             "&redirect_uri=" +
                                             Url.Encode(AuthorizeUrl) +
                                             "&scope=publish_stream&state=" +
                                             state;
                        return Redirect(redirectUrl);
                    }

                    string sessionState = Convert.ToString(Session["state"]);
                    string requestState = Request.QueryString["state"];

                    if (!String.IsNullOrEmpty(requestState) &&
                        !String.IsNullOrEmpty(sessionState) &&
                        requestState.Length >= sessionState.Length &&
                        requestState.Substring(0, sessionState.Length) == sessionState)
                    {
                        string tokenUrl = "https://graph.facebook.com/oauth/access_token?client_id=" + AppId +
                                          "&redirect_uri=" + Url.Encode(AuthorizeUrl) +
                                          "&client_secret=" + AppSecret +
                                          "&code=" + code;
                        string response = GetPageContent(tokenUrl);

                        var responseDictionary = ParseQueryString(response);
                        if (responseDictionary.Contains("access_token"))
                        {
                            // note: you don't HAVE to respect this, as long as you
                            // get a new token before trying to use the FB API
                            double facebookTokenExpirationSeconds =
                                Convert.ToDouble(responseDictionary["expires"]);

                            // Note: you may want to store responseDictionary["access_token"] and
                            // facebookTokenExpirationSeconds somewhere so you can use it for other FB API requests
                            string graphUrl = "https://graph.facebook.com/me?access_token=" +
                                              responseDictionary["access_token"];

                            var serializer = new JavaScriptSerializer();
                            dynamic facebookUser = serializer.DeserializeObject(GetPageContent(graphUrl));

                            // grab facebook name and Id to use as our forms authentication ticket
                            string facebookName = facebookUser["name"];
                            long facebookUserId = Convert.ToInt64(facebookUser["id"]);

                            string facebookEmail = string.Empty;

                            // Extended permissions
                            try
                            {
                                facebookEmail = facebookUser["email"];
                            }
                            catch (KeyNotFoundException exception)
                            {
                                LogManager.GetCurrentClassLogger()
                                    .LogException(LogLevel.Warn, "email", exception);
                            }

                            // Create local user if first login
                            var user = RavenSession.Load<Web.Models.User>(facebookUserId);
                            if (user == null)
                            {
                                user = new Web.Models.User()
                                {
                                    Id = facebookUserId,
                                    Name = facebookName,
                                    Email = facebookEmail,
                                };

                                // Save user to user store
                                RavenSession.Store(user);

                                // Notify admin about new user.
                                TaskExecutor.ExcuteLater(new NewUserNotificationEmailTask(new NewUserRegisteredViewModel()
                                {
                                    Id = user.Id,
                                    Name = user.Name
                                }));
                            }
                            else
                            {
                                // Update potential name changes from fb
                                if (facebookName != user.Name)
                                {
                                    user.Name = facebookName;
                                    user.Email = facebookEmail;

                                    RavenSession.Store(user);
                                }
                            }

                            //string userData = serializer.Serialize(facebookName);

                            // get the cookie the way forms authentication would put it together.
                            //Note: I am using the facebookUserId as the "username" as it's guaranteed to be unique
                            var authCookie = FormsAuthentication.GetAuthCookie(facebookUserId.ToString(), true);
                            var ticket = FormsAuthentication.Decrypt(authCookie.Value);
                            // we want to change the expiration of our forms authentication cookie
                            // to match the token expiration date, but you can also use your own expiration
                            DateTime expiration = ticket.IssueDate.AddSeconds(facebookTokenExpirationSeconds);

                            var newTicket =
                                new FormsAuthenticationTicket(
                                    ticket.Version,
                                    ticket.Name,
                                    ticket.IssueDate,
                                    expiration,
                                    ticket.IsPersistent,
                                    facebookName);

                            // encrypt the cookie again
                            authCookie.Value = FormsAuthentication.Encrypt(newTicket);

                            // manually set it (instead of calling FormsAuthentication.SetAuthCookie)
                            Response.Cookies.Add(authCookie);

                            // If we added the Redirect Url to our 'state', grab it and redirect
                            if (requestState.Length > sessionState.Length)
                            {
                                returnUrl = requestState.Substring(sessionState.Length);
                                if (!String.IsNullOrEmpty(returnUrl))
                                {
                                    return Redirect(returnUrl);
                                }
                            }

                            // otherwise redirect back to Home or whatever your default page is
                            return RedirectToAction("Index", "Items");
                        }
                        else
                        {
                            ViewBag.ErrorMessage = "Facebook authorization replied with this invalid response: " +
                                response;
                        }

                    }
                    else
                    {
                        ViewBag.ErrorMessage =
                            "There is a problem with the redirect from Facebook. You may be a victim of CSRF.";
                    }
                }
            }
            catch (Exception ex)
            {
                ViewBag.ErrorMessage = "Login failed with this exception: " + ex.Message;

                LogManager.GetCurrentClassLogger()
                    .FatalException("Login failed with this exception: " + ex.Message, ex);
            }

            LogManager.GetCurrentClassLogger()
                    .Fatal("Facebook login encountered an error without a description.");

            ViewBag.ErrorMessage = "Facebook login encountered an error without a description.";

            return RedirectToAction("Index", "Home");
        }