Estoy trabajando con la aplicación ASP.NET Core. Estoy tratando de implementar la autenticación basada en tokens, pero no puedo entender cómo usar el nuevo sistema de seguridad para mi caso. Revisé ejemplos, pero no me ayudaron mucho, están utilizando autenticación de cookies o autenticación externa (GitHub, Microsoft, Twitter).
Cuál es mi escenario: la aplicación angularjs debe solicitar el /token
paso del nombre de usuario y contraseña de la URL WebApi debe autorizar al usuario y devolver lo access_token
que será utilizado por la aplicación angularjs en las siguientes solicitudes.
Encontré un excelente artículo sobre la implementación de exactamente lo que necesito en la versión actual de ASP.NET: autenticación basada en tokens utilizando ASP.NET Web API 2, Owin e Identity . Pero no es obvio para mí cómo hacer lo mismo en ASP.NET Core.
Mi pregunta es: ¿cómo configurar la aplicación ASP.NET Core WebApi para que funcione con autenticación basada en token?
Respuestas:
Actualización para .Net Core 3.1:
David Fowler (arquitecto del equipo de ASP .NET Core) ha reunido un conjunto increíblemente simple de aplicaciones de tareas, incluida una aplicación simple que demuestra JWT . Pronto incorporaré sus actualizaciones y estilo simplista a esta publicación.
Actualizado para .Net Core 2:
Las versiones anteriores de esta respuesta usaban RSA; Realmente no es necesario si el mismo código que genera los tokens también verifica los tokens. Sin embargo, si está distribuyendo la responsabilidad, es probable que aún desee hacerlo utilizando una instancia de
Microsoft.IdentityModel.Tokens.RsaSecurityKey
.Crea algunas constantes que usaremos más adelante; esto es lo que hice:
Agregue esto a su Startup.cs's
ConfigureServices
. Usaremos la inyección de dependencia más tarde para acceder a esta configuración. Supongo queauthenticationConfiguration
es un objetoConfigurationSection
uConfiguration
tal que puede tener una configuración diferente para la depuración y la producción. ¡Asegúrese de guardar su clave de forma segura! Puede ser cualquier cadena.He visto otras respuestas cambiar otras configuraciones, como
ClockSkew
; los valores predeterminados están configurados de tal manera que deberían funcionar para entornos distribuidos cuyos relojes no están exactamente sincronizados. Estas son las únicas configuraciones que necesita cambiar.Configurar autenticación. Debería tener esta línea antes de cualquier middleware que requiera su
User
información, comoapp.UseMvc()
.Tenga en cuenta que esto no hará que su token se emita con el
SignInManager
o cualquier otra cosa. Deberá proporcionar su propio mecanismo para generar su JWT; consulte a continuación.Es posible que desee especificar un
AuthorizationPolicy
. Esto le permitirá especificar controladores y acciones que solo permiten tokens de portador como autenticación utilizando[Authorize("Bearer")]
.Aquí viene la parte difícil: construir el token.
Luego, en su controlador donde desea su token, algo como lo siguiente:
Aquí, supongo que ya tienes un director. Si está utilizando Identity, puede usarlo
IUserClaimsPrincipalFactory<>
para transformarloUser
en aClaimsPrincipal
.Para probarlo : Obtener una ficha, ponerlo en la forma en jwt.io . ¡Las instrucciones que proporcioné anteriormente también le permiten usar el secreto de su configuración para validar la firma!
Si estaba renderizando esto en una vista parcial en su página HTML en combinación con la autenticación de solo portador en .Net 4.5, ahora puede usar a
ViewComponent
para hacer lo mismo. Es casi lo mismo que el código de acción del controlador anterior.fuente
IOptions<OAuthBearerAuthenticationOptions>
para usar las Opciones; el uso de un objeto Opciones directamente no es compatible debido a la configuración con nombre que es compatible con el marco del Modelo de opciones.Trabajando a partir de la fabulosa respuesta de Matt Dekrey , he creado un ejemplo completamente funcional de autenticación basada en token, trabajando contra ASP.NET Core (1.0.1). Puede encontrar el código completo en este repositorio en GitHub (ramas alternativas para 1.0.0-rc1 , beta8 , beta7 ), pero en resumen, los pasos importantes son:
Genere una clave para su aplicación
En mi ejemplo, genero una clave aleatoria cada vez que se inicia la aplicación, tendrá que generar una y almacenarla en algún lugar y proporcionarla a su aplicación. Vea este archivo para saber cómo estoy generando una clave aleatoria y cómo podría importarla desde un archivo .json . Como se sugiere en los comentarios de @kspearrin, la API de protección de datos parece un candidato ideal para administrar las claves "correctamente", pero aún no he resuelto si eso es posible. ¡Envíe una solicitud de extracción si lo resuelve!
Startup.cs - ConfigureServices
Aquí, necesitamos cargar una clave privada para que se firmen nuestros tokens, que también usaremos para verificar los tokens a medida que se presentan. Estamos almacenando la clave en una variable de nivel de clase
key
que reutilizaremos en el método de configuración a continuación. TokenAuthOptions es una clase simple que contiene la identidad de firma, la audiencia y el emisor que necesitaremos en TokenController para crear nuestras claves.También hemos establecido una política de autorización que nos permite usar
[Authorize("Bearer")]
en los puntos finales y clases que deseamos proteger.Startup.cs - Configurar
Aquí, necesitamos configurar JwtBearerAuthentication:
TokenController
En el controlador de token, debe tener un método para generar claves firmadas utilizando la clave que se cargó en Startup.cs. Hemos registrado una instancia de TokenAuthOptions en Startup, por lo que debemos inyectarla en el constructor de TokenController:
Luego, deberá generar el token en su controlador para el punto final de inicio de sesión, en mi ejemplo, estoy tomando un nombre de usuario y contraseña y validando los que usan una instrucción if, pero lo clave que debe hacer es crear o cargar un reclamo basada en identidad y generar el token para eso:
Y eso debería ser. Simplemente agregue
[Authorize("Bearer")]
a cualquier método o clase que desee proteger, y debería obtener un error si intenta acceder sin un token presente. Si desea devolver un error 401 en lugar de 500, deberá registrar un controlador de excepción personalizado como lo he hecho en mi ejemplo aquí .fuente
Puede echar un vistazo a las muestras de conexión de OpenId que ilustran cómo tratar con diferentes mecanismos de autenticación, incluidos los tokens JWT:
https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Samples
Si observa el proyecto Cordova Backend, la configuración de la API es la siguiente:
También vale la pena echar un vistazo a la lógica en /Providers/AuthorizationProvider.cs y el RessourceController de ese proyecto;).
Alternativamente, también puede usar el siguiente código para validar los tokens (también hay un fragmento para que funcione con signalR):
Para emitir un token, puede usar los paquetes del servidor openId Connect de la siguiente manera:
EDITAR: he implementado una aplicación de una sola página con implementación de autenticación basada en token utilizando el marco front-end de Aurelia y el núcleo ASP.NET. También hay una señal R de conexión persistente. Sin embargo, no he hecho ninguna implementación de DB. El código se puede ver aquí: https://github.com/alexandre-spieser/AureliaAspNetCoreAuth
Espero que esto ayude,
Mejor,
Alex
fuente
Eche un vistazo a OpenIddict: es un nuevo proyecto (en el momento de la escritura) que facilita la configuración de la creación de tokens JWT y la actualización de tokens en ASP.NET 5. La validación de los tokens es manejada por otro software.
Suponiendo que el uso
Identity
deEntity Framework
la última línea es lo que se agrega a suConfigureServices
método:En
Configure
, configura OpenIddict para servir tokens JWT:También configura la validación de tokens en
Configure
:Hay una o dos cosas menores, como que su DbContext necesita derivarse de OpenIddictContext.
Puedes ver una explicación completa en esta publicación de blog: http://capesean.co.za/blog/asp-net-5-jwt-tokens/
Una demostración funcional está disponible en: https://github.com/capesean/openiddict-test
fuente