Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does redirect to returnUrl work in Asp.Net MVC5

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

like image 999
Ola Karlsson Avatar asked Dec 17 '13 08:12

Ola Karlsson


People also ask

How does redirect to action work?

The RedirectToAction() Method This method is used to redirect to specified action instead of rendering the HTML. In this case, the browser receives the redirect notification and make a new request for the specified action. This acts just like as Response.

How we can redirect to another page or controller?

Redirect() method The first method od redirecting from one URL to another is Redirect(). The Rediect() method is available to your controller from the ControllerBase class. It accepts a target URL where you would like to go.

How can I redirect to another page in asp net MVC 5?

Use RedirectToActionResult in ASP.NET Core MVC This action result can be used to redirect to the specified action and controller. If no controller is specified it redirects to the specified action within the current controller.

How do I redirect to an action in ASP NET MVC?

RedirectToAction(String, String, RouteValueDictionary) Redirects to the specified action using the action name, controller name, and route values.


2 Answers

You need to check if the url is local indeed using this method (it is not handled by the framework automatically): http://msdn.microsoft.com/en-us/library/system.web.mvc.urlhelper.islocalurl%28v=vs.118%29.aspx

if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
{
  return Redirect(returnUrl);
}
like image 190
Marthijn Avatar answered Oct 03 '22 05:10

Marthijn


As Sandeep Phadke told, the returnUrl Parameter is filled, because of configuration in startup.Auth.cs.

The CookieAuthenticationOptions has a property ReturnUrlParameter which is by Default set to "returnUrl". That is the reason, why it looks like magic. You can Change it to whatever you want:

app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        ReturnUrlParameter = "returnTo"
    });

Then you can Change the AccountController Login-Action to:

[AllowAnonymous]
    public ActionResult Login(string returnTo)
    {
        ViewBag.ReturnUrl = returnTo;
        return View();
    } 
like image 22
Kirsten Avatar answered Oct 03 '22 04:10

Kirsten