After my previous post regarding Secure Token Services / SSO, I have been diving deeper into OWIN to understand its capabilities further.
As I mentioned, the STS system I devised is still using FormsAuthentcation. As a consequence, the relying applications are also dependent on FormsAuth. Upon further inspection, I found that this is redundant. It turns out that OWIN was doing more than I initially divined. Additionally, from all that I have read, it appears that Microsoft’s vision is to completely supplant, and retire, FormsAuth. This, obviously, could be a point of contention if one ties their authentication system into FormsAuth.
What was I missing? I didn’t understand the breadth of OWIN’s scope, nor did I realize that its cookie data fully. As it happens, OWIN’s cookie holds all of the Claims of the ClaimsIdentity (user) that has signed in. Initially, I wasn’t certain how the parts were pulled together, and this was why I would extract claims from the encrypted AccessToken (yes, they’re available there as well) and put the Claims into Roles of the FormsAuth ticket. Overall, this is still a serviceable approach for legacy applications that are heavily vested in FormsAuth, but for new apps, it’s burdensome and unneeded.
There were still a few gotchas to get OWIN CookieAuth working with MVC5. To completely remove FormsAuth from the equation, it’s best to remove FormsAuth modules in your web.config:
<system.webServer> <validation validateIntegratedModeConfiguration="false" /> <modules runAllManagedModulesForAllRequests="true"> <remove name="FormsAuthenticationModule" /> <remove name="FormsAuthentication" /> </modules> </system.webServer>
Another problem I ran into was that MVC5’s [Authorize] attribute would never redirect to my login page in the client WebApp due to the issuance of 401/403 errors. However, a nice work-around is to replace the default Authorize attribute by placing one in your WebApp’s default (root) namespace:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute { protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext) { if (filterContext.HttpContext.Request.IsAuthenticated) { filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden); } else { base.HandleUnauthorizedRequest(filterContext); } } }
In your consuming/client application, you need the following Nuget packages:
- Microsoft.Owin.Host.SystemWeb
- Microsoft.Owin.Security
- Microsoft.Owin.Security.Cookies
Beyond that, you’ll still configure your WebApp through OWIN’s IAppBuilder to utilize cookies (UseCookieAuthentication). The basic configuration needs to utilize the same domain, cookie name, and other parameters that match your SSO end-point. It might look something like this:
[assembly: OwinStartupAttribute(typeof(MyWebApp.Startup))] namespace MyWebApp { public partial class Startup { public void Configuration(IAppBuilder app) { var appCookieOptions = new CookieAuthenticationOptions() { AuthenticationType = "myAuthType", AuthenticationMode = AuthenticationMode.Active, LoginPath = new PathString("/login"), LogoutPath = new PathString("/logout"), CookieSecure = CookieSecureOption.Always, CookieName = "myCookie", CookieDomain = "", CookiePath = "/", SlidingExpiration = true }; app.UseCookieAuthentication(appCookieOptions); } } }
Incidentally, behind the scenes, the Login end-point is calling the SSO and dealing with the login redirect workflow. With just these small pieces of configuration and code in place, I could login with OWIN CookieAuthenticaiton and access claims by casting HttpContext.Current.User.Identity as ClaimsIdentity.
All in all, I am happier now to leave FormsAuth behind. Having a better understanding beyond Secure Token Generation has helped immensely. FormsAuth is an aging module that bound the developer to IIS whereas OWIN (and Katana) middleware aims to remove the reliance from and decouple your applications from IIS.