Search code examples
asp.net-mvcasp.net-identityforms-authentication

FormsAuthentication with MVC5


In MVC5 ASP.Identity replaces old form authentication. However as per the discussion here A type of FormsAuthentication still exists though. According to Microsoft,

But i also found Microsoft.Owin.Security.Forms library is also deprecated (check this nuget link)

What are my options here if i want to use ASP.NET MVC5 and i want to store userid & password in SQL table ( eg aspnet_users & aspnet_membership SQL tables) ( this should be a quick temporary solution until we move to new OpenIdConnect)


Solution

  • ASP.NET Identity does support cookie based authentication out of the box, allowing you to store logins in DB and having a "forms authentication like" mechanism. Default tables schema are not the same than with membership, but it is customizable.

    Bootstrapping sample:

    [assembly: OwinStartup(typeof(YourNamespace.Startup))]
    namespace YourNamespace
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                var options = GetCookieOptions();
                app.UseCookieAuthentication(options);
            }
    
            public static CookieAuthenticationOptions GetCookieOptions()
            {
                var options = new CookieAuthenticationOptions
                {
                    AuthenticationType = 
                        DefaultAuthenticationTypes.ApplicationCookie,
                    SlidingExpiration = true,
    
                    // On ajax calls, better have a 401 rather than a redirect
                    // to an HTML login page.
                    // Taken from http://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/
                    Provider = new CookieAuthenticationProvider
                    {
                        OnApplyRedirect = ctx =>
                        {
                            if (!IsAjaxRequest(ctx.Request))
                            {
                                // Patching by the way the absolute uri using http
                                // instead of https, when we are behind a lb
                                // terminating the https: returning only
                                // PathAndQuery
                                ctx.Response.Redirect(new Uri(ctx.RedirectUri)
                                    .PathAndQuery);
                            }
                        }
                    }
                };
    
                if (!string.IsNullOrEmpty(Settings.Default.LoginPath))
                    options.LoginPath = new PathString(Settings.Default.LoginPath);
                if (!string.IsNullOrEmpty(Settings.Default.AuthCookieName))
                    options.CookieName = Settings.Default.AuthCookieName;
                if (!string.IsNullOrEmpty(Settings.Default.AuthCookieDomain))
                    options.CookieDomain = Settings.Default.AuthCookieDomain;
                if (Settings.Default.ForceSecuredCookie)
                    options.CookieSecure = CookieSecureOption.Always;
                return options;
            }
    
            // Taken from http://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/
            private static bool IsAjaxRequest(IOwinRequest request)
            {
                var query = request.Query;
                if (query != null && StringComparer.OrdinalIgnoreCase.Equals(
                    query["X-Requested-With"], "XMLHttpRequest"))
                    return true;
                var headers = request.Headers;
                return headers != null && StringComparer.OrdinalIgnoreCase.Equals(
                    headers["X-Requested-With"], "XMLHttpRequest");
            }
        }
    }
    

    (Settings.Default. are custom configuration properties of the project in those sample.)

    sign-in, sign-out sample:

    UserManager<IdentityUser> yourUserManager;
    
    public bool SignIn(string login, string password, bool rememberMe)
    {
        var user = yourUserManager.Find(userName, password);
        if (user == null)
            return false;
        var expiration = rememberMe ?
            Settings.Default.PermanentAuthCookieExpiration : 
            Settings.Default.AuthCookieExpiration;
    
        var authenticationManager = 
            HttpContext.Current.GetOwinContext().Authentication;
    
        var claimsIdentity = yourUserManager.CreateIdentity(user,
            DefaultAuthenticationTypes.ApplicationCookie);
        authenticationManager.SignIn(
            new AuthenticationProperties
            {
                AllowRefresh = true,
                IssuedUtc = DateTime.UtcNow,
                ExpiresUtc = DateTime.UtcNow.AddMinutes(expiration),
                IsPersistent = rememberMe
            }, claimsIdentity);
        return true;
    }
    
    public void IIdentityUserManager.SignOut()
    {
        var authenticationManager = 
            HttpContext.Current.GetOwinContext().Authentication;
        authenticationManager.SignOut();
    }
    

    And of course, with MVC, use AuthorizeAttribute as a global filter along with [AllowAnonymous] on actions which do not require authorization.