Search code examples
c#model-view-controllerformsauthentication

Using formsauthentication for login and use HttpContext.Current.User.Identity


I have made a website with a page that includes a razor form. The user can login on this form and then redirects to a different page. The logging in (and logging out) works with formsauthentication succesfully. However, I can't seem to use HttpContext.Current.User.Identity.Name to retrieve the stored username (in the formsauthentication cookie). It returns an empty string "".

I am using MVC 5 and ASP 4.5 with no standard membership or role providers.

Login:

 [HttpPost]
        public ActionResult Login(User user)
        {
            if (ModelState.IsValid)
            {
                bool authenticated = userscontroller.isAuthorized(user.Email, user.Password);
                if (authenticated)
                {
                    if (userscontroller.isAuthenticated())
                    {
                        userscontroller.deAuthenticateUser();
                    }
                    userscontroller.authenticateUser(user);
                    return Redirect(Url.Action("Index", "Home"));
                }
            }
        }

Authenticating the user:

 public void authenticateUser(User user)
    {
        FormsAuthentication.SetAuthCookie(user.Username, false);
    }

Then getting the name of the user:

public User userFromCookie()
{
    if (isAuthenticated())
    {
        return getUserByUsername(HttpContext.Current.User.Identity.Name);
    }
    else { return null; }
}

isauthenticated()

public bool isAuthenticated()
{
    if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
    {
        return true;
    }
    else
    {
        return false;
    }
}

Webconfig:

<authentication mode="Forms">
  <forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
 <authorization > <deny users="?"/> </authorization>

So the identity.name returns "".

Help is appreciated!


Solution

  • Possible reasons it does not work.

    1. You are just calling it wrong. Try this.User.Identity.Name
    2. The cookie is not being persisted in the Response object so the user is actually not authenticated in the next request.
    3. You do not have your web.config configured to make use of forms authentication with cookies.

    Here is a fully working example I created for you. This whole thing works, the only dependency is on a Newtonsoft library but you could remove that and put anything you want in the user data.

    Here is the user controller

    using System;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Security;
    
    namespace TestAuth.Controllers
    {
        public class UserModel
        {
            public string UserName { get; set; }
            public string Password { get; set; }
            public bool RememberMe { get; set; }
        }
    
        public class UserInfo
        {
            public string UserName { get; set; }
        }
    
        public class UserController : Controller
        {
            [AllowAnonymous]
            public ActionResult Login()
            {
                var model = new UserModel() {Password = "password",UserName = "ItsMe", RememberMe = true};
                var serializedUser = Newtonsoft.Json.JsonConvert.SerializeObject(model);
    
                var ticket = new FormsAuthenticationTicket(1, model.UserName, DateTime.Now, DateTime.Now.AddHours(3), model.RememberMe, serializedUser);
                var encryptedTicket = FormsAuthentication.Encrypt(ticket);
                var isSsl = Request.IsSecureConnection; // if we are running in SSL mode then make the cookie secure only
    
                var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
                {
                    HttpOnly = true, // always set this to true!
                    Secure = isSsl,
                };
    
                if (model.RememberMe) // if the user needs to persist the cookie. Otherwise it is a session cookie
                    cookie.Expires = DateTime.Today.AddMonths(3); // currently hard coded to 3 months in the future
    
                Response.Cookies.Set(cookie);
    
                return View(); // return something
            }
    
            [Authorize]
            public ActionResult ShowUserName()
            {
                return View(new UserInfo() {UserName = this.User.Identity.Name});
            }
        }
    }
    

    Here are the views. View Login.cshtml

    Logged in
    <br/>
    
    @Html.ActionLink("Show the user their name", "ShowUserName", "User")
    

    View ShowUserName.cshtml

    @model TestAuth.Controllers.UserInfo
    
    <h2>title</h2>
    user name = @Model.UserName
    

    web.config section Note that the key was generated from some web site that came up in a google search. You should probably look into getting your own and with the correct encryption types as the site I used was somewhat dated.

      <system.web>
            <authentication mode="Forms">
                <forms name="myAuthCookie" ticketCompatibilityMode="Framework40" cookieless="UseCookies" requireSSL="false" timeout="180" protection="Encryption" />
            </authentication>
            <machineKey
      validationKey="DA87693F33607268657E61BCF16D2EAFE339ECE0F6C9B94DFA0FE5BBCA0035EB320F81662A32D98F0A0D2A5DCBE3E678EDF216FBD45CB8BD6F13489D1548214C"
      decryptionKey="26F44FEF28C3466FAB261CEF4844535678578C6658F85C6ADAE17A99B0947468"
      validation="SHA1" decryption="AES"/>
    
    
            <compilation debug="true" targetFramework="4.6"/>
        <httpRuntime targetFramework="4.6"/>
      </system.web>