0

There are many questions about custom authentication in ASP.NET, but none of them answers how to fully integrate it with ASP.NET mechanics. I want to make a web application for system which already exists and have users.

Let's create new ASP.NET MVC project. I choose "No authentication" to make it from scratch (because I need to read from custom tables, custom hashing function etc, so I'll go this way).

I'll use IIdentity and IPrincipal interfaces to carry logged in user in HttpContext.

public class Identity : IIdentity
{
    public Identity(string name)
    {
        Name = name;
        IsAuthenticated = true;
    }

    public string Name { get; private set; }

    public string AuthenticationType { get; set; }

    public bool IsAuthenticated { get; set; }
}

public class Principal : IPrincipal
{
    public Principal(string email)
    {
        Identity = new Identity(email);
    }

    public IIdentity Identity { get; private set; }

    public bool IsInRole(string role)
    {
        return false;
    }
}

I'll create SessionsController which will create and destroy Session. Session will contain Id of logged in user.

public class UserManager
{
    public bool Authenticate(WorkerDTO user, string password)
    {
        using (var context = new DatabaseContext())
        {
            var user = context.Users.SingleOrDefault(w => w.Email == user.Email);

            if (user != null)
            {
                // compute SHA512 of password with salt
                var hash = Hash(user.Password);

                if (user.HashPassword == hash)
                    return true;
            }

            return false;
        }
    }
}

public class SessionsController : Controller
{
    private IDatabaseManager _dbManager;
    private UserManager _userManager;

    public SessionsController(IDatabaseManager dbManager, UserManager userManager)
    {
        _dbManager = dbManager;
        _userManager = userManager;
    }

    [HttpGet]
    public ActionResult Login()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Login(UserLoginViewModel model)
    {
        var user = _dbManager.Give(new WorkerByEmail(model.Email));
        if(user != null && _userManager.Authenticate(user, model.Password))
        {
            // create session
            Session["UserId"] = worker.Id;
            // assign User property
            User = new Principal(worker.Email);

            return RedirectToAction("Index", "Home");
        }

        return RedirectToAction("New");
    }

    public ActionResult Logout()
    {
        Session.Remove("UserId");
        User = null;

        return View();
    }
}

Application won't remember that User = new Principal(worker.Email);. So, if I want to make use of sessions, I want to tell my ASP.NET application that User behind UserId carried by session (probably a cookie) each request is the logged in user. In Global.asax I have available events with reasonable names:

  • AuthenticateRequest
  • PostAuthenticateRequest.

Unfortunately, Session is unavailable in these events. How to make use of ASP.NET in my application? Maybe Session isn't the way to go?

Should I create new IPrincipal object and attach to User prop each request? And why User property isn't null at start? Should I set it to null on logout?

Jacek
  • 829
  • 12
  • 31
  • Session isn't the conventional way to go. Read up about Forms Authentication. This stores the user identity in an encrypted cookie that is totally independent of Session, which has a number of benefits, including the fact that the user identity is not lost when Session is lost, e.g. due to an application pool recycle when using in-memory Session. – Joe Oct 03 '17 at 06:39
  • As far as I know Session is pretty secure way to go in many web frameworks. Forms Authentication is module from ASP WebForms? – Jacek Oct 03 '17 at 06:41
  • Do **NOT** use `Session`. You create a `FormsAuthenticationTicket` and add it as a cookie. Refer [this answer](https://stackoverflow.com/questions/1064271/asp-net-mvc-set-custom-iidentity-or-iprincipal) for a typical example –  Oct 03 '17 at 06:58
  • Actually I want to use both session and cookie for better security – Jacek Oct 03 '17 at 07:10
  • `Session does not give you 'security'! And it can be recycled at any time so you could lose it anyway. Do not try and reinvent the wheel. –  Oct 03 '17 at 07:39
  • 1
    The fact you have custom tables and custom hashing functions is no reason to write authentication from scratch. The framework has ample extension points to hook into, to adapt to your system. I suggest you start from the built-in solutions and see where you get blocked and workaround from there. Rolling your own security is **always** a terrible idea. – MarioDS Oct 03 '17 at 09:10

0 Answers0