Getting Umbraco to work with Azure Easy Auth
There’s a nifty feature in your Azure App Service that allows you to very quickly add authentication and authorization to your Azure website. You’ll see most folks calling this “Easy Auth” and there’s quite a few articles on the subject such as:
- https://medium.com/tech-feed/azure-active-directorys-hidden-feature-easy-auth-315e34d92249
- https://azure.microsoft.com/en-us/resources/videos/azure-websites-easy-authentication-and-authorization-with-chris-gillum/
- https://docs.microsoft.com/en-us/azure/app-service/app-service-authentication-overview
The good news is this all works the way you’d expect with an Umbraco website for front-end requests but unfortunately this doesn’t play nicely with the Umbraco back office … but it’s easy to configure Umbraco to work!
The problem
The problem is that if you turn on Easy Auth and try to log in to your Umbraco back office, the login will succeed but you’ll get 401 responses for other back office requests and essentially you’ll see a blank screen. The reason this happens is due to the way that Easy Auth works:
- It activates an HttpModule in your site called EasyAuthAspNetThreadPrincipalModule
- During the HttpModule.AuthenticateRequest stage it replaces the Thread.CurrentPrincipal with it’s own ClaimsPrincipal/ClaimsIdentity instance
Umbraco also sets the Thread.CurrentPrincipal.Identity during this phase but at the OWIN level which executes before the EasyAuthAspNetThreadPrincipalModule. Because the Easy Auth module replaces the principal/identity, it wipes out the one created by Umbraco. What it should do instead is check if the current principal is a ClaimsPrincipal and then add it’s identity to the identity collection instead of wiping out anything that is already there. If that were the case, everything would ‘just work’ but since it is not we have to work around this issue.
The solution
UPDATE! (19/04/18) - Chris Gillum who created Easy Auth got in touch with me on Twitter to share some handy (and fairly hidden) documentation for Easy Auth. Looks like another work around is to use the WEBSITE_AUTH_DISABLE_IDENTITY_FLOW appSetting which will prevent Easy Auth from setting the thread identity at all.
To work around this problem we need to tell Umbraco to perform it’s authentication procedure after the Easy Auth module runs which is actually pretty easy to do.
Create a new OWIN startup class:
[assembly: OwinStartup("MyOwinStartup", typeof(MyOwinStartup))]
namespace MyProject
{
public class MyOwinStartup : Umbraco.Web.UmbracoDefaultOwinStartup
{
}
}
Update an appSetting in your web.config to tell OWIN to use your class:
<add key="owin:appStartup" value="MyOwinStartup" />
Override the method that configures Umbraco's authentication procedure and tell it to execute after the default Authentication stage, notice this code block is using PipelineStage.PostAuthenticate:
public class MyOwinStartup : Umbraco.Web.UmbracoDefaultOwinStartup
{
protected override void ConfigureUmbracoAuthentication(IAppBuilder app)
{
app
.UseUmbracoBackOfficeCookieAuthentication(ApplicationContext, PipelineStage.PostAuthenticate)
.UseUmbracoBackOfficeExternalCookieAuthentication(ApplicationContext, PipelineStage.PostAuthenticate)
.UseUmbracoPreviewAuthentication(ApplicationContext, PipelineStage.Authorize);
}
}
That's it! Now the Umbraco back office will authenticate correctly with Azure Easy Auth turned on.