13

I have an intranet project written in MVC 4 which uses Windows Authentication to authorise and authenticate users.

I need to add a 'Login as another user' functionality.

After some searching I found this solution which suggests returning a 401, and created the following Action (which is called using a form):

    // 
    // POST: /Home/LogOut

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOut()
    {
        return new HttpUnauthorizedResult();
    }

The Action gets called, and the browser pops up a username and password window, however as the result redirects back to the Action, a 401 is always returned.

How do I redirect the user back to the previous action, once they have logged in with the new credentials?

Is there a way to invalidate the credentials on the server side instead of just returning a 401?

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Darbio
  • 11,286
  • 12
  • 60
  • 100
  • 1
    Maybe you should consider passing return url argument to the LogOut method, then manually logout user and redirect to logon with this return url? – Robert Skarżycki Jul 26 '13 at 06:50
  • How do you 'manually logout a user' when using Windows Authentication? All the solutions I have found require a 403 response to be sent to the browser which results in a credentials box being shown. – Darbio Jul 28 '13 at 12:05
  • Sorry, I've missed that You talk about WinAuth, not about FormsAuth. The only solution I found - but not tested it - is to log out through javascript: http://stackoverflow.com/questions/1067263/asp-net-windows-authentication-logout (I mean pass return url to the special logpout page with javascript logout function as above called on load, and then redirect - using windows.location JS object - user to the page determined by returnurl argument from querystring. – Robert Skarżycki Jul 29 '13 at 06:42
  • Thanks Rob - I will give that a go and let you know if it works. – Darbio Jul 29 '13 at 07:29
  • @Macropus Did you have any luck with this? Currently trying the same thing and the javascript option gives mixed results on different browsers. – Stephen Sep 12 '13 at 13:12
  • Nope not had any luck with this yet - though it is such a small feature that I haven't revisited for a while. I will report back if I find an answer. – Darbio Sep 13 '13 at 06:13
  • http://forums.iis.net/t/1162665.aspx?Login+as+different+user+in+asp+net+as+in+share+point – JohnLBevan Apr 05 '14 at 12:21
  • It's not really a solution, but as info for the benefit of searchers, the windows auth seems to be reset on close of the browser (tested chrome, March 2017) – JsAndDotNet Mar 24 '17 at 10:48

3 Answers3

25

People reverse engineered\decompiled some code from Sharepoint that happens to have this feature.

I tested it in an ASP.NET MVC 5 app and it's working as expected.

The code is based on decompiling the Microsoft.TeamFoundation.WebAccess which has the "Sign in as a different User" function.

public ActionResult LogOut()
{
    HttpCookie cookie = Request.Cookies["TSWA-Last-User"];

    if(User.Identity.IsAuthenticated == false || cookie == null || StringComparer.OrdinalIgnoreCase.Equals(User.Identity.Name, cookie.Value))
    {
        string name = string.Empty;

        if(Request.IsAuthenticated)
        {
            name = User.Identity.Name;
        }

        cookie = new HttpCookie("TSWA-Last-User", name);
        Response.Cookies.Set(cookie);

        Response.AppendHeader("Connection", "close");
        Response.StatusCode = 401; // Unauthorized;
        Response.Clear();
        //should probably do a redirect here to the unauthorized/failed login page
        //if you know how to do this, please tap it on the comments below
        Response.Write("Unauthorized. Reload the page to try again...");
        Response.End();

        return RedirectToAction("Index");
    }

    cookie = new HttpCookie("TSWA-Last-User", string.Empty)
    {
        Expires = DateTime.Now.AddYears(-5)
    };

    Response.Cookies.Set(cookie);

    return RedirectToAction("Index");

}

Source:

Force Sign in as a different user while using Windows Authentication in asp.net

ForestPhoenix
  • 155
  • 2
  • 9
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
  • And how do we redirect to another action? – Zeshan Munir Nov 01 '16 at 09:55
  • In my experience, this will not work when testing the code through the **Visual Studio IDE and localhost**. You'll be able to change the user only once. After that, the credentials are not handled properly and are never accepted. After 3 attempts, the standard 401 page is displayed. The only way to reset is to close/reopen the browser. – TLS Jun 23 '17 at 12:07
  • I also noticed an exception thrown with this code. We're not supposed to redirect after a Header has been added to the response. Because the redirect is stopped, the code works. An alternative to setting the header and status code and manually ending the Response is to simply call `Return New HttpUnauthorizedResult("Unauthorized")`. This is also more "MVC-ish" in my opinion. Rather than manipulating the Response directly, let the return value from the Action do the job. – TLS Jun 23 '17 at 12:12
0

This method will always log the user out and redirect to the home page. I also added [AllowAnonymous] to make sure everybody can access this method.

    [AllowAnonymous]
    public ActionResult LogOut()
    {
        HttpCookie cookie = Request.Cookies["TSWA-Last-User"];

        cookie = new HttpCookie("TSWA-Last-User", string.Empty)
        {
            Expires = DateTime.Now.AddYears(-5)
        };
        Response.Cookies.Set(cookie);

        Response.AppendHeader("Connection", "close");
        Response.StatusCode = 401; // Unauthorized;
        Response.Clear();

        // redirect to home
        Response.Write("<script type='text/javascript'>");
        Response.Write("var getUrl = window.location; var baseUrl = getUrl.protocol + " + 
           "'//' + getUrl.host + '/' + getUrl.pathname.split('/')[1]; window.location.href = baseUrl; ");
        Response.Write("</script>");
        Response.End();           

        return RedirectToAction("Index");

    }
  • after adding the above function into my code, windows authentication window is coming again and again, even after providing correct credentials. – Sonali Oct 04 '17 at 11:01
  • Hi @Sonali, I will look at the code in about 2 - 3 hours and will try to find a solution. – Random Stranger Oct 05 '17 at 11:48
  • this happening because I am trying to login with same user again and again. After trying new user, it worked fine. – Sonali Oct 05 '17 at 11:50
0

For me, working this:

 public ActionResult LogOut()
{
    HttpCookie cookie = Request.Cookies["TSWA-Last-User"];

if(User.Identity.IsAuthenticated == false || cookie == null
{
    string name = string.Empty;

    if(Request.IsAuthenticated)
    {
        name = User.Identity.Name;
    }

    cookie = new HttpCookie("TSWA-Last-User", name);
    Response.Cookies.Set(cookie);

    Response.AppendHeader("Connection", "close");
    Response.StatusCode = 401; // Unauthorized;
    Response.Clear();
    //should probably do a redirect here to the unauthorized/failed login page
    //if you know how to do this, please tap it on the comments below
    Response.Write("Unauthorized. Reload the page to try again...");
    Response.End();

    return RedirectToAction("Index");
}

cookie = new HttpCookie("TSWA-Last-User", string.Empty)
{
    Expires = DateTime.Now.AddYears(-5)
};

Response.Cookies.Set(cookie);

return RedirectToAction("Index");

}

And in html

   <a href="@Url.Action("LogOut", "Home")" class="logout"><i class="fa fa-fw fa-power-off"></i> Salir</a>

   $(".logout").click(function () {
            logOut();
        });


    function logOut() {
        try {
            document.execCommand("ClearAuthenticationCache");
        } catch (e) { }
    }
Mario Villanueva
  • 327
  • 3
  • 10