Skip to content

Cookie Authentication

txgz999 edited this page Jul 26, 2019 · 29 revisions

Cookie authentication is similar to forms authentication, but it can be used by OWIN applications. As an example, we create an ASP.NET web application with MVC template, then

  • install package Microsoft.Owin.Host.SystemWeb
  • install package Microsoft.Owin.Security.Cookies
  • create Startup.cs
public class Startup {
    public void Configuration(IAppBuilder app) {
        ConfigureOAuth(app);
    }
    public void ConfigureOAuth(IAppBuilder app) {
        app.UseCookieAuthentication(new CookieAuthenticationOptions {
            AuthenticationType = "AppCookie",
            LoginPath = new PathString("/Home/Login"),
        });
    }
}
  • create a login form, first create the action methods in the Home controller:
public class HomeController : Controller {
    [HttpGet]
    public ActionResult Login() {
        return View();
    }

    [HttpPost]
    public ActionResult Login(LoginModel model) {
        if (model.UserName == "test" && model.Password == "test") {
            var claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.Name, model.UserName));
            var id = new ClaimsIdentity(claims, "AppCookie");
            var ctx = Request.GetOwinContext();
            var authenticationManager = ctx.Authentication;
            authenticationManager.SignIn(id);
            return RedirectToAction("Index", "Home");
        }
        return View(model);
    }

    [Authorize]
    public ActionResult Index() {
        return View();
    }
}

Notice that I have added the Authorize decorator to the Index page, so if the user has not logged in yet, the application would take the user to the Login page when he tries to access the home page.

  • and the corresponding view
<h2>Login</h2>
@using (Html.BeginForm("Login", "Home", FormMethod.Post)) {
    @Html.ValidationSummary(true)
  <fieldset>
    @Html.LabelFor(m => m.UserName):
    @Html.TextBoxFor(m => m.UserName)
    <br />
    @Html.LabelFor(m => m.Password):
    @Html.TextBoxFor(m => m.Password)
    <br />
    <input type="submit" value="Submit" />
  </fieldset>
}
  • LoginModel class is defined as
public class LoginModel {
    public string UserName { get; set; }
    public string Password { get; set; }
}
  • then we want to show the current login status by adding the following to _Layout.cshtml
    @User.Identity.Name

Notice that I hard code the AuthenticationType value. It can be any value, as long as the Startup class and the Login method use the same value. Some sample uses the value DefaultAuthenticationTypes.ApplicationCookie, which is the constant ApplicationCookie, but in order to use it we have to install the package Microsoft.AspNet.Identity.Core. That value determines the cookie name (.AspNet.<AuthenticationType>).

Cookie authentication is not related to OAuth, thus the package Microsoft.Owin.Security.OAuth is not needed. In a sense, Microsoft.Owin.Security.Cookies plays a similar role.

Share Cookie Authentication

Cookie can possibly be shared by all applications running on the same domain (e.g. http://www.xyz.com/test1, http://www.xyz.com/test2, http://www.xyz.com:3000). But in order for each application to share the authentication cookie, all we need is to make them to use the same machine key, see https://www.dotnetexpertguide.com/2016/11/sharing-owin-authentication-cookie-across-iis-applications.html.

Say, the example above runs at http://localhost:4000, then I can create a second ASP.NET web application using the WebForm template and running at http://localhost:4001 and is setup as follows:

  • install package Microsoft.Owin.Host.SystemWeb
  • install package Microsoft.Owin.Security.Cookies
  • create Startup.cs
public class Startup {
    public void Configuration(IAppBuilder app) {
        ConfigureOAuth(app);
    }
    public void ConfigureOAuth(IAppBuilder app) {
        app.UseCookieAuthentication(new CookieAuthenticationOptions {
            AuthenticationType = "AppCookie",
        });
    }
}
  • add the following to Default.aspx:
<%=User.Identity.Name %>
  • add a common machineKey to the system.web section of the web.config file in both applications, e.g.
<machineKey decryptionKey="85F7ABF05FD7713140FB4A6E1A402F68FDCC0330CED20080" validationKey="BA4C9F70AB3AC0A6CB2AF7753982378244269374CDE3C5A7BA07F78583CF882551D5144C4425D10C05AA96701AA1A0680E318DD99C4D14AAB4A780E0783E60D0" />  

Then once I login from the first application, then navigate to the second application, my user name appears on the page.

  • To get the claims, we can have code like the following in The Default.aspx.cs:
protected void Page_Load(object sender, EventArgs e) {
     var ctx = Request.GetOwinContext();
     var user = ctx.Authentication.User;
     var claims = user.Claims;
}

I also tested a ASP.NET WebApi application, with the following setup:

  • install package Microsoft.Owin.Host.SystemWeb
  • install package Microsoft.Owin.Security.Cookies
  • create Startup.cs
public class Startup {
    public void Configuration(IAppBuilder app) {
        ConfigureOAuth(app);
    }
    public void ConfigureOAuth(IAppBuilder app) {
        app.UseCookieAuthentication(new CookieAuthenticationOptions {
            AuthenticationType = "AppCookie",
        });
    }
}
  • add the same machineKey to the system.web section of the web.config file
  • add Authorize to the api action:
public class ValuesController : ApiController {
    // GET api/values
    [Authorize]
    public IEnumerable<string> Get() {
        return new string[] { "value1", "value2" };
    }

Then I can access the api via http://localhost:4002/api/values, where we assume the WebApi application running at http://localhost:4002.

Now let us consider a concrete scenario, we have the following web sites:

  • an ASP.NET WebForm application having login form, running at http://localhost:4000
  • an Angular application, running at http://localhost:4001
  • an ASP.NET WebApi application, running at http://localhost:4002 We make the WebForm and WebApi application to share the same machineKey, and set up cookie authentication there. We login from the WebForm application, then navigate to the Angular page, then set http request to the WebApi from there. Would the WebApi application be able to get the authentication information?

Resources

Clone this wiki locally