How to add ASP.NET Identity (OWIN) - Front end authentication
How to add ASP.NET Identity (OWIN) - Front end authentication
I recently started a new project using Umbraco and as any application goes we have to implement some sort of user authentication. Umbraco now support ASP.NET Identity by default if you have a look at the web.config you might spot an entry like that.
<add key="owin:appStartup" value="UmbracoDefaultOwinStartup" />
My eyes sparkled when I saw that, having that entry there would mean we can participate on the Owin startup, for those not familiar with OWIN (Open Web Interface) I suggest watching the following video (it’s old but still applies; plus, gives you a bit of history and understanding about why Microsoft incorporated it).
After a bit of research on the internet I gathered enough information to support my theory and as usual, created the OWIN startup classes.
Startup.cs
[assembly: OwinStartup("MyProjectOwinStartup",typeof(Mynamespace.Owin.Startup))]
namespace Mynamespace.Owin
{
public partial class Startup : UmbracoDefaultOwinStartup
{
protected override void Configuration(IAppBuilder app)
{
base.Configuration(app);
ConfigureAuth(app);
}
}
}
Startup.Auth.cs
namespace Mynamespace.Owin
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/signin"), // --> the path for your sign in page
Provider = new CookieAuthenticationProvider
{
OnApplyRedirect = ctx => { ctx.Response.Redirect(ctx.RedirectUri); }
},
ExpireTimeSpan = TimeSpan.FromMinutes(20),
CookieName = "My project name"
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
}
}
}
After doing this you need to tell Umbraco to use our OWIN start up instead. In order to accomplish that, just change that first configuration to the following
<add key="owin:appStartup" value="MyProjectOwinStartup" />
All you have to do now is restart the process that is hosting your app (e.g. w3wp if IIS, if IIS Express just kills the website).
Now we have the front end hooked to our OWIN, but how do we sign in and out?
I decided to create a helper class but you can use whatever suits you better.
public void SignInUser(User user)
{
var Identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Email, user.Email)
// --> add as many claims as you need
}, DefaultAuthenticationTypes.ApplicationCookie);
// get owin context
var ctx = Request.GetOwinContext();
// get authentication manager
var authManager = ctx.Authentication;
// finally sign in
authManager.SignIn(new AuthenticationProperties()
{
AllowRefresh = true,
IsPersistent = true,
ExpiresUtc = DateTime.UtcNow.AddHours(1)
}, Identity);
}
public void SignOut()
{
var ctx = Request.GetOwinContext();
var authManager = ctx.Authentication;
authManager.SignOut();
}
Now we have sign in and out mechanisms in place it’s time to test, add an attribute in one of your actions [Authorize] and access it.
To my surprise that did not work, somehow it is redirecting me to a login.aspx page which doesn’t even exist Turns out that there is another configuration in web.config we need to change, and actually remove.
<authentication mode="Forms">
<forms name="yourAuthCookie" loginUrl="login.aspx" protection="All" path="/" />
</authentication>
Ok, now give it another try and you will see your front end authenticating using ASP.NET Identity nicely.
The Backoffice
You will notice that after you sign-in on the front-end, trying to sign-in onto backoffice will result in a failure. Looking closely you can see that for some reason Umbraco is trying to redirect you to the same sign-in page as the front-end. What is happening?
The cookies are getting mixed-up. After a bit of research, I found that this issue was already faced by Shannon’s project ASP.NET Identity for Umbraco, you can find it here.
Inspired by his implementation of FrontEndCookieAuthenticationOptions I’ve navigated around that issue quite easily.
After a couple of hours of being happy with OWIN, I tried to use the preview functionality in Umbraco to see one of the pages that is protected by the attribute [Authorize] and it redirects me to sign in page as expected. However, after authenticating it breaks, and doesn’t show me the actual page.
I found an issue raised in Umbraco which provides more information about why that happens. I’ll just give you a short cut; the preview pipeline needs to be registered after our middleware and to do that you need to override a different method in our OWIN Startup.cs (ConfigureMiddleware instead of Configuration).
public partial class Startup : UmbracoDefaultOwinStartup
{
protected override void ConfigureMiddleware(IAppBuilder app)
{
app.UseUmbracoBackOfficeCookieAuthentication(ApplicationContext, PipelineStage.Authenticate)
.UseUmbracoBackOfficeExternalCookieAuthentication(ApplicationContext, PipelineStage.Authenticate);
ConfigureAuth(app);
app.UseUmbracoPreviewAuthentication(ApplicationContext, PipelineStage.PostAuthenticate);
}
}
This is it, now we have OWIN authentication for front end without impacting the backoffice!
Happy coding.