Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why the duplicate returnUrl redirect logic in asp.net web applications with owin / identity?

When you create a new web application (either webforms or mvc) in visual studio, there is post-authentication logic that checks for a ReturnUrl param in the query string, and then redirects the user there if it exists: In weforms - Login.aspx.cs you have this:

protected void LogIn(object sender, EventArgs e)
{
   ...
        switch (result)
        {
            case SignInStatus.Success:
                IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
                break;
            ...
        }
    }
}

In MVC - AccountController.cs you have this:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
   ...
    switch (result)
    {
        case SignInStatus.Success:
            return RedirectToLocal(returnUrl);
        ...
    }
}

Now in addition, the Owin configuration is setup to use cookie authentication, which uses the Microsoft.Owin.Security.Cookies.CookieAuthenticationHandler class, which itself checks for a ReturnUrl parameter, and applies a redirect if it exists:

protected override async Task ApplyResponseGrantAsync()
{
    AuthenticationResponseGrant signin = Helper.LookupSignIn(Options.AuthenticationType);
    bool shouldSignin = signin != null;
    AuthenticationResponseRevoke signout = Helper.LookupSignOut(Options.AuthenticationType, Options.AuthenticationMode);
    bool shouldSignout = signout != null;

    if (shouldSignin || shouldSignout || _shouldRenew)
    {
        ...

        if ((shouldLoginRedirect || shouldLogoutRedirect) && Response.StatusCode == 200)
        {
            IReadableStringCollection query = Request.Query;
            string redirectUri = query.Get(Options.ReturnUrlParameter);
            if (!string.IsNullOrWhiteSpace(redirectUri)
                && IsHostRelative(redirectUri))
            {
                var redirectContext = new CookieApplyRedirectContext(Context, Options, redirectUri);
                Options.Provider.ApplyRedirect(redirectContext);
            }
        }
    }
}

Both redirects appear to execute during the login/authentication request. One is applied on the HttpContext.Response, and the other applied on the Owin redirect context. In my experience, it looks like the latter redirect call wins, which is a problem if you have special redirect logic applied post-login in your website code because it gets overridden by the built-in Owin redirect.

Is there a good reason for this duplicate logic? Is this just poor design? So if I'm using asp.net Owin CookieAuthentication, should I have post-login redirect code logic on account controller or aspx code behind? And if so, should the redirect be applied on the HttpContext.Response or through Owin somehow?

like image 278
Rafe Avatar asked Dec 03 '14 19:12

Rafe


People also ask

What is Owin identity?

OWIN includes middleware components for authentication, including support for log-ins using external identity providers (like Microsoft Accounts, Facebook, Google, Twitter), and log-ins using organizational accounts from on-premises Active Directory or Azure Active Directory.

What is redirecttoroute method in ASP NET Core?

The RedirectToRoute method is yet another redirection method that is used to redirect a request in ASP.NET Core from one URL to another. This can be used to redirect based on some condition. The method is part of the Controllerbase class so it’s directly available for use in the controller class.

What is returnURL in ASP NET Core?

What is returnUrl? If an un-authenticated user tries to access a page, then ASP.NET Core redirects him to the login page - and at the same time stores the returnUrl in a query string parameter. returnUrl is null if the user comes directly from the login page.

How do I get the return url when redirecting a page?

ASP.NET automatically adds the return URL when the browser is redirected to the login page. By default, the ReturnUrl variable must refer to a page within the current application. If ReturnUrl refers to a page in a different application or on a different server, the GetRedirectUrl methods returns the URL in the DefaultUrl property.

What is localredirect method in ASP NET Core?

The LocalRedirect method is similar to the Redirect method in that it is used to redirect a request in ASP.NET Core from one URL to another. This can be used to redirect based on some condition. The method is part of the Controllerbase class so it’s directly available for use in the controller class.


1 Answers

As you said, these three ways to redirect all belong to different parts: WebForms, MVC, OWIN. Each one of them can be used independently from the other (OWIN in self-hosting situation), so there is a need to do the same thing in each and every one of them.

However I'm not entirely sure why latest MVC template needs RedirectToLocal. I'd go with the backward compatibility - this method been there for ages.

Also the OWIN redirect does not win in MVC - in one of my apps, I always redirect user depending on their role, even if there is a parameter with local URL to go to, my users always end up on the page specified in MVC controller.
However, having looked therough OWIN source code and the redirecting logic, it seems strange that MVC wins. Probably need to step-through all the way down and see what happens in MVC scenario.

like image 153
trailmax Avatar answered Oct 20 '22 01:10

trailmax