ASP.NET: Sharing OWIN Authentication Cookie across IIS Applications
It's been almost 3 years since I've shared my learning experience on this blog. During this past 3 years, I worked on various technology right from fixing some classic ASP pages in legacy application to ASP.NET Core, Visual Studio Team System (VSTS), Single-Sign-On (SSO) with CAS, Shibboleth, Azure AD and other related SSO technology/protocol, and much more. I'll try to post articles on some of the interesting learning experience later. But here in this post we will see how we can share OWIN authentication cookie across IIS application within same website.
Recently I was tasked with revamp of an existing intranet application. An existing application was already deployed with several modules from last year and an half. Few months back we decided to add some more modules and as a result of addition of these new proposed modules, application would become almost double in term of it's features. As application become large, it is also necessary that it maintain it’s user friendliness and end-user must not confused/struggle between so many features and it's different workflow. And this, application becoming large, was one of the key factor for revamp of existing modules. One of the major overhaul was to change entire HTML template and hence user experience & re organize existing modules url (controller action) so that admin can configure which user will have access to which module and this access can be to entire module or some of the functionality of module. As it was an intranet application to be used within organization only, application was deployed as an IIS application for e.g. http://10.0.0.1/App However we decided that this new revamped application will be deployed as another IIS application for e.g. http://10.0.0.1/AppV2 and as and when we complete migration of existing module we will move it from App to AppV2 and eventually old deployment i.e. http://10.0.0.1/App will become obsolete. Here comes our very first challenge that during this short time of transition how to share OWIN authentication cookie between these two IIS application and this post is all about how I implemented it.
Configuring OWIN cookie authentication
In-depth explanation of configuring OWIN cookie authentication is beyond the scope of this post. However to address our scenario, very first step is to make sure that both old and new application use cookie authentication and both application use the same name for authentication cookie.
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "AppCookieName",
LoginPath = new PathString("/Account/LogIn")
});
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
}
}
We have to make sure that we use same cookie name in OWIN startup class while configuring authentication. Above configuration will make sure that both old and new application will redirect unauthenticated user to their respective Account/Login action. In next section we will see how to redirect new application to login page of old application.
Redirection to appropriate login page
Now we have two separate version of application, we need to make sure that when user browse either of the version old or new, it redirect to appropriate login page and after successful login it redirect back to originally requested version. Here we decided that whenever user browse new application (i.e. http://10.0.0.1/AppV2) we will redirect it to login page of older application (i.e. http://10.0.0.1/App) In older application we have login logout action as
public ActionResult LogIn(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
public ActionResult LogOut()
{
AuthenticationManager.SignOut("AppCookieName");
return Redirect("~/");
}
In new application we have added below app setting key
<appSettings>
<add key="LoginUrl" value="http://10.0.0.1/App/Account/LogIn?ReturnUrl=" />
<add key="LogoutUrl" value="http://10.0.0.1/App/Account/LogOut" />
</appSettings>
And we added below login logout action in new application
public ActionResult LogIn()
{
return Redirect(string.Format("{0}{1}", ConfigurationManager.AppSettings["LoginUrl"], HttpRuntime.AppDomainAppVirtualPath));
}
public ActionResult LogOut()
{
return Redirect(ConfigurationManager.AppSettings["LogoutUrl"]);
}
Above all code will ensure that whenever unauthenticated user browse old or new application it will always redirect to old application login page with appropriate ReturnUrl value. This ReturnUrl value is important because when user browse new application, even though login page is of old application it should redirect to new application.
Setting Up a Machine Key
When I started with this task actually, I was pretty sure on above two step that I have to configure same cookie name and redirect both to either old or new login page. But to be frank at that moment I was not sure how I’ll handle authentication cookie encryption/decryption. Of course we do not need to write code for this, but I was not sure how OWIN cookie authentication middleware will handle this encryption/decryption as both are separate IIS application. But as I implement above two steps, I remember that earlier for other project when we implemented round robin load balancer, we kept machine key in sync across servers. Bottom line is we also need to use same machine key for both old and new deployment. Below is the minimal web.config changes to set custom machine key.
<system.web>
<machineKey decryptionKey="85F7ABF05FD7713140FB4A6E1A402F68FDCC0330CED20080" validationKey="BA4C9F70AB3AC0A6CB2AF7753982378244269374CDE3C5A7BA07F78583CF882551D5144C4425D10C05AA96701AA1A0680E318DD99C4D14AAB4A780E0783E60D0" />
</system.web>
Please do not use above machine key and keep your machine key private and backed up in case for security and recovery.
We can also generate machine key from IIS. To generate machine key, select website or IIS application, in our case select old IIS application from left pane and open Machine Key
Now click on Generate Keys on Right pane and it should generate Machine Keys for selected website/IIS application. Copy and paste it to new application web.config and we are done.
Now our both application can share authentication cookie. Hope this post helpful!