Redirect in Controller after Authentication

Vote:
 

Hi folks,

We have a custom login page in place, quite similar to this one here.

We would like to redirect users to the backend, to be precise to "/EPiServer/CMS".

Currently, the code in the CustomLoginController looks like this:

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        [ValidateInput(false)]
        public ActionResult LocalLogin(CustomLoginViewModel model)
        {
            if (ModelState.IsValid)
            {
                bool result = uiSignInManager.SignIn(uiUserProvider.Name, model.Username, model.Password);

                if (result)
                {
                    return Redirect(UrlResolver.Current.GetUrl(ContentReference.StartPage));
                }
            }

            ModelState.AddModelError("LoginError", "Login failed");

            return View(Global.CustomLoginView, model);
        }

So we tried different things here to actually redirect to the backend but whatever we do we always get redirected to the StartPage / index page. Things we have tried:

return Redirect(UrlResolver.Current.GetUrl("/EPiServer/CMS"));

return Redirect("/EPiServer/CMS");

//Even those two get ignored and users get redirected to the StartPage

return Redirect("WHATEVER");

return Redirect("http://www.google.com");

Any ideas what we are doing wrong?

Best regards,

Patrick

#196619
Sep 05, 2018 16:58
Vote:
 

Sounds strange, can you post a version of the full code that still redirects to start page but shouldn't?

When I tested it worked fine redirecting to /episerver/cms using this test code:

Action:

[HttpPost]
public ActionResult TestRedirect()
{
    return Redirect("/episerver/cms");
}

View:

<div>
    @using (Html.BeginForm("TestRedirect", "Test", FormMethod.Post))
    {
        <button type="submit">Test</button>
    }
</div>

(I'm already logged in when doing this, but the outcome should be the same regardless of when you login the user.)

#196634
Edited, Sep 05, 2018 23:38
Vote:
 

Here is the full monty.

View:

    <div class="modal">
            @using (Html.BeginForm("LocalLogin", "CustomLogin", FormMethod.Post))
            {
                @Html.AntiForgeryToken()

                <ol class="clearfix">
                    <li>
                        <img src="/util/images/login/DXC_long.svg" alt="logo" class="logo" />
                    </li>
                    <li>
                        <div class="validation-summary text--error">
                            @Html.ValidationSummary()
                        </div>
                    </li>
                    <li>
                        @Html.LabelFor(x => x.Username)
                        @Html.TextBoxFor(x => x.Username)
                    </li>
                    <li>
                        @Html.LabelFor(x => x.Password)
                        @Html.PasswordFor(x => x.Password)
                    </li>
                    <li>
                        <input type="submit" value="Log in" class="epi-button-child-item" />
                    </li>
                    <li>
                        <p class="text--small">
                            <a "#" onclick="toggleCookieText(); return false;">
                                When you log in, cookies will be used.
                            </a>
                        </p>
                        <div id="cookieInfoPanel" class="cookie-information">
                            <p class="text--small">
                                A cookie containing login information will be sent to your web browser. If you do not want to receive cookies, you will be unable to log into the website.
                            </p>
                        </div>
                    </li>
                </ol>
            }
        </div>

Controller:

namespace A1Digital.Site.Controllers
{
    public class CustomLoginController : Controller
    {
        private UISignInManager uiSignInManager = ServiceLocator.Current.GetInstance<UISignInManager>();
        private UIUserProvider uiUserProvider = ServiceLocator.Current.GetInstance<UIUserProvider>();

        public ActionResult Index()
        {
            return View(Global.CustomLoginView);
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        [ValidateInput(false)]
        public ActionResult LocalLogin(CustomLoginViewModel model)
        {
            if (ModelState.IsValid)
            {
                bool result = uiSignInManager.SignIn(uiUserProvider.Name, model.Username, model.Password);

                if (result)
                {
                    return Redirect("/EPiServer/CMS");
                }
            }

            ModelState.AddModelError("LoginError", "Login failed");

            return View(Global.CustomLoginView, model);
        }
    }
}

Moreover, when taking a look at the network tab in the browsers console, the request points correctly to "/CustomLogin/LocalLogin" with a HTTP Status Code of "302 - Found", but the "Location" header of the response is "/".

#196654
Sep 06, 2018 10:26
Vote:
 

If you manually visit "/episerver" after being redirected to "/", is your user considered to be logged in?

Do you have an <authentication>-element in your web.config? If you have one, what does it look like?

#196659
Sep 06, 2018 12:43
Vote:
 

Yes, after the user is redirected to "/" he can even see the orange EPiServer menu in the upper right corner and can access the backend.

That's what the <authentication>-element looks like in our web.config:

    <authentication mode="None">
    </authentication>
#196660
Sep 06, 2018 13:16
Vote:
 

Does this happen in a specific environment?

Can you test what happens if you use the basic redirect code I posted above? You can first login (for example through "/Util/Login.aspx").

#196668
Sep 06, 2018 15:04
Vote:
 

So far I have only tested this on my local machine (we have the DXC subscription).

Interestingly your code works. When clicking the "Test" button, I get redirected to /episerver/cms.

#196727
Sep 10, 2018 14:10
Vote:
 

probably late to the party and not sure if it's related, but looking at `EPiServer.Cms.UI.AspNetIdentity.ApplicationUISignInManager<TUser>` you can see that it does redirect on its own.

public override bool SignIn(string providerName, string userName, string password)
{
  string returnUrl = this.GetReturnUrl();
  if (!this._signInManager().SignIn(userName, password, returnUrl))
    return false;
  this.Redirect(returnUrl);
  return true;
}

and there is custom redirect method in that manager:

protected virtual void Redirect(string returnUrl)
{
  HttpContext current = HttpContext.Current;
  if (current == null)
    return;
  if (string.IsNullOrWhiteSpace(returnUrl))
    return;
  try
  {
    current.Response.Redirect(VirtualPathUtility.ToAbsolute(returnUrl), false);
    current.ApplicationInstance.CompleteRequest();
    current.Response.End();
  }
  catch (ThreadAbortException ex)
  {
  }
}

NB! note `currect.Response.End()` method..

and redirect url is standard aspnet query string (if present) - "?ReturnUrl=..". you can give it a try and test login process with custom redirect url just to make sure that this signin manager is not messing things up.

#196756
Sep 11, 2018 7:35
Vote:
 

I just tried to login with the ReturnUrl parameter like "/CustomLogin?ReturnUrl=%2Fepiserver%2Fcms" but again simply got redirected to "/" undecided

#196764
Sep 11, 2018 10:04
Vote:
 

it might be lost during post back to the controller maybe?

#196765
Sep 11, 2018 10:15
Vote:
 

Is there a way to find this out?

#196812
Sep 12, 2018 9:53
Vote:
 

can you add what request is being posted to the controller (can capture network traffic in dev tools for instance)?

#196947
Sep 18, 2018 9:25
Vote:
 

LoginNetworkRequest

#196949
Sep 18, 2018 10:13
Vote:
 

the login page is really a custom one (and just looks like built-in) or you use default epi login page?

#196952
Sep 18, 2018 10:47
Vote:
 

Yes, this is actually a custom login page and just looks like the OOTB login page (for now ^^).

#196967
Sep 18, 2018 15:29
Vote:
 

ok, and custom login page form containing action with "ReturnUrl" query string?

#196975
Sep 18, 2018 20:45
Vote:
 

You can check the view here.

#196987
Edited, Sep 19, 2018 9:06
Vote:
 
@using (Html.BeginForm("LocalLogin", "CustomLogin", new { ReturnUrl = "http://takemehome.com" }, FormMethod.Post))

?

#197026
Sep 19, 2018 15:25
Vote:
 

Hello again Patrick!

I started setting up a project of my own which makes use of ASP.NET Identity. After I set it up I decided to take a proper look at solving this issue.

It was indeed the absence of ReturnUrl that caused it. The solution to this that I came up with can be found here:

https://world.episerver.com/blogs/jafet-valdez/dates/2018/9/curing-your-redirect-woes-when-using-uisigninmanager-signin/

The solution doesn't require you to set a ReturnUrl at all (if you don't want to) and it also enables you to use your OWIN configuration file to specify a redirect location when users sign in.

Hope this helps!

Thanks a lot @Valdis for pointing us in the right direction!

#197042
Edited, Sep 20, 2018 1:23
Vote:
 

Thanks guys, with your help I was able to resolve the issue! cool

#197055
Sep 20, 2018 10:58
Vote:
 

ah, nice. great success! I was lazy enough not to provide complete solution ;)

#197061
Sep 20, 2018 14:16
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.