Autenticación y autorización
Sugerencia
Este contenido es un extracto del libro electrónico "Patrones de aplicaciones empresariales con .NET MAUI", disponible en Documentación de .NET o como un PDF descargable y gratuito que se puede leer sin conexión.
La autenticación es el proceso de obtener credenciales de identificación, como el nombre y la contraseña de un usuario, y validar esas credenciales en una autoridad. La entidad que envió las credenciales se considera una identidad autenticada si las credenciales son válidas. Una vez establecida una identidad, un proceso de autorización determina si esa identidad tiene acceso a un recurso determinado.
Hay muchos enfoques para integrar la autenticación y la autorización en una aplicación .NET MAUI que se comunica con una aplicación web de ASP.NET, incluido el uso de ASP.NET Core Identity, proveedores de autenticación externos, como Microsoft, Google, Facebook o Twitter, y middleware de autenticación. La aplicación multiplataforma eShop realiza la autenticación y autorización con un microservicio de identidad contenedorizado que usa IdentityServer. La aplicación solicita tokens de seguridad de IdentityServer para autenticar a un usuario o acceder a un recurso. Para que IdentityServer emita tokens en nombre de un usuario, el usuario debe iniciar sesión en IdentityServer. Sin embargo, IdentityServer no proporciona una interfaz de usuario ni una base de datos para la autenticación. Por lo tanto, en la aplicación de referencia eShop, ASP.NET Core Identity se usa para este propósito.
Autenticación
Se requiere autenticación cuando una aplicación necesita conocer la identidad del usuario actual. El mecanismo principal de ASP.NET Core para identificar a los usuarios es el sistema de pertenencia a ASP.NET Core Identity, que almacena la información del usuario en un almacén de datos configurado por el desarrollador. Normalmente, este almacén de datos será un almacén de EntityFramework, aunque se pueden usar almacenes personalizados o paquetes de terceros para almacenar información de identidad en Azure Storage, DocumentDB u otras ubicaciones.
ASP.NET Core Identity es una solución adecuada para los escenarios de autenticación que usan un almacén de datos de usuario local y que conservan la información de la identidad entre las solicitudes mediante el uso de cookies (como es habitual en las aplicaciones web de ASP.NET). En cambio, las cookies no son una manera natural de conservar y transmitir datos. Por ejemplo, una aplicación web de ASP.NET Core que expone puntos de conexión de RESTful a los que se accede desde una aplicación normalmente tendrá que usar la autenticación por token de portador, ya que las cookies no se pueden usar en este escenario. Sin embargo, los tokens de portador se pueden recuperar e incluir fácilmente en el encabezado de autorización de las solicitudes web realizadas desde la aplicación.
Emisión de tokens de portador mediante IdentityServer
IdentityServer es un marco de código abierto de OpenID Connect y OAuth 2.0 para ASP.NET Core, que se puede usar para muchos escenarios de autenticación y autorización, incluida la emisión de tokens de seguridad para usuarios locales de ASP.NET Core Identity.
Nota:
OpenID Connect y OAuth 2.0 son muy similares, aunque tienen diferentes responsabilidades.
OpenID Connect es una capa de identidad basada en el protocolo OAuth 2.0. OAuth 2 es un protocolo que permite a las aplicaciones solicitar tokens de acceso desde un servicio de token de seguridad y usarlos para comunicarse con las API. Esta delegación reduce la complejidad tanto en las aplicaciones cliente como en las API, ya que la autenticación y la autorización se pueden centralizar.
OpenID Connect y OAuth 2.0 combinan los dos problemas de seguridad fundamentales de la autenticación y el acceso a la API, y IdentityServer es una implementación de estos protocolos.
En las aplicaciones que usan la comunicación directa de cliente a microservicio, como la aplicación de referencia eShop, se puede usar un microservicio de autenticación dedicado que actúa como servicio de token de seguridad (STS) para autenticar a los usuarios, como se muestra en el diagrama siguiente. Para obtener más información sobre la comunicación directa de cliente a microservicio, consulte Microservicios.
La aplicación multiplataforma eShop se comunica con el microservicio de identidad, que usa IdentityServer para realizar la autenticación y el control de acceso para las API. Por lo tanto, la aplicación multiplataforma solicita tokens de IdentityServer, ya sea para autenticar a un usuario o para acceder a un recurso:
- La autenticación de usuarios con IdentityServer se logra mediante la aplicación multiplataforma que solicita un token de identidad, que representa el resultado de un proceso de autenticación. Como mínimo, contiene un identificador para el usuario e información sobre cómo y cuándo se autentica el usuario. También puede incluir datos de identidad adicionales.
- El acceso a un recurso con IdentityServer se logra mediante la aplicación multiplataforma que solicita un token de acceso, lo que permite acceder a un recurso de API. Los clientes solicitan tokens de acceso y los reenvían a la API. Los tokens de acceso contienen información sobre el cliente y el usuario, si están presentes. A continuación, las API usan esa información para autorizar el acceso a sus datos.
Nota
Un cliente debe registrarse con IdentityServer para poder solicitar tokens correctamente. Para obtener más información sobre cómo agregar clientes, vea Definición de clientes.
Adición de IdentityServer a una aplicación web
Para que una aplicación web de ASP.NET Core use IdentityServer, debe agregarse a la solución de Visual Studio de la aplicación web. Para obtener más información, consulte Configuración e información general en la documentación de IdentityServer.
Una vez que IdentityServer está incluido en la solución de Visual Studio de la aplicación web, debe agregarse a su canalización de procesamiento de solicitudes HTTP para atender solicitudes a los puntos de conexión de OpenID Connect y OAuth 2.0. Esto se configura en el Identity.API
Program.cs del proyecto, tal y como se muestra en el siguiente ejemplo de código:
...
app.UseIdentityServer();
El orden es importante en la canalización de procesamiento de solicitudes HTTP de la aplicación web. Por lo tanto, IdentityServer debe agregarse a la canalización antes del marco de la interfaz de usuario que implementa la pantalla de inicio de sesión.
Configuración de IdentityServer
IdentityServer se configura en el Identity.API
Program.cs del proyecto llamando al AddIdentityServer
método, como se muestra en el ejemplo de código siguiente de la aplicación de referencia de eShop:
builder.Services.AddIdentityServer(options =>
{
options.Authentication.CookieLifetime = TimeSpan.FromHours(2);
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
// TODO: Remove this line in production.
options.KeyManagement.Enabled = false;
})
.AddInMemoryIdentityResources(Config.GetResources())
.AddInMemoryApiScopes(Config.GetApiScopes())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryClients(Config.GetClients(builder.Configuration))
.AddAspNetIdentity<ApplicationUser>()
// TODO: Not recommended for production - you need to store your key material somewhere secure
.AddDeveloperSigningCredential();
Después de llamar al método services.AddIdentityServer
, se llama a otras API fluidas para configurar lo siguiente:
- Credenciales usadas para firmar.
- Los recursos de identidad y de API a los que los usuarios podrían solicitar acceso.
- Los clientes que se conectarán para solicitar tokens.
- ASP.NET Core Identity.
Sugerencia
Cargue dinámicamente la configuración de IdentityServer. Las API de IdentityServer permiten configurar IdentityServer desde una lista en memoria de objetos de configuración. En la aplicación de referencia eShop, estas colecciones en memoria se codifican de forma rígida en la aplicación. Sin embargo, en escenarios de producción, se pueden cargar dinámicamente desde un archivo de configuración o desde una base de datos.
Para obtener información sobre cómo configurar IdentityServer para usar ASP.NET Core Identity, consulte Uso de ASP.NET Core Identity en la documentación de IdentityServer.
Configuración de recursos de API
Al configurar recursos de API, el método AddInMemoryApiResources
espera una colección IEnumerable<ApiResource>
. En el ejemplo de código siguiente se muestra el método GetApis
que proporciona esta colección en la aplicación de referencia eShop:
public static IEnumerable<ApiResource> GetApis()
{
return new List<ApiResource>
{
new ApiScope("orders", "Orders Service"),
new ApiScope("basket", "Basket Service"),
new ApiScope("webhooks", "Webhooks registration Service"),
};
}
Este método especifica que IdentityServer debe proteger las API de cesta de la compra y pedidos. Por lo tanto, se necesitarán tokens de acceso administrados por IdentityServer al realizar llamadas a estas API. Para obtener más información sobre el tipo ApiResource
, consulte Recurso de API en la documentación de IdentityServer.
Configuración de recursos de identidad
Al configurar recursos de API, el método AddInMemoryIdentityResources
espera una colección IEnumerable<IdentityResource>
. Los recursos de identidad son datos como el identificador de usuario, el nombre o la dirección de correo electrónico. Cada recurso de identidad tiene un nombre único, y se le pueden asignar tipos de notificación arbitrarios, que se incluirán en el token de identidad del usuario. En el ejemplo de código siguiente se muestra el método GetResources
que proporciona esta colección en la aplicación de referencia eShop:
public static IEnumerable<IdentityResource> GetResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
}
La especificación de OpenID Connect especifica algunos recursos de identidad estándar. El requisito mínimo es que se proporcione compatibilidad para emitir un identificador único para los usuarios. Esto se logra mediante la exposición del recurso de identidad IdentityResources.OpenId
.
Nota
La clase IdentityResources admite todos los ámbitos definidos en la especificación de OpenID Connect (OpenID, correo electrónico, perfil, teléfono y dirección).
IdentityServer también admite la definición de recursos de identidad personalizados. Para obtener más información, consulte Definición de recursos de identidad personalizados en la documentación de IdentityServer. Para obtener más información sobre el tipo IdentityResource, consulte Recurso de identidad en la documentación de IdentityServer.
Configuración de clientes
Los clientes son aplicaciones que pueden solicitar tokens de IdentityServer. Normalmente, se debe definir la siguiente configuración para cada cliente como mínimo:
- Un identificador de cliente único.
- Las interacciones permitidas con el servicio de token (conocido como tipo de concesión).
- La ubicación a la que se envían los tokens de identidad y acceso (conocida como URI de redireccionamiento).
- Una lista de recursos a los que el cliente puede acceder (conocidos como ámbitos).
Al configurar clientes, el método AddInMemoryClients
espera una colección IEnumerable<Client>
. En el ejemplo de código siguiente se muestra la configuración de la aplicación multiplataforma eShop en el método GetClients
que proporciona esta colección en la aplicación de referencia eShop:
public static IEnumerable<Client> GetClients(Dictionary<string,string> clientsUrl)
{
return new List<Client>
{
// Omitted for brevity
new Client
{
ClientId = "maui",
ClientName = "eShop MAUI OpenId Client",
AllowedGrantTypes = GrantTypes.Code,
//Used to retrieve the access token on the back channel.
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { configuration["MauiCallback"] },
RequireConsent = false,
RequirePkce = true,
PostLogoutRedirectUris = { $"{configuration["MauiCallback"]}/Account/Redirecting" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
"orders",
"basket",
"mobileshoppingagg",
"webhooks"
},
//Allow requesting refresh tokens for long lived API access
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
AlwaysIncludeUserClaimsInIdToken = true,
AccessTokenLifetime = 60 * 60 * 2, // 2 hours
IdentityTokenLifetime = 60 * 60 * 2 // 2 hours
}
};
}
Esta configuración especifica los datos de las siguientes propiedades:
Propiedad | Descripción |
---|---|
ClientId |
Un identificador único para el cliente. |
ClientName |
El nombre para mostrar del cliente, que se usa para el registro y la pantalla de consentimiento. |
AllowedGrantTypes |
Especifica cómo un cliente quiere interactuar con IdentityServer. Para obtener más información, consulte Configuración del flujo de autenticación. |
ClientSecrets |
Especifica las credenciales del secreto de cliente que se usan al solicitar tokens desde el punto de conexión del token. |
RedirectUris |
Especifica los URI permitidos a los que se van a devolver tokens o códigos de autorización. |
RequireConsent |
Especifica si se requiere una pantalla de consentimiento. |
RequirePkce |
Especifica si los clientes que usan un código de autorización deben enviar una clave de prueba. |
PostLogoutRedirectUris |
Especifica los URI permitidos a los que se realizará el redireccionamiento después de cerrar la sesión. |
AllowedCorsOrigins |
Especifica el origen del cliente para que IdentityServer pueda permitir llamadas entre orígenes desde el origen. |
AllowedScopes |
Especifica los recursos a los que tiene acceso el cliente. De forma predeterminada, un cliente no tiene acceso a ningún recurso. |
AllowOfflineAccess |
Especifica si el cliente puede solicitar tokens de actualización. |
AllowAccessTokensViaBrowser |
Especifica si el cliente puede recibir tokens de acceso desde una ventana del explorador. |
AlwaysIncludeUserClaimsInIdToken |
Especifica que las notificaciones de usuario siempre se agregarán al token de identificador. De forma predeterminada, estos tendrían que recuperarse mediante el punto de conexión userinfo . |
AccessTokenLifetime |
Especifica la duración del token de acceso en segundos. |
IdentityTokenLifetime |
Especifica la duración del token de identidad en segundos. |
Configuración del flujo de autenticación
El flujo de autenticación entre un cliente y IdentityServer se puede configurar especificando los tipos de concesión en la propiedad Client.AllowedGrantTypes
. Las especificaciones de OpenID Connect y OAuth 2.0 definen varios flujos de autenticación, entre los que se incluyen:
Flujo de autenticación | Descripción |
---|---|
Implícita | Este flujo está optimizado para aplicaciones basadas en el explorador y se debe usar para las solicitudes de solo autenticación de usuario o de autenticación y token de acceso. Todos los tokens se transmiten a través del explorador y, por tanto, no se admiten características avanzadas como los tokens de actualización. |
Código de autorización | Este flujo proporciona la capacidad de recuperar tokens en un canal posterior, en lugar del canal frontal del explorador, a la vez que admite la autenticación de cliente. |
Híbrido | Este flujo es una combinación de los tipos de concesión de código implícito y de autorización. El token de identidad se transmite a través del canal del explorador y contiene la respuesta del protocolo firmado y otros artefactos, como el código de autorización. Después de validar correctamente la respuesta, se debe usar el canal posterior para recuperar el token de acceso y actualización. |
Sugerencia
Considere la posibilidad de usar el flujo de autenticación híbrida. El flujo de autenticación híbrida mitiga varios ataques que se aplican al canal del explorador y es el flujo recomendado para las aplicaciones nativas que desean recuperar tokens de acceso, y posiblemente actualizar tokens.
Para obtener más información sobre los flujos de autenticación, consulte Tipos de concesión en la documentación de IdentityServer.
Realización de la autenticación
Para que IdentityServer emita tokens en nombre de un usuario, el usuario debe iniciar sesión en IdentityServer. Sin embargo, IdentityServer no proporciona una interfaz de usuario ni una base de datos para la autenticación. Por lo tanto, en la aplicación de referencia eShop, ASP.NET Core Identity se usa para este propósito.
La aplicación multiplataforma eShop se autentica con IdentityServer mediante el flujo de autenticación híbrida, que se ilustra en el diagrama siguiente.
Se realiza una solicitud de inicio de sesión a <base endpoint>:5105/connect/authorize
. Después de una autenticación correcta, IdentityServer devuelve una respuesta de autenticación que contiene un código de autorización y un token de identidad. El código de autorización se envía a <base endpoint>:5105/connect/token
, que responde con tokens de acceso, identidad y actualización.
La aplicación multiplataforma eShop cierra la sesión de IdentityServer mediante el envío de una solicitud a <base endpoint>:5105/connect/endsession
con parámetros adicionales. Después de cerrar sesión, IdentityServer responde enviando un URI de redireccionamiento posterior al cierre de sesión a la aplicación multiplataforma. En el diagrama siguiente se ilustra este proceso.
En la aplicación multiplataforma eShop, la clase IdentityService
realiza la comunicación con IdentityServer, que implementa la interfaz IIdentityService
. La interfaz especifica que la clase que realiza la implementación debe proporcionar los métodos SignInAsync
, SignOutAsync
, GetUserInfoAsync
y GetAuthTokenAsync
.
Inicio de sesión
Cuando el usuario pulsa el botón LOGIN
en LoginView
, se ejecuta SignInCommand
en la clase LoginViewModel
, que, a su vez, ejecuta el método SignInAsync
. El siguiente ejemplo de código muestra este método:
[RelayCommand]
private async Task SignInAsync()
{
await IsBusyFor(
async () =>
{
var loginSuccess = await _appEnvironmentService.IdentityService.SignInAsync();
if (loginSuccess)
{
await NavigationService.NavigateToAsync("//Main/Catalog");
}
});
}
Este método invoca el método SignInAsync
en la clase IdentityService
, como se muestra en el ejemplo de código siguiente:
public async Task<bool> SignInAsync()
{
var response = await GetClient().LoginAsync(new LoginRequest()).ConfigureAwait(false);
if (response.IsError)
{
return false;
}
await _settingsService
.SetUserTokenAsync(
new UserToken
{
AccessToken = response.AccessToken,
IdToken = response.IdentityToken,
RefreshToken = response.RefreshToken,
ExpiresAt = response.AccessTokenExpiration
})
.ConfigureAwait(false);
return !response.IsError;
}
El IdentityService
usa el OidcClient
proporcionado con el paquete NuGet IdentityModel.OidcClient
. Este cliente muestra la vista web de autenticación al usuario en la aplicación y captura el resultado de la autenticación. El cliente se conecta al URI para el punto de conexión de autorización de IdentityServer con los parámetros necesarios. El punto de conexión de autorización está en /connect/authorize
en el puerto 5105 del punto de conexión de base expuesto como una configuración del usuario. Para obtener más información sobre la configuración del usuario, consulte Administración de configuración.
Nota:
La superficie expuesta a ataques de la aplicación multiplataforma eShop se reduce mediante la implementación de la clave de prueba para el intercambio de código (PKCE) en OAuth. PKCE protege el código de autorización para que no se use en caso de que se intercepte. Esto se logra mediante el cliente que genera un comprobador de secretos, cuyo hash se pasa en la solicitud de autorización, y que se presenta sin hash al canjear el código de autorización. Para obtener más información sobre PKCE, vea Clave de prueba para intercambio de código por clientes públicos de OAuth en el sitio web de Internet Engineering Task Force.
Si el punto de conexión del token recibe información de autenticación válida, código de autorización válido y un comprobador de secretos PKCE, responde con un token de acceso, un token de identidad y un token de actualización. El token de acceso (que permite el acceso a los recursos de API) y el token de identidad se almacenan como configuración de la aplicación y se realiza la navegación por páginas. Por lo tanto, el efecto general en la aplicación multiplataforma eShop es el siguiente: siempre que los usuarios puedan autenticarse correctamente con IdentityServer, navegan hasta la ruta //Main/Catalog
, que es un elemento TabbedPage
que muestra CatalogView
como su pestaña seleccionada.
Para obtener información sobre la navegación por páginas, consulte Navegación. Para obtener información sobre cómo la navegación de WebView hace que se ejecute un método de modelo de vista, consulte Invocación de navegación mediante comportamientos. Para obtener información sobre la configuración de la aplicación, consulte Administración de configuración.
Nota:
eShop también permite un inicio de sesión ficticio cuando la aplicación está configurada para usar servicios ficticios en SettingsView
. En este modo, la aplicación no se comunica con IdentityServer, sino que permite al usuario iniciar sesión con las credenciales.
Cierre de sesión
Cuando el usuario pulsa el botón LOG OUT
en ProfileView
, se ejecuta LogoutCommand
en la clase ProfileViewModel
, que ejecuta el método LogoutAsync
. Este método realiza la navegación de página a la página LoginView
, pasando un parámetro de consulta Logout
establecido en true
.
Ese parámetro se evalúa en el método ApplyQueryAttributes
. Si el parámetro Logout
está presente con un valor de true
, se ejecuta el método PerformLogoutAsync
de la clase LoginViewModel
, que se muestra en el ejemplo de código siguiente:
private async Task PerformLogoutAsync()
{
await _appEnvironmentService.IdentityService.SignOutAsync();
_settingsService.UseFakeLocation = false;
UserName.Value = string.Empty;
Password.Value = string.Empty;
}
Este método invoca el método SignOutAsync
en la clase IdentityService
, que invoca el OidcClient
para finalizar la sesión del usuario y borra los tokens de usuario guardados. Para más información sobre la configuración de la aplicación, consulte Administración de configuración. El siguiente ejemplo de código muestra el método SignOutAsync
:
public async Task<bool> SignOutAsync()
{
var response = await GetClient().LogoutAsync(new LogoutRequest()).ConfigureAwait(false);
if (response.IsError)
{
return false;
}
await _settingsService.SetUserTokenAsync(default);
return !response.IsError;
}
Este método usa el OidcClient
para llamar al URI al punto de conexión d finalización de la sesión de IdentityServer con los parámetros necesarios. El punto de conexión de finalización de la sesión está en /connect/endsession
en el puerto 5105 del punto de conexión de base expuesto como una configuración del usuario. Una vez que el usuario haya cerrado la sesión correctamente, se mostrará LoginView
y se borrará cualquier información guardada del usuario.
Para obtener información sobre la navegación por páginas, consulte Navegación. Para obtener información sobre cómo la navegación de WebView
hace que se ejecute un método de modelo de vista, consulte Invocación de navegación mediante comportamientos. Para obtener información sobre la configuración de la aplicación, consulte Administración de configuración.
Nota:
eShop también permite un cierre de sesión ficticio cuando la aplicación está configurada para usar servicios ficticios en SettingsView
. En este modo, la aplicación no se comunica con IdentityServer y, en su lugar, borra todos los tokens almacenados de la configuración de la aplicación.
Authorization
Después de la autenticación, las API web de ASP.NET Core a menudo necesitan autorizar el acceso, lo que permite que un servicio haga que las API estén disponibles para algunos usuarios autenticados, pero no para todos.
La restricción del acceso a una ruta de ASP.NET Core se puede lograr mediante la aplicación de un atributo Authorize a un controlador o una acción, que limita el acceso al controlador o la acción a los usuarios autenticados, como se muestra en el ejemplo de código siguiente:
[Authorize]
public sealed class BasketController : Controller
{
// Omitted for brevity
}
Si un usuario no autorizado intenta acceder a un controlador o una acción marcados con el atributo Authorize, el marco API devuelve un código de estado HTTP 401 (unauthorized)
.
Nota
Los parámetros se pueden especificar en el atributo Authorize para restringir una API a usuarios específicos. Para obtener más información, consulte Documentación de ASP.NET Core: Autorización.
IdentityServer se puede integrar en el flujo de trabajo de autorización para que los tokens de acceso proporcionen autorización de control. Este enfoque se muestra en el diagrama siguiente.
La aplicación multiplataforma eShop se comunica con el microservicio de identidad y solicita un token de acceso como parte del proceso de autenticación. A continuación, el token de acceso se reenvía a las API expuestas por los microservicios de pedidos y cesta de la compra como parte de las solicitudes de acceso. Los tokens de acceso contienen información sobre el cliente y el usuario. A continuación, las API usan esa información para autorizar el acceso a sus datos. Para obtener información sobre cómo configurar IdentityServer para proteger las API, consulte Configuración de recursos de API.
Configuración de IdentityServer para realizar la autorización
Para realizar la autorización con IdentityServer, se debe agregar su middleware de autorización a la canalización de solicitudes HTTP de la aplicación web. El middleware se agrega en el método de extensión AddDefaultAuthentication
, que se invoca desde el método AddApplicationServices
en la clase Program
y se muestra en el siguiente ejemplo de código de la aplicación de referencia de eShop:
public static IServiceCollection AddDefaultAuthentication(this IHostApplicationBuilder builder)
{
var services = builder.Services;
var configuration = builder.Configuration;
var identitySection = configuration.GetSection("Identity");
if (!identitySection.Exists())
{
// No identity section, so no authentication
return services;
}
// prevent from mapping "sub" claim to nameidentifier.
JsonWebTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
services.AddAuthentication().AddJwtBearer(options =>
{
var identityUrl = identitySection.GetRequiredValue("Url");
var audience = identitySection.GetRequiredValue("Audience");
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.Audience = audience;
options.TokenValidationParameters.ValidIssuers = [identityUrl];
options.TokenValidationParameters.ValidateAudience = false;
});
services.AddAuthorization();
return services;
}
Este método garantiza que solo se pueda acceder a la API con un token de acceso válido. El middleware valida el token entrante para garantizar que se envía desde un emisor de confianza y valida que el token es válido para usarse con la API que lo recibe. Por lo tanto, la navegación al controlador de pedidos o de la cesta de la compra devolverá un código de estado HTTP 401 (unauthorized)
, que indica que se requiere un token de acceso.
Realización de solicitudes de acceso a las API
Al realizar solicitudes a los microservicios de pedidos y de cesta de la compra, el token de acceso obtenido de IdentityServer durante el proceso de autenticación debe incluirse en la solicitud, como se muestra en el ejemplo de código siguiente:
public async Task CreateOrderAsync(Models.Orders.Order newOrder)
{
var authToken = await _identityService.GetAuthTokenAsync().ConfigureAwait(false);
if (string.IsNullOrEmpty(authToken))
{
return;
}
var uri = $"{UriHelper.CombineUri(_settingsService.GatewayOrdersEndpointBase, ApiUrlBase)}?api-version=1.0";
var success = await _requestProvider.PostAsync(uri, newOrder, authToken, "x-requestid").ConfigureAwait(false);
}
El token de acceso se almacena con la implementación de IIdentityService
y se puede recuperar mediante el método GetAuthTokenAsync
.
Del mismo modo, el token de acceso debe incluirse al enviar datos a una API protegida de IdentityServer, como se muestra en el ejemplo de código siguiente:
public async Task ClearBasketAsync()
{
var authToken = await _identityService.GetAuthTokenAsync().ConfigureAwait(false);
if (string.IsNullOrEmpty(authToken))
{
return;
}
await GetBasketClient().DeleteBasketAsync(new DeleteBasketRequest(), CreateAuthenticationHeaders(authToken))
.ConfigureAwait(false);
}
El token de acceso se recupera del IIdentityService
y se incluye en la llamada al método ClearBasketAsync
de la clase BasketService
.
La clase RequestProvider
de la aplicación multiplataforma eShop usa la clase HttpClient
para realizar solicitudes a las API de RESTful expuestas por la aplicación de referencia eShop. Al realizar solicitudes a las API de pedidos y cesta de la compra, que requieren autorización, se debe incluir un token de acceso válido con la solicitud. Esto se logra agregando el token de acceso a los encabezados de la instancia httpClient, como se muestra en el ejemplo de código siguiente:
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
La propiedad DefaultRequestHeaders
de la clase HttpClient
expone los encabezados que se envían con cada solicitud, y el token de acceso se agrega al encabezado Authorization
cuyo prefijo es la cadena Bearer
. Cuando la solicitud se envía a una API de RESTful, el valor del encabezado Authorization
se extrae y se valida para garantizar que se envía desde un emisor de confianza y se usa para determinar si el usuario tiene permiso para invocar la API que lo recibe.
Para obtener más información sobre cómo la aplicación multiplataforma eShop realiza solicitudes web, consulte Acceso a datos remotos.
Resumen
Hay muchos enfoques para integrar la autenticación y la autorización en una aplicación de .NET MAUI que se comunica con una aplicación web de ASP.NET. La aplicación multiplataforma eShop realiza la autenticación y autorización con un microservicio de identidad contenedorizado que usa IdentityServer. IdentityServer es un marco de código abierto de OpenID Connect y OAuth 2.0 para ASP.NET Core que se integra con ASP.NET Core Identity para realizar la autenticación de tokens de portador.
La aplicación multiplataforma solicita tokens de seguridad de IdentityServer para autenticar a un usuario o acceder a un recurso. Al acceder a un recurso, se debe incluir un token de acceso en la solicitud a las API que requieren autorización. El middleware de IdentityServer valida los tokens de acceso entrantes para garantizar que se envían desde un emisor de confianza y que son válidos para usarlos con la API que los recibe.