How does redirect to returnUrl work in Asp.Net MVC5

Viewed 41021

I've started a new MVC 5 site, using the new Asp.Net Identity with Owin. In my "account" controller which has the attribute [Authorize], I have fairly standard actions;

   // GET: /User/Login
        [AllowAnonymous]
        public ActionResult Login(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            return View();
        } 

// POST: /User/Login
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    var userApi = new UserService();
                    var apiUser = await userApi.LogIn(UserManager, model.CardNumber, model.Pin, model.RememberMe);

                    if (apiUser != null)
                    {
                        await SignInAsync(apiUser, model.RememberMe);
                        if (string.IsNullOrEmpty(returnUrl))
                        {                                   
                            return RedirectToAction("UserLoggedIn", "User");    
                        }
                    }
                    else
                    {
                        ModelState.AddModelError("", "Invalid username or password.");
                    }
                }

            }
            catch (Exception ex)
            {
                Trace.TraceError("Cannot login {0}", ex.ToString());
                Response.AppendToLog(ex.ToString());
                ModelState.AddModelError("", ex.ToString());
            }
            // If we got this far, something failed, redisplay form
            return View(model);
        }

My question is in regards to the returnUrl behavior, the code above works in the sense that, if a user is not logged in and calls a action in a controller that has the attribute [Authorize], it gets sent to the login actions above and then returned to the controller/action that was requested. Which is great, BUT how?? And is it safe?

In this article about "Preventing open redirect attacks"(for earlier versions of Asp.Net MVC) the recommendation is to do a check on the returnUrl that it's a local url before doing the redirect, is that something I should still do or is it now handled by the framework?

Cheers, Ola

4 Answers
Related