En esta publicación, se examina la nueva compatibilidad con la identidad principal de ASP.NET incorporada en .NET 8 mediante puntos de conexión de API, facilitando así la realización de funciones básicas de identidad, como el registro de usuarios. Estos puntos de conexión representan opciones API como alternativa a la «interfaz de usuario predeterminada» que ha estado disponible con la identidad principal de ASP.NET a lo largo del tiempo. Se ilustrará cómo utilizar estas API para interactuar con las API protegidas de la aplicación.
¿Qué es ASP.NET Core Identity y por qué necesitamos APIs?
ASP.NET Core Identity se presenta como una capa o marco adicional integrado con ASP.NET Core, suministrando una diversidad de servicios para la gestión de cuentas de usuario en su aplicación ASP.NET Core. Este conjunto comprende tanto las abstracciones como las implementaciones por defecto para cada servicio.
A través de ASP.NET Core Identity, se tiene la capacidad de almacenar cuentas de usuario en su aplicación, gestionar los detalles del usuario, activar la autenticación de dos factores y vincular inicios de sesión de terceros con los usuarios. Fundamentalmente, implica la conservación de cuentas de usuario en su aplicación y la utilización de esas cuentas para llevar a cabo el inicio de sesión.
Data Model: los tipos fundamentales del modelo de identidad principal de ASP.NET. Incluye tipos como entity UserId y idIdentityRole.
Stores: la capa de persistencia para almacenar y recuperar instancias de los tipos de modelos de datos. Incluye interfaces como IUserStore<> y IRoleStore<>, así como una gran cantidad de interfaces detalladas, como IUserPasswordStore<>, IUserAuthenticatorKeyStore<> etc.
Administradores: proporcionan una capa de servicio en la parte superior de las tiendas para administrar usuarios. Hay tres abstracciones principales:
- UserManager: realiza operaciones de nivel relativamente alto en los usuarios, como crear un usuario a partir de un nombre de usuario y un correo electrónico, tener cuidado de aplicar hash a la contraseña, generar nombres normalizados, actualizar sellos de seguridad, etc.
- RoleManager: similar a UserManager, realiza operaciones de alto nivel relacionadas con roles, como agregar o quitar notificaciones de un rol.
- SignInManager: proporciona API de alto nivel para iniciar y cerrar sesión de usuarios, validar códigos de dos factores, verificar el bloqueo de cuentas, etc
Los administradores ofrecen API de un nivel relativamente alto para la interacción con Identity, no obstante, aún es necesario invocar las interfaces para su uso, por ejemplo. Para facilitar esta etapa, Microsoft ha suministrado durante un extenso período un paquete de interfaz de usuario predeterminado, Microsoft.AspNetCore.Identity.UI, que incorpora más de 30 páginas de Razor diseñadas para trabajar con Identity. Este conjunto comprende páginas para el inicio y cierre de sesión, páginas para cambiar su correo electrónico y contraseña, páginas para habilitar y administrar códigos de autenticación de factor de remolque (2FA), entre otras.
La abundante cantidad de código que introduce la interfaz de usuario por defecto (y, por lo tanto, le evita escribir) resulta impresionante. Puede integrar este código en su aplicación mediante la herramienta de andamiaje (mostrada anteriormente) para permitir la personalización de las páginas y, de esta manera, obtener una comprensión real de la magnitud de lo que está sucediendo aquí. Intentar implementar todo esto por sí mismo normalmente sería una empresa insensata.
Desafortunadamente, esto lo coloca en una posición incómoda. Si desea utilizar ASP.NET Identity principal para almacenar cuentas de usuario en la aplicación, se encuentra limitado a una de las tres rutas principales:
- Use la interfaz de usuario predeterminada de Razor Pages tal cual. Eso significa que estás atascado con el estilo predeterminado, aparte de cualquier cosa que puedas tematizar a nivel global. Está bien para juguetes, o incluso para aplicaciones internas, pero no es genial para nada más.
- Aplica scaffolding a la interfaz de usuario predeterminada de Razor Pages y, a continuación, personalizar las plantillas de Razor. Esto significa que puede tener un estilo personalizado, pero hay muchas páginas que actualizar y mantener actualizado el código con scaffolding es difícil.
- Cree toda la interfaz de usuario usted mismo. Son muchas páginas para crear. Y es mejor que esperes no introducir ningún error, dado que las páginas de inicio de sesión y cuenta son probablemente las partes más sensibles de tu aplicación.
Ninguna de estas opciones resulta especialmente atractiva. Además, si se está creando una aplicación móvil o una SPA con Blazor (o JavaScript), se produce una discrepancia técnica y mental entre las páginas de identidad que utilizan Razor Pages y el resto de la aplicación. Además, no se debe pasar por alto que no existía un método para emitir tokens al portador con el propósito de su utilización en dispositivos móviles (o aplicaciones SPA, si no se utiliza el patrón BFF).
Es en este punto donde entran en juego los innovadores puntos de conexión de la API de identidad.
Nuevos puntos de conexión de la API de identidad
.NET 8, se han incorporado aplicaciones auxiliares a ASP.NET Core para agregar puntos de conexión de API mínimos vinculados con la identidad en la aplicación. Estos puntos de conexión son prácticamente equivalentes a las páginas predeterminadas de la interfaz de usuario de Razor Pages. Esto resuelve dos casos de uso fundamentales.
Ahora puede desarrollar fácilmente su propia interfaz de usuario en la aplicación de SPA que utiliza las API. De esta manera, el estilo de la interfaz de usuario de identidad/cuentas de la aplicación se mantiene alineado con el resto de la aplicación. Puede emitir tokens de acceso para que los utilice la aplicación SPA o una aplicación móvil al llamar a otras API en la aplicación principal de ASP.NET.
Los beneficios del primer punto son bastante evidentes, pero vale la pena explorar más a fondo este último aspecto.
En el contexto de la interfaz de usuario predeterminada de Razor Pages, se realiza el inicio de sesión mediante un nombre de usuario y una contraseña, y la aplicación inicia sesión al configurar una cookie de autenticación. La configuración de esa cookie es el resultado del proceso de inicio de sesión.
No obstante, las cookies en las aplicaciones móviles suelen ser complicadas de gestionar. Es considerablemente más sencillo utilizar la autenticación de token de portador en su lugar y almacenar un token de acceso. Con la interfaz de usuario predeterminada de Razor Pages, eso no era realmente posible, pero recuperar un token es sencillo con las API de identidad:
POST http://localhost:5117/account/login Content-Type: application/json { "username": "andrew@example.com", "password": "SuperSecret1!" }
Este punto de conexión ofrece una respuesta JSON similar a la siguiente (he acortado los tokens por razones de concisión).
{ "token_type": "Bearer", "access_token": "CfDJ8CuDyfVIT-VKm_2z2YS9T0jen4IyKKwsovVDRrrFyC_nU4HRXbiOjkOr64HnnXYT35pCnWdVXaE32Ztu6PgKhwawiTLLy9J5AYFVF3j9S9SEYoibQQyQ5L7pu", "expires_in": 3600, "refresh_token": "CfDJ8CuDyfVIT-VKm_2z2YS9T0gvL1EYfbVBnppccNrI6WrfRcsOb7LHPTC6VewrV8UUsARjkdFT5CPj_ofGTGWw_gWtsPtfKDjrlLqeYfvmYllWJ8-LssInwA_fn" }
El token de acceso tiene una vigencia relativamente corta (se puede ajustar mediante la configuración), pero el cliente puede obtener un nuevo token a través del incluido refresh_token en la respuesta y emplearlo para obtener uno fresco. Todo esto es bastante estándar, pero anteriormente no estaba integrado en ASP.NET Core Identity.
Consideraciones y limitaciones de diseño
Como era de esperar, hay varias limitaciones y consideraciones al utilizar estas API. Lo primero en lo que hay que pensar es en cómo operan estas API. En esencia, utilizan exactamente las mismas API que la interfaz de usuario de identidad predeterminada. Esto implica que si ya tiene una implementación de identidad, debería poder conectar estos puntos de conexión sin demasiada dificultad.
Una característica importante a tener en cuenta es que el token de acceso devuelto por el punto de conexión de identidad no es un JWT. Básicamente, el token contiene exactamente la misma información que la cookie de identidad en la interfaz de usuario predeterminada. Esto facilita la implementación del punto final, pero también proporciona información sobre la finalidad de estas API.
En particular, los puntos de conexión de identidad no están destinados a reemplazar a los servidores de tokens IdentityServer u OpenIddict. Los tokens de acceso generados por el punto de conexión de identidad están diseñados para ser utilizados exclusivamente por esa aplicación. Además, están concebidos para ser utilizados por usuarios interactivos, no para la comunicación de máquina a máquina.
En este sentido, es posible utilizar los puntos de conexión de identidad dentro de una implementación de IdentityServer. La interacción entre IdentityServer y ASP.NET Core Identity suele generar confusión, así que planeo hacer una publicación aclarando esto y explorando la integración de los puntos finales de Identity en un futuro próximo.
Si se está estableciendo una combinación simple de back-end + SPA, los recién implementados puntos de conexión de identidad pueden parecer una opción fácil. No obstante, si está desarrollando algo más significativo, podría ser sensato considerar un servidor OpenID Connect como IdentityServer.
Cabe destacar que optar por utilizar los puntos de conexión de la API de identidad con un token de portador conlleva diversas limitaciones, riesgos de suplantación y vulnerabilidades, en comparación con la utilización del enfoque establecido de «cookies para autenticación + OIDC para aplicaciones». Ampliaré estos aspectos en una futura publicación, pero es crucial tener en cuenta que emplear los puntos de conexión de identidad para algo más que un proyecto de pasatiempo puede entrañar riesgos.
Conclusiones
En resumen, hemos explorado la nueva compatibilidad con la identidad principal de ASP.NET integrada en .NET 8, presentando puntos de conexión de API que simplifican las funciones esenciales de identidad, como el registro de usuarios. Esta evolución representa una alternativa a la tradicional «interfaz de usuario predeterminada» de la identidad principal de ASP.NET. En la próxima entrega, profundizaremos en la implementación práctica de estas API, detallando cómo interactuar con las funciones protegidas de la aplicación. Este análisis previo sienta las bases para una comprensión más completa y eficaz de la integración de la identidad principal en el desarrollo de aplicaciones con .NET 8. ¡No te pierdas la siguiente entrega donde veremos la implementación en acción!