Moving legacy ASP.NET apps with Windows authentication to Azure App Service (Part 1)

Developer Support

App Dev Manager Mike Lapierre explores authentication options when moving legacy ASP.NET apps to Azure App Services.


When attempting to move legacy ASP.NET apps to Azure App Service, you might encounter a few challenges which are documented here. I want to cover specially the use Windows authentication which is not supported in Azure App Service. Let’s split this in two parts, first authentication and then authorization.

Authentication

The obvious solution is to use Azure AD which allows authentication on the Intranet without entering your password with technologies like Seamless SSO or ADFS. There are a few techniques that can be used to accomplish this. For instance, code can be modified to use Azure AD authentication as described by my colleague in this article. Another option, since the target environment is App Service, is to make use of App Service Authentication. The nice thing about it is no change to the code is required, you just configure it and the identity will flow in automatically for ASP.NET 4.6+ applications. If you want authentication on the Intranet without any prompt, you’ll also need to configure the domain hint.

Authorization

Authorization is a broader topic since it depends on what technique you’re using. With Azure AD, the use of roles scoped to the application is a popular choice. If backward compatibility is essential, it’s also possible to use groups, but keep in mind they are not scoped to the application so they can get large and there’s a 200 limit. If you wish to use application roles, follow this procedure. For groups, follow this one.

Now that the roles or groups claims are sent to the application, let’s have a look on the application impacts. Since we’re talking about legacy ASP.NET apps, let’s start with Web Forms. The first Web Forms apps with Windows authentication usually relied on the two modules, the FileAuthorizationModule and/or the UrlAuthorizationModule.

FileAuthorizationModule

The FileAuthorizationModule does authorization checks based on file permissions on the disk. Since you cannot authenticate with a Windows identity in App Service, you’ll have to extract the ACL rules and move towards something else like the UrlAuhorizationModule I will cover next.

UrlAuthorizationModule

The UrlAuthorizationModule does authorization checks based on entries in the web.config. The module relies on the role claims, so it will continue to work as is. There’s a small caveat though, you have to a little bit of claim transformation to make it work properly.

If you choose to use roles, you’ll need to convert the roles claims received from App Service to the proper claim type. Here’s a small HttpModule that will do the trick:

public class ClaimTransformationModule : IHttpModule
{
    public void Dispose() { }

    public void Init(HttpApplication context)
    {
        context.PostAuthenticateRequest += new EventHandler(PostAuthenticateRequest);
    }

    private void PostAuthenticateRequest(Object source, EventArgs e)
    {
        if (!(HttpContext.Current.User?.Identity is ClaimsIdentity ci)) return;

        foreach (var c in ci.Claims.Where(x => x.Type == "roles"))
        {
            ci.AddClaim(new Claim(ci.RoleClaimType, c.Value));
        }
    }
}

If you choose to use groups, you’ll have to do something similar, but you’ll receive the group object ids rather than the group names, so you’ll have to convert them to the proper name before adding the claims, see this article for more details. You could also choose to query the Microsoft Graph to resolve the group names.

Now that we have injected the proper role claims, calls to IsInRole for imperative security checks will also work as is. That will cover most Web Form applications using Windows authentication. Let’s now switch to MVC applications. With MVC, routes no longer map to physical files, so it doesn’t make sense to use the FIleAuthorizationModule. The UrlAuthorizationModule can still be used, but the use of authorization filters like the Authorize attribute is more common. The Authorize attribute is based on the role claims, so it will also work just like the IsInRole calls. You could alternatively implement the same code as above using an OWIN Middleware instead of a HttpModule.

The techniques covered in this article will work for most two-tier applications, but what about three-tier applications? In Part 2, I will cover moving web services using Windows authentication to Azure App Service.

0 comments

Discussion is closed.

Feedback usabilla icon