"Easy Auth" / App Service authentication using multiple providers
App Service authentication is a feature in Microsoft Azure that allows extremely easy setup of authentication using either:
- Active Directory
- Microsoft Account (MSA)
It is often referred to as "Easy Auth". This is due to how easy it is to setup and integrate into your app. Effectively, no code required (at least for authentication).
Lets say you have developed a web site and are deploying it to Azure as an App Service. Without doing anything in code, you can enable one of these forms of authentication from within the Azure portal.
You can enable this feature by using the "Authentication/Authorization" option in the list of settings associated with an App Service.
Any anonymous requests that come through are automatically caught by the pipeline that Azure injects, and an authentication process with the configured provider is performed. For example, if Google is specified and configured, then when an un-authenticated request comes in, the user is redirected to google for authentication, then redirected back to the site once this is successful.
This works great but has a few shortcomings.
- You can only specify 1 provider to use. For example, you can use Active Directory, or Google, but not both.
- Local development. You cannot enable this option locally so how do you develop locally with security enabled?
Problem 1 - Using multiple providers
While this is not supported out of the box, you can make it work. In order to do this, you will need to do the following:
- Ensure that the "Action to take when request is not authenticated" option in the azure portal is set to "Allow anonymous requests".
- Ensure your application requires authenticated users with a redirect to a login page. There are a few ways to do this. As an example, you can include the "Microsoft.Owin.Security " nuget package and place the following code in your Owin startup class:
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Login")
});
}
- Provide a login page with options to the user about which provider to use when authenticating. This page should not require authentication.
- These options should link directly to each provider instead of allowing azure to automatically redirect. The way to do that is by using the following link format:
- https://{your-host}/.auth/login/{provider}
- The available providers to use are "aad","google","facebook" and "microsoftaccount".
- As an example, let's say we have created an AppService that is hosted at http://awesomeapp.azurewebsites.net. The Url for the 'Login with Active Directory' button would be http://awesomeapp.azurewebsites.net/.auth/login/aad and for google it would be http://awesomeapp.azurewebsites.net/.auth/login/google
- Further to this, we need to include an extra parameter to instruct where the process should redirect to after successful authentication. We can do this with the 'post_login_redirect_uri' parameter. Without this, the process will redirect to a default 'Authentication Successful' page with a link to go back to the site. So the final Url (in the case of Active directory) will look like:
- With the two options now linking to each providers login option, and with a post login redirect in place, we are good to go.
Problem 2 - Local Development
Obviously, when developing locally, we are not hosting in azure and so cannot take advantage of the "Easy Auth" functionality within the azure portal. In order to get around this, you can provide a further option to login locally, but that is only displayed when in local development mode. To do this, you can:
- Create an appSetting value in web.config that identifies whether the app is in local development mode such as:
<add key="EnableLocalLogin" value="true" />
- Define this value in the azure portal application settings as false. This value will overwrite the one configured in the web.config.
- Create another login option that is only displayed when EnableLocalLogin appSetting is true.
-
The "Login as local developer" button simply calls into an action method which:
-
Checks if the app is in local development mode.
-
If so, constructs an instance of the IPrincipal class with appropriate claims and calls the ASP.Net Identity systems to assign the identity to the current context.
-
if (IsInLocalDevelopmentMode())
{
claims = new List
{
new Claim(ClaimTypes.Name, "LocalDev"),
new Claim(ClaimTypes.NameIdentifier, "LocalDev"),
new Claim(ClaimTypes.Email, "LocalDev@local.com"),
new Claim(ClaimTypes.Surname, "Developer"),
new Claim(ClaimTypes.GivenName, "LocalDev"),
new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity")
};
var owinContext = HttpContext.Current.GetOwinContext();
var authmanager = owinContext.Authentication;
var claimsIdentity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
authmanager.SignIn(new AuthenticationProperties { IsPersistent = false, AllowRefresh = true }, claimsIdentity);
}
- Note the explicit claim added for identityprovider. I found without doing that, the security system would complain of a missing claim.
- Now your local developers can login and use the system just as if they had logged in via active directory or google. Obviously the local login can be more elaborate that what I have shown but you get the idea.
So that’s about it. It is a little more work, but the end result is a pretty easy way of enabling multiple external identity providers to act as authentication providers for your site. This allows the very easy configuration mechanism of "Easy Auth" within azure to be utilised.
As a side note, once logged in via one of the providers, you can navigate to the https://{your-host}/.auth/me endpoint to access the token and its associated details.
For further information around the Url scheme with "Easy Auth", multiple providers and associated tokens claims, you can refer to this post: https://blogs.msdn.microsoft.com/kaushal/2016/04/01/azure-web-apps-how-to-retrieve-user-email-in-the-claim-when-using-microsoft-account-as-a-provider-in-easy-auth/