Integrar Azure Active Directory en una aplicación ASP.NET Core 2.1 existente

El otro día comencé a desarrollar una aplicación con ASP.NET Core desde Visual Studio for Mac y, poco después de tener algo de funcionalidad en mi aplicación, me di cuenta de que este IDE todavía no facilita la integración de tus aplicaciones con Azure Active Directory, algo a lo que estamos acostumbrados en Visual Studio “para Windows” :). Es por ello que me tocó montar esta integración una vez que ya tenía la aplicación y no encontré mucha información actualizada que relatara este escenario. Hoy te voy a contar cuáles son los pasos básicos para integrar Azure Active Directory con una aplicación con ASP.NET Core 2.1.

Lo primero que necesitas es registrar tu aplicación dentro de Azure Active Directory. Para ello, accede al portal de Azure y selecciona el recurso Azure Active Directory. Una vez en él verás que tienes una sección llamada App Registrations

Azure Active Directory – App registrations section

Al crear una aplicación dentro de nuestro directorio le estamos dando permiso a la misma a poder trabajar con los usuarios que tenemos en él. Para darla de alta haz clic sobre el botón New application registration de la sección. Una aplicación registrada consta de un nombre, el tipo de aplicación (en este caso Web app / API) y la URL de retorno.

Azure Active Directory – App Registrations – Create

Una vez creada la aplicación guarda el Application ID que será necesario para después.

Azure Active Directory – App Registration – Application ID

Del lado de la aplicación, para integrar Azure Active Directory primero necesitas instalar los siguientes paquetes de Nuget:

  • Microsoft.AspNetCore.Authentication.AzureAD.UI
  • Microsoft.AspNetCore.Authentication

El archivo donde ocurre toda la magia es el Startup.cs donde debes de modificar por un lado el método ConfigureServices de la siguiente manera:

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
                .AddAzureAD(options => Configuration.Bind("AzureAd", options));

            services.AddMvc(options =>
            {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);            

        }

Y por otro lado debes añadir dentro del método Configure la llamada al método app.UseAuthentication();

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();

            //Before app.UseMvc please
            app.UseAuthentication();


            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }

Es muy importante que app.UseAuthentication() sea invocado antes de app.UseMvc. De no ser así verás que una vez autenticado nunca terminará de redirigir la petición de nuevo a tu sitio.

Por último, en el archivo de configuración appsettings.json debes crear la sección AzureAd con las siguiente propiedades.

  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "Domain": "YOUR_TENANT_NAME.onmicrosoft.com",
    "TenantId": "YOUR_TENANT_ID",
    "ClientId": "YOUR_CLIENT_ID",
    "CallbackPath": "/signin-oidc"
  }

El nombre del tenant puedes recuperarlo dentro del recurso de Azure Active Directory en el apartado Overview.

Azure Active Directory – Tenant name

El Tenant Id está disponible en la sección Endpoints, en el mismo sitio que hiciste clic para registrar tu aplicación.

Azure Active Directory – App Registrations – Endpoints

Si copias cualquiera de ellos, por ejemplo OAUTH 2.0 AUTHORIZATION ENDPOINT podrás ver el tenant id en la URL: https://login.microsoftonline.com/ESTE_ES_TU_TENANT_ID/oauth2/authorize. Client Id es el GUID que copiaste anteriormente llamado Application ID.

Si ejecutas tu aplicación en local verás que ya tendrás tu aplicación con ASP.NET Core protegida desde la nube.

¡Saludos!