Cómo autorizar a tus usuarios utilizando los grupos de Azure Active Directory en tus aplicaciones

Una vez que ya tienes tu aplicación integrada con Azure Active Directory, lo siguiente que debes decidir es cómo autorizas a tus usuarios en tu aplicación a ciertas páginas, cómo configuras las vistas y menús en función del grupo al que pertenezcan, etcétera. Hace tiempo te conté como utilizar los roles pero ahora me gustaría mostrarte cómo puedes utilizar los grupos definidos en Azure Active Directory para el mismo fin.

Lo primero de todo, para que tu aplicación sea capaz de devolver los claims correspondientes a los grupos es necesario que modifiques el manifiesto de tu aplicación registrada en Azure Active Directory. La propiedad que debes cambiar es groupMembershipClaims con el valor SecurityGroup.

Azure Active Directory – Manifiest – groupMembershipClaims

Ahora que tu aplicación ya recupera los grupos, necesitas tener algunos ;-). En mi ejemplo voy a trabajar con tres: Admins, Developers y Test. Obviamente, deberás añadir algún usuario a cada uno de los grupos para poder hacer las pruebas pertinentes. Puedes darlos de alta a través de la sección Groups.

Azure Active Directory – Groups

El siguiente paso es recuperar el valor de Object Id de cada uno de los grupos. Si seleccionas cualquiera de ellos verás que lo tienes en la misma sección Overview.

Azure Active Directory – Groups – Admins – Object Id

Crea un nuevo apartado dentro del archivo appsettings.json con la siguiente estructura:

"AzureSecurityGroups": {
    "DevelopersObjectId": "9e2b789f-2349-46cc-aaf7-cad1cbd557e8",
    "AdminsObjectId": "d4da75e0-eff1-48bb-b95c-0bb668e8fb46",
    "TestObjectId": "4500f669-b1f3-4678-8f94-095fda18d8d8"
}

Ahora en el archivo Startup.cs en el método ConfigureServices añade el siguiente fragmento justo antes de service.AddMvc:

services.AddAuthorization(options =>
{
    options.AddPolicy("Admins",
                    builder => builder.RequireClaim("groups",
                    Configuration.GetValue<string>("AzureSecurityGroups:AdminsObjectId")));

    options.AddPolicy("Developers",
                    builder => builder.RequireClaim("groups",
                    Configuration.GetValue<string>("AzureSecurityGroups:DevelopersObjectId")));

    options.AddPolicy("Test",
                    builder => builder.RequireClaim("groups",
                    Configuration.GetValue<string>("AzureSecurityGroups:TestObjectId")));
});

Lo que estamos haciendo con ello es generar una serie de políticas que podremos usar después para autorizar el acceso a ciertas partes de nuestra aplicación. Para poder usarlo, dependiendo de dónde lo necesites, tienes diferentes maneras:

Si quieres controlar el acceso a una acción, controlador, etcétera puedes utilizarlo con el atributo Authorize, indicando el nombre de la polítca que quieres aplicar.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace HangFireWebApp.Controllers
{
    public class TestRoleController : Controller
    {
        [Authorize(Policy = "Admins")]
        public IActionResult Index()
        {
            ViewBag.WhoYouAre = "You are an admin";
            return View();
        }

        [Authorize(Policy = "Test")]
        public IActionResult Test()
        {
            ViewBag.WhoYouAre = "You are a test";
            return View();
        }
    }
}

Si lo que necesitas es utilizarlo directamente en el código, puedes hacerlo de la siguiente manera:

public async Task<bool> HasAccess(DashboardContext context)
{
    var authorizationService = context.GetHttpContext().RequestServices.GetService(typeof(IAuthorizationService)) as IAuthorizationService;

    return (await authorizationService.AuthorizeAsync(context.GetHttpContext().User, "Admins")).Succeeded;
    
}

Si es a nivel de vista, para mostrar u ocultar ciertas secciones, deberás utilizar en la cabecera  de la página lo siguiente:

@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService

Y comprobar la política de la siguiente manera donde necesites.

<div class="navbar-collapse collapse">
    <ul class="nav navbar-nav">
        <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
        <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
        <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
        @if ((await AuthorizationService.AuthorizeAsync(User, "Admins")).Succeeded)
        {
        <li><a href="/admin">Admin Dashboard</a></li>
        }
    </ul>
</div>

¡Saludos!