Autenticación y autorización en API mínimas

Las API mínimas admiten todas las opciones de autenticación y autorización disponibles en ASP.NET Core y proporcionan alguna funcionalidad adicional para mejorar la experiencia de trabajo con la autenticación.

Conceptos clave de autenticación y autorización

La autenticación es el proceso de determinar la identidad de un usuario. Por su parte, la autorización consiste en determinar si un usuario tiene acceso a un recurso. Los escenarios de autenticación y autorización comparten una semántica de implementación similar en ASP.NET Core. La autenticación se controla mediante el servicio de autenticación, IAuthenticationService, que es el que usa el middleware de autenticación. El servicio de autorización controla la autorización, IAuthorizationService, que es el que usa el middleware de autorización.

El servicio de autenticación usa controladores de autenticación registrados para completar las acciones relacionadas con la autenticación. Por ejemplo, una acción relacionada con la autenticación es autenticar a un usuario o cerrar la sesión de un usuario. Los esquemas de autenticación son nombres que se usan para identificar de forma única un controlador de autenticación y sus opciones de configuración. Los controladores de autenticación son responsables de implementar las estrategias para la autenticación y generar notificaciones de un usuario dada una estrategia de autenticación determinada, como OAuth o OIDC. Las opciones de configuración son exclusivas de la estrategia y proporcionan al controlador la configuración que afecta al comportamiento de autenticación, como los URI de redirección.

Hay dos estrategias para determinar el acceso de los usuarios a los recursos en el nivel de autorización:

En ASP.NET Core, ambas estrategias se capturan en un requisito de autorización. El servicio de autorización aprovecha los controladores de autorización para determinar si un usuario determinado cumple o no los requisitos de autorización aplicados a un recurso.

Habilitación de la autenticación en aplicaciones mínimas

Para habilitar la autenticación, llame a AddAuthentication para registrar los servicios de autenticación necesarios en el proveedor de servicios de la aplicación.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication();
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

Normalmente, se usa una estrategia de autenticación específica. En el ejemplo siguiente, la aplicación está configurada con compatibilidad con la autenticación basada en portador de JWT. En este ejemplo se hace uso de las API disponibles en el paquete NuGet de Microsoft.AspNetCore.Authentication.JwtBearer.

var builder = WebApplication.CreateBuilder(args);
// Requires Microsoft.AspNetCore.Authentication.JwtBearer
builder.Services.AddAuthentication().AddJwtBearer();
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

De forma predeterminada, la clase WebApplication registra automáticamente los middlewares de autenticación y autorización si se habilitan determinados servicios de autenticación y autorización. En el ejemplo siguiente, no es necesario invocar UseAuthentication o UseAuthorization para registrar los middlewares porque WebApplication lo hace automáticamente después de que se llame a AddAuthentication o AddAuthorization.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

En algunos casos, como al controlar el orden de middleware, es necesario registrar explícitamente la autenticación y la autorización. En el ejemplo siguiente, el middleware de autenticación se ejecuta después de que se haya ejecutado el middleware CORS. Para más información sobre los middleware y este comportamiento automático, consulte Middleware en aplicaciones de API mínimas.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors();
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();

var app = builder.Build();

app.UseCors();
app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/", () => "Hello World!");
app.Run();

Configuración de la estrategia de autenticación

Las estrategias de autenticación suelen admitir varias configuraciones que se cargan mediante opciones. Opciones de soporte de carga de las aplicaciones mínimas desde la configuración para las siguientes estrategias de autenticación:

El marco ASP.NET Core espera encontrar estas opciones en la sección Authentication:Schemes:{SchemeName} en configuración. En el ejemplo siguiente, se definen dos esquemas diferentes, Bearer y LocalAuthIssuer, con sus respectivas opciones. La opción Authentication:DefaultScheme se puede usar para configurar la estrategia de autenticación predeterminada que se usa.

{
  "Authentication": {
    "DefaultScheme":  "LocalAuthIssuer",
    "Schemes": {
      "Bearer": {
        "ValidAudiences": [
          "https://localhost:7259",
          "http://localhost:5259"
        ],
        "ValidIssuer": "dotnet-user-jwts"
      },
      "LocalAuthIssuer": {
        "ValidAudiences": [
          "https://localhost:7259",
          "http://localhost:5259"
        ],
        "ValidIssuer": "local-auth"
      }
    }
  }
}

En Program.cs, se registran dos estrategias de autenticación basadas en portador JWT, con:

  • Nombre del esquema "Bearer".
  • Nombre del esquema "LocalAuthIssuer".

"Bearer" es el esquema predeterminado típico en aplicaciones habilitadas basadas en portador JWT, pero el esquema predeterminado se puede invalidar estableciendo la propiedad DefaultScheme como en el ejemplo anterior.

El nombre del esquema se usa para identificar de forma única una estrategia de autenticación y se usa como clave de búsqueda al resolver las opciones de autenticación de la configuración, como se muestra en el ejemplo siguiente:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication()
  .AddJwtBearer()
  .AddJwtBearer("LocalAuthIssuer");
  
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

Configuración de directivas de autorización en aplicaciones mínimas

La autenticación se usa para identificar y validar la identidad de los usuarios en una API. La autorización se usa para validar y comprobar el acceso a los recursos de una API y la facilita la clase IAuthorizationService registrada por el método de extensión AddAuthorization. En el escenario siguiente, se agrega un recurso /hello que requiere que un usuario presente una notificación admin con una notificación de ámbito greetings_api.

La configuración de los requisitos de autorización en un recurso es un proceso de dos pasos que requiere lo siguiente:

  1. Configuración de los requisitos de autorización en una directiva de formal global.
  2. Aplicación de directivas individuales a los recursos.

En el código siguiente, se invoca AddAuthorizationBuilder, que hace lo siguiente:

  • Agrega servicios relacionados con la autorización al contenedor de inserción de dependencias.
  • Devuelve un elemento AuthorizationBuilder que se puede usar para registrar directamente las directivas de autorización.

El código crea una nueva directiva de autorización, denominada admin_greetings, que encapsula dos requisitos de autorización:

  • Un requisito basado en roles a través de RequireRole para los usuarios con un rol admin.
  • Un requisito basado en notificaciones mediante RequireClaim en el que el usuario debe proporcionar una notificación de ámbito greetings_api.

La directiva admin_greetings se proporciona como una directiva necesaria para el punto de conexión /hello.

using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorizationBuilder()
  .AddPolicy("admin_greetings", policy =>
        policy
            .RequireRole("admin")
            .RequireClaim("scope", "greetings_api"));

var app = builder.Build();

app.MapGet("/hello", () => "Hello world!")
  .RequireAuthorization("admin_greetings");

app.Run();

Uso de dotnet user-jwts para pruebas de desarrollo

En este artículo se usa una aplicación configurada con autenticación basada en portador JWT. La autenticación basada en portador JWT requiere que los clientes presenten un token en el encabezado de solicitud para validar su identidad y notificaciones. Normalmente, estos tokens los emite una autoridad central, como un servidor de identidades.

Al desarrollar en el equipo local, se puede usar la herramienta dotnet user-jwts para crear tokens de portador.

dotnet user-jwts create

Nota

Cuando se invoca en un proyecto, la herramienta agrega de forma automática las opciones de autenticación que hacen coincidir el token generado con appsettings.json.

Los tokens se pueden configurar con una variedad de personalizaciones. Por ejemplo, para crear un token para el rol admin y el ámbito greetings_api esperado por la directiva de autorización en el código anterior, use lo siguiente:

dotnet user-jwts create --scope "greetings_api" --role "admin"

Ahora, el token generado se puede enviar como parte del encabezado en la herramienta de prueba que prefiera. Por ejemplo, con curl:

curl -i -H "Authorization: Bearer {token}" https://localhost:{port}/hello

Para más información sobre la herramienta dotnet user-jwts, lea la documentación completa.