"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
  • Google
  • Facebook
  • Twitter
  • 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.

  1. You can only specify 1 provider to use. For example, you can use Active Directory, or Google, but not both.
  2. 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:
  • 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/

    6 Comments

    • hi welcome to this blog. really you have post an informative blog. it will be really helpful to many peoples.thank you for sharing this blog.

    • Great post - I was wondering how to do this.

    • Incredibly useful - why isn't this part of the official docs?

    • Great article! How can we access the token from backend ? Got articles saying .auth/me is the way to go. if i make the call to it from browser it works. however, i need the to call it from backend ?

      Any thoughts ?

    • Good job Glav boy. you still got it

    • q1. With current vs17 | file | new project | visual c# | web | asp.net core web application | api, no authentication project template environment how would one author IsInLocalDevelopmentMode() function to determine you were carrying out a localhost vs17 debug/test session vs app running in azure web app deployment?

      q2. With current vs17 | file | new project | visual c# | web | asp.net core web application | api, no authentication project template environment where would you stick the IsInLocalDevelopmentMode code that creates a valid this.User [ / ClaimsPrincipal ] where this.User.Identity.IsAuthenticated = true and this.User.Claims() properties are set? I ask because I tried to stick it in a constructor for the default project template's ValuesController() and it doesn't like .Current in var owinContext = HttpContext.Current.GetOwinContext(); and show potential fixes doesn't seem to be able to find DefaultAuthenticationTypes enum in any of the referenced assembly namespaces.

    Add a Comment

    As it will appear on the website

    Not displayed

    Your website