Autenticación JWT simple en ASP.NET Core 1.0 Web API

Estoy buscando la forma más sencilla de configurar un servidor de API web que use JWT para la autenticación en ASP.NET Core (también conocido como ASP.NET 5). Este proyecto ( blog post / github ) hace exactamente lo que estoy buscando pero usa ASP.NET 4.

Solo quiero poder:

  1. configura una ruta de inicio de sesión que puede crear un token JWT y devolverlo en el encabezado. Estoy integrando esto con un servicio RESTful existente que me dirá si el nombre de usuario y la contraseña son válidos. En el proyecto ASP.NET 4 estoy viendo que esto podría hacerse con la siguiente ruta https://github.com/stewartm83/Jwt-WebApi/blob/master/src/JwtWebApi/Controllers/AccountController.cs#L24- L54

  2. Interceptar las solicitudes entrantes a las rutas que requieren autorización, descifrar y validar el token JWT que viene en el encabezado y hacer que la información del usuario en la carga útil del token JWT sea accesible para la ruta. por ejemplo, algo como esto: https://github.com/stewartm83/Jwt-WebApi/blob/master/src/JwtWebApi/App_Start/AuthHandler.cs

Todos los ejemplos que he visto en ASP.NET Core son muy complejos y dependen de algunos o todos OAuth, IS, OpenIddict y EF que me gustaría evitar.

¿Puede alguien señalarme un ejemplo de cómo hacer esto en ASP.NET Core o ayudarme a comenzar con esto?

EDITAR: Respondo Terminé usando esta respuesta: https://stackoverflow.com/a/33217340/373655

Nota / Actualización:

El siguiente código fue para .NET Core 1.1
Dado que .NET Core 1 era muy RTM, la autenticación cambió con el salto de .NET Core 1 a 2.0 (también conocido como [¿parcialmente?] Corregido con cambios de última hora).
Es por eso que el código de abajo ya no funciona con .NET Core 2.0.
Pero todavía será una lectura útil.

Actualización 2018

Mientras tanto, puede encontrar un ejemplo de trabajo de ASP.NET Core 2.0 JWT-Cookie-Authentication en mi repository de prueba de github . Se completa con una implementación de la clase abstracta MS-RSA y MS-ECDSA con BouncyCastle y un generador de claves para RSA y ECDSA.


Nigromancia
Profundicé en JWT. Aquí están mis hallazgos:

Necesita agregar Microsoft.AspNetCore.Authentication.JwtBearer

entonces puedes establecer

app.UseJwtBearerAuthentication(bearerOptions); 

en Startup.cs => Configurar

donde bearerOptions es definido por usted, por ejemplo, como

 var bearerOptions = new JwtBearerOptions() { AutomaticAuthenticate = true, AutomaticChallenge = true, TokenValidationParameters = tokenValidationParameters, Events = new CustomBearerEvents() }; // Optional // bearerOptions.SecurityTokenValidators.Clear(); // bearerOptions.SecurityTokenValidators.Add(new MyTokenHandler()); 

donde CustomBearerEvents es el lugar donde puede agregar datos de token a httpContext / Route

 // https://github.com/aspnet/Security/blob/master/src/Microsoft.AspNetCore.Authentication.JwtBearer/Events/JwtBearerEvents.cs public class CustomBearerEvents : Microsoft.AspNetCore.Authentication.JwtBearer.IJwtBearerEvents { ///  /// Invoked if exceptions are thrown during request processing. The exceptions will be re-thrown after this event unless suppressed. ///  public Func OnAuthenticationFailed { get; set; } = context => Task.FromResult(0); ///  /// Invoked when a protocol message is first received. ///  public Func OnMessageReceived { get; set; } = context => Task.FromResult(0); ///  /// Invoked after the security token has passed validation and a ClaimsIdentity has been generated. ///  public Func OnTokenValidated { get; set; } = context => Task.FromResult(0); ///  /// Invoked before a challenge is sent back to the caller. ///  public Func OnChallenge { get; set; } = context => Task.FromResult(0); Task IJwtBearerEvents.AuthenticationFailed(AuthenticationFailedContext context) { return OnAuthenticationFailed(context); } Task IJwtBearerEvents.Challenge(JwtBearerChallengeContext context) { return OnChallenge(context); } Task IJwtBearerEvents.MessageReceived(MessageReceivedContext context) { return OnMessageReceived(context); } Task IJwtBearerEvents.TokenValidated(TokenValidatedContext context) { return OnTokenValidated(context); } } 

Y tokenValidationParameters lo define usted, por ejemplo

 var tokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters { // The signing key must match! ValidateIssuerSigningKey = true, IssuerSigningKey = signingKey, // Validate the JWT Issuer (iss) claim ValidateIssuer = true, ValidIssuer = "ExampleIssuer", // Validate the JWT Audience (aud) claim ValidateAudience = true, ValidAudience = "ExampleAudience", // Validate the token expiry ValidateLifetime = true, // If you want to allow a certain amount of clock drift, set that here: ClockSkew = TimeSpan.Zero, }; 

Y MyTokenHandler es opcionalmente definido por usted, si desea personalizar la validación de tokens, por ejemplo

 // https://gist.github.com/pmhsfelix/4151369 public class MyTokenHandler : Microsoft.IdentityModel.Tokens.ISecurityTokenValidator { private int m_MaximumTokenByteSize; public MyTokenHandler() { } bool ISecurityTokenValidator.CanValidateToken { get { // throw new NotImplementedException(); return true; } } int ISecurityTokenValidator.MaximumTokenSizeInBytes { get { return this.m_MaximumTokenByteSize; } set { this.m_MaximumTokenByteSize = value; } } bool ISecurityTokenValidator.CanReadToken(string securityToken) { System.Console.WriteLine(securityToken); return true; } ClaimsPrincipal ISecurityTokenValidator.ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) { JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler(); // validatedToken = new JwtSecurityToken(securityToken); try { tokenHandler.ValidateToken(securityToken, validationParameters, out validatedToken); validatedToken = new JwtSecurityToken("jwtEncodedString"); } catch (Exception ex) { System.Console.WriteLine(ex.Message); throw; } ClaimsPrincipal principal = null; // SecurityToken validToken = null; validatedToken = null; System.Collections.Generic.List ls = new System.Collections.Generic.List(); ls.Add( new System.Security.Claims.Claim( System.Security.Claims.ClaimTypes.Name, "IcanHazUsr_éèêëïàáâäåãæóòôöõõúùûüñçø_ÉÈÊËÏÀÁÂÄÅÃÆÓÒÔÖÕÕÚÙÛÜÑÇØ 你好,世界 Привет\tмир" , System.Security.Claims.ClaimValueTypes.String ) ); // System.Security.Claims.ClaimsIdentity id = new System.Security.Claims.ClaimsIdentity("authenticationType"); id.AddClaims(ls); principal = new System.Security.Claims.ClaimsPrincipal(id); return principal; throw new NotImplementedException(); } } 

La parte difícil es cómo obtener AsymmetricSecurityKey, porque no desea pasar un rsaCryptoServiceProvider, porque necesita interoperabilidad en formato criptográfico.

La creación sigue las líneas de

 // System.Security.Cryptography.X509Certificates.X509Certificate2 cert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(byte[] rawData); System.Security.Cryptography.X509Certificates.X509Certificate2 cert2 = DotNetUtilities.CreateX509Cert2("mycert"); Microsoft.IdentityModel.Tokens.SecurityKey secKey = new X509SecurityKey(cert2); 

por ejemplo, con BouncyCastle de un certificado DER:

  // http://stackoverflow.com/questions/36942094/how-can-i-generate-a-self-signed-cert-without-using-obsolete-bouncycastle-1-7-0 public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateX509Cert2(string certName) { var keypairgen = new Org.BouncyCastle.Crypto.Generators.RsaKeyPairGenerator(); keypairgen.Init(new Org.BouncyCastle.Crypto.KeyGenerationParameters( new Org.BouncyCastle.Security.SecureRandom( new Org.BouncyCastle.Crypto.Prng.CryptoApiRandomGenerator() ) , 1024 ) ); Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keypair = keypairgen.GenerateKeyPair(); // --- Until here we generate a keypair var random = new Org.BouncyCastle.Security.SecureRandom( new Org.BouncyCastle.Crypto.Prng.CryptoApiRandomGenerator() ); // SHA1WITHRSA // SHA256WITHRSA // SHA384WITHRSA // SHA512WITHRSA // SHA1WITHECDSA // SHA224WITHECDSA // SHA256WITHECDSA // SHA384WITHECDSA // SHA512WITHECDSA Org.BouncyCastle.Crypto.ISignatureFactory signatureFactory = new Org.BouncyCastle.Crypto.Operators.Asn1SignatureFactory("SHA512WITHRSA", keypair.Private, random) ; var gen = new Org.BouncyCastle.X509.X509V3CertificateGenerator(); var CN = new Org.BouncyCastle.Asn1.X509.X509Name("CN=" + certName); var SN = Org.BouncyCastle.Math.BigInteger.ProbablePrime(120, new Random()); gen.SetSerialNumber(SN); gen.SetSubjectDN(CN); gen.SetIssuerDN(CN); gen.SetNotAfter(DateTime.Now.AddYears(1)); gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0))); gen.SetPublicKey(keypair.Public); // -- Are these necessary ? // public static readonly DerObjectIdentifier AuthorityKeyIdentifier = new DerObjectIdentifier("2.5.29.35"); // OID value: 2.5.29.35 // OID description: id-ce-authorityKeyIdentifier // This extension may be used either as a certificate or CRL extension. // It identifies the public key to be used to verify the signature on this certificate or CRL. // It enables distinct keys used by the same CA to be distinguished (eg, as key updating occurs). // http://stackoverflow.com/questions/14930381/generating-x509-certificate-using-bouncy-castle-java gen.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityKeyIdentifier.Id, false, new Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier( Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keypair.Public), new Org.BouncyCastle.Asn1.X509.GeneralNames(new Org.BouncyCastle.Asn1.X509.GeneralName(CN)), SN )); // OID value: 1.3.6.1.5.5.7.3.1 // OID description: Indicates that a certificate can be used as an SSL server certificate. gen.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage.Id, false, new Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage(new ArrayList() { new Org.BouncyCastle.Asn1.DerObjectIdentifier("1.3.6.1.5.5.7.3.1") })); // -- End are these necessary ? Org.BouncyCastle.X509.X509Certificate bouncyCert = gen.Generate(signatureFactory); byte[] ba = bouncyCert.GetEncoded(); System.Security.Cryptography.X509Certificates.X509Certificate2 msCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(ba); return msCert; } 

Posteriormente, puede agregar un formato de cookie personalizado que contenga el JWT-Bearer:

 app.UseCookieAuthentication(new CookieAuthenticationOptions() { AuthenticationScheme = "MyCookieMiddlewareInstance", CookieName = "SecurityByObscurityDoesntWork", ExpireTimeSpan = new System.TimeSpan(15, 0, 0), LoginPath = new Microsoft.AspNetCore.Http.PathString("/Account/Unauthorized/"), AccessDeniedPath = new Microsoft.AspNetCore.Http.PathString("/Account/Forbidden/"), AutomaticAuthenticate = true, AutomaticChallenge = true, CookieSecure = Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest, CookieHttpOnly = false, TicketDataFormat = new CustomJwtDataFormat("foo", tokenValidationParameters) // DataProtectionProvider = null, // DataProtectionProvider = new DataProtectionProvider(new System.IO.DirectoryInfo(@"c:\shared-auth-ticket-keys\"), //delegate (DataProtectionConfiguration options) //{ // var op = new Microsoft.AspNet.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptionOptions(); // op.EncryptionAlgorithm = Microsoft.AspNet.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_256_GCM: // options.UseCryptographicAlgorithms(op); //} //), }); 

Donde CustomJwtDataFormat es algo similar a

 public class CustomJwtDataFormat : ISecureDataFormat { private readonly string algorithm; private readonly TokenValidationParameters validationParameters; public CustomJwtDataFormat(string algorithm, TokenValidationParameters validationParameters) { this.algorithm = algorithm; this.validationParameters = validationParameters; } // This ISecureDataFormat implementation is decode-only string ISecureDataFormat.Protect(AuthenticationTicket data) { return MyProtect(data, null); } string ISecureDataFormat.Protect(AuthenticationTicket data, string purpose) { return MyProtect(data, purpose); } AuthenticationTicket ISecureDataFormat.Unprotect(string protectedText) { return MyUnprotect(protectedText, null); } AuthenticationTicket ISecureDataFormat.Unprotect(string protectedText, string purpose) { return MyUnprotect(protectedText, purpose); } private string MyProtect(AuthenticationTicket data, string purpose) { return "wadehadedudada"; throw new System.NotImplementedException(); } // http://blogs.microsoft.co.il/sasha/2012/01/20/aggressive-inlining-in-the-clr-45-jit/ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] private AuthenticationTicket MyUnprotect(string protectedText, string purpose) { JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler(); ClaimsPrincipal principal = null; SecurityToken validToken = null; System.Collections.Generic.List ls = new System.Collections.Generic.List(); ls.Add( new System.Security.Claims.Claim( System.Security.Claims.ClaimTypes.Name, "IcanHazUsr_éèêëïàáâäåãæóòôöõõúùûüñçø_ÉÈÊËÏÀÁÂÄÅÃÆÓÒÔÖÕÕÚÙÛÜÑÇØ 你好,世界 Привет\tмир" , System.Security.Claims.ClaimValueTypes.String ) ); // System.Security.Claims.ClaimsIdentity id = new System.Security.Claims.ClaimsIdentity("authenticationType"); id.AddClaims(ls); principal = new System.Security.Claims.ClaimsPrincipal(id); return new AuthenticationTicket(principal, new AuthenticationProperties(), "MyCookieMiddlewareInstance"); try { principal = handler.ValidateToken(protectedText, this.validationParameters, out validToken); JwtSecurityToken validJwt = validToken as JwtSecurityToken; if (validJwt == null) { throw new System.ArgumentException("Invalid JWT"); } if (!validJwt.Header.Alg.Equals(algorithm, System.StringComparison.Ordinal)) { throw new System.ArgumentException($"Algorithm must be '{algorithm}'"); } // Additional custom validation of JWT claims here (if any) } catch (SecurityTokenValidationException) { return null; } catch (System.ArgumentException) { return null; } // Validation passed. Return a valid AuthenticationTicket: return new AuthenticationTicket(principal, new AuthenticationProperties(), "MyCookieMiddlewareInstance"); } } 

Y también puede crear el token JWT con Microsoft.IdentityModel.Token:

 // https://github.com/aspnet/Security/blob/master/src/Microsoft.AspNetCore.Authentication.JwtBearer/Events/IJwtBearerEvents.cs // http://codereview.stackexchange.com/questions/45974/web-api-2-authentication-with-jwt public class TokenMaker { class SecurityConstants { public static string TokenIssuer; public static string TokenAudience; public static int TokenLifetimeMinutes; } public static string IssueToken() { SecurityKey sSKey = null; var claimList = new List() { new Claim(ClaimTypes.Name, "userName"), new Claim(ClaimTypes.Role, "role") //Not sure what this is for }; JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler(); SecurityTokenDescriptor desc = makeSecurityTokenDescriptor(sSKey, claimList); // JwtSecurityToken tok = tokenHandler.CreateJwtSecurityToken(desc); return tokenHandler.CreateEncodedJwt(desc); } public static ClaimsPrincipal ValidateJwtToken(string jwtToken) { SecurityKey sSKey = null; var tokenHandler = new JwtSecurityTokenHandler(); // Parse JWT from the Base64UrlEncoded wire form //(..) JwtSecurityToken parsedJwt = tokenHandler.ReadToken(jwtToken) as JwtSecurityToken; TokenValidationParameters validationParams = new TokenValidationParameters() { RequireExpirationTime = true, ValidAudience = SecurityConstants.TokenAudience, ValidIssuers = new List() { SecurityConstants.TokenIssuer }, ValidateIssuerSigningKey = true, ValidateLifetime = true, IssuerSigningKey = sSKey, }; SecurityToken secT; return tokenHandler.ValidateToken("token", validationParams, out secT); } private static SecurityTokenDescriptor makeSecurityTokenDescriptor(SecurityKey sSKey, List claimList) { var now = DateTime.UtcNow; Claim[] claims = claimList.ToArray(); return new Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor { Subject = new ClaimsIdentity(claims), Issuer = SecurityConstants.TokenIssuer, Audience = SecurityConstants.TokenAudience, IssuedAt = System.DateTime.UtcNow, Expires = System.DateTime.UtcNow.AddMinutes(SecurityConstants.TokenLifetimeMinutes), NotBefore = System.DateTime.UtcNow.AddTicks(-1), SigningCredentials = new SigningCredentials(sSKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.EcdsaSha512Signature) }; } } 

Tenga en cuenta que dado que puede asignar un usuario diferente en la cookie frente a los encabezados http (al portador), o cualquier otro método de autenticación que especifique, ¡puede tener MÁS de 1 usuario!


Mira esto:
https://stormpath.com/blog/token-authentication-asp-net-core

debería ser exactamente lo que estás buscando.

También están estos dos:

https://goblincoding.com/2016/07/03/issuing-and-authenticating-jwt-tokens-in-asp-net-core-webapi-part-i/

https://goblincoding.com/2016/07/07/issuing-and-authenticating-jwt-tokens-in-asp-net-core-webapi-part-ii/

y éste
http://blog.novanet.no/hooking-up-asp-net-core-1-rc1-web-api-with-auth0-bearer-tokens/

Y las fonts de JWT-Bearer https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer


Si necesita seguridad ultra alta, debe protegerse contra ataques de repetición renovando el ticket en cada solicitud e invalidar tickets viejos después de un tiempo de espera determinado y después de que el usuario cierre la sesión (no solo después de la caducidad de la validez).


Para aquellos de ustedes que terminan aquí desde google, pueden implementar un TicketDataFormat en la autenticación de cookies cuando quieran usar su propia versión de JWT.

Tuve que buscar trabajo en JWT, porque necesitábamos asegurar nuestra aplicación.
Debido a que todavía tenía que usar .NET 2.0, tuve que escribir mi propia biblioteca.

He transferido el resultado de eso a .NET Core este fin de semana. Lo encontrará aquí: https://github.com/ststeiger/Jwt_Net20/tree/master/CoreJWT

No utiliza ninguna base de datos, ese no es el trabajo de una biblioteca de JWT.
Obtener y establecer datos de DB es su trabajo.
La biblioteca permite la autorización y verificación de JWT en .NET Core con todos los algoritmos especificados en el JWT RFC enumerados en la asignación IANA JOSE .
En cuanto a agregar autorización a la tubería y agregar valores a la ruta, estas son dos cosas que deben hacerse por separado, y creo que es mejor que lo haga usted mismo.

Puede usar autenticación personalizada en ASP.NET Core.
Consulte la categoría “Seguridad” de documentos en docs.asp.net.

O puede consultar el Middleware de cookies sin la identidad ASP.NET o en una autorización personalizada basada en políticas .

También puede obtener más información en el taller de autenticación en github o en la sección de inicio de sesión social o en este video tutorial de canal 9 .
Si todo lo demás falla, el código fuente de la seguridad asp.net está en github .


El proyecto original para .NET 3.5, que es de donde se deriva mi biblioteca, está aquí:
https://github.com/jwt-dotnet/jwt
Eliminé todas las referencias a los métodos de extensión LINQ +, porque no son compatibles con .NET 2.0. Si incluye LINQ o ExtensionAttribute en el código fuente, entonces no puede simplemente cambiar el tiempo de ejecución .NET sin recibir advertencias; es por eso que los he eliminado completamente.
Además, he agregado los métodos RSA + ECSD JWS, por esa razón, el proyecto CoreJWT depende de BouncyCastle.
Si se limita a HMAC-SHA256 + HMAC-SHA384 + HMAC-SHA512, puede eliminar BouncyCastle.

JWE aún no es compatible.

El uso es como jwt-dotnet / jwt, excepto que cambié el espacio de nombres JWT a CoreJWT .
También agregué una copia interna de PetaJSON como serializador, por lo que no hay interferencia con las dependencias del proyecto de otras personas.

Crea un token JWT:

 var payload = new Dictionary() { { "claim1", 0 }, { "claim2", "claim2-value" } }; var secretKey = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk"; string token = JWT.JsonWebToken.Encode(payload, secretKey, JWT.JwtHashAlgorithm.HS256); Console.WriteLine(token); 

Verificar un token JWT:

 var token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjbGFpbTEiOjAsImNsYWltMiI6ImNsYWltMi12YWx1ZSJ9.8pwBI_HtXqI3UgQHQ_rDRnSQRxFL1SR8fbQoS-5kM5s"; var secretKey = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk"; try { string jsonPayload = JWT.JsonWebToken.Decode(token, secretKey); Console.WriteLine(jsonPayload); } catch (JWT.SignatureVerificationException) { Console.WriteLine("Invalid token!"); } 

Para RSA y ECSA, deberá pasar la clave privada (BouncyCastle) RSA / ECSD en lugar de la clave secreta.

 namespace BouncyJWT { public class JwtKey { public byte[] MacKeyBytes; public Org.BouncyCastle.Crypto.AsymmetricKeyParameter RsaPrivateKey; public Org.BouncyCastle.Crypto.Parameters.ECPrivateKeyParameters EcPrivateKey; public string MacKey { get { return System.Text.Encoding.UTF8.GetString(this.MacKeyBytes); } set { this.MacKeyBytes = System.Text.Encoding.UTF8.GetBytes(value); } } public JwtKey() { } public JwtKey(string macKey) { this.MacKey = macKey; } public JwtKey(byte[] macKey) { this.MacKeyBytes = macKey; } public JwtKey(Org.BouncyCastle.Crypto.AsymmetricKeyParameter rsaPrivateKey) { this.RsaPrivateKey = rsaPrivateKey; } public JwtKey(Org.BouncyCastle.Crypto.Parameters.ECPrivateKeyParameters ecPrivateKey) { this.EcPrivateKey = ecPrivateKey; } } } 

Para saber cómo generar / exportar / importar claves RSA / ECSD con BouncyCastle, consulte el proyecto llamado “BouncyCastleTests” en el mismo repository. Dejo que usted almacene y recupere de forma segura sus propias claves privadas RSA / ECSD.

Verifiqué los resultados de mi biblioteca para HMAC-ShaXXX y RSA-XXX con JWT.io, parece que están bien.
ECSD también debería estar bien, pero no lo probé en contra de nada.
No hice pruebas exhaustivas de todos modos, para su información.

La opción más fácil que he encontrado hasta ahora es OpenIddict . Usted dice que quiere evitar Entity Framework y OpenIddict; entonces usted mismo hará una gran cantidad de códigos, reescribiendo efectivamente partes de OpenIddict y ASOS (que usa OpenIddict) para hacer lo que están haciendo de todos modos.

Si estás bien usando OpenIddict, esta es prácticamente toda la configuración que necesitarás a continuación. Es muy sencillo.

Si no quieres usar EF, eso es posible con OpenIddict. No estoy seguro de cómo, pero eso es lo que tendrás que descubrir.

ConfigureServices:

 services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders() .AddOpenIddictCore(config => config.UseEntityFramework()); // this line is for OpenIddict 

Configurar

 app.UseOpenIddictCore(builder => { // tell openiddict you're wanting to use jwt tokens builder.Options.UseJwtTokens(); // NOTE: for dev consumption only! for live, this is not encouraged! builder.Options.AllowInsecureHttp = true; builder.Options.ApplicationCanDisplayErrors = true; }); // use jwt bearer authentication app.UseJwtBearerAuthentication(options => { options.AutomaticAuthenticate = true; options.AutomaticChallenge = true; options.RequireHttpsMetadata = false; // these urls must match the value sent in the payload posted from the client side during login options.Audience = "http://localhost:58292/"; options.Authority = "http://localhost:58292/"; }); 

Hay una o dos cosas menores, como su DbContext necesita derivar de OpenIddictContext .

Puedes ver una explicación completa (incluidos enlaces al repository github) en esta publicación del blog: http://capesean.co.za/blog/asp-net-5-jwt-tokens/

Si todo lo que necesita es autenticación contra un proveedor externo de OAuth / OpenID (como Google, GitHub, Facebook, cuenta de Microsoft, etc.), entonces no necesita herramientas de terceros.

Los proveedores de autenticación para los proveedores de OAuth y OpenID más utilizados ya cuentan con ASP.NET Core en los paquetes Microsoft.AspNetCore.Authorization.* . Consulte las muestras proporcionadas en el repository GitHub del repository ” Seguridad ”

Si necesita crear sus propios tokens JWT, entonces necesita un servidor OAuth / OpenID. OpenIddict es un servidor de autorización fácil de configurar. Para esto necesita alguna forma de base de datos, ya que los proveedores externos se usarán para autenticar a la persona, pero también necesita que tengan una cuenta en su servidor de autorización.

Si necesita más personalización y más control del flujo, tiene que usar ASOS o IdentityServer4 (actualmente solo es compatible con ASP.NET Core cuando se trabaja en conjunto con .NET Framework o Mono. El tiempo de ejecución de Core aún no es compatible, por lo que sé .

También hay un Gitter Chatroom para OpenIddict en https://gitter.im/openiddict/core y https://gitter.im/aspnet-contrib/AspNet.Security.OpenIdConnect.Server para ASOS.

Hay un ejemplo completo para ASP.NET Core + JWT Auth + SQL Server + Swagger: https://github.com/wilsonwu/netcoreauth

Espero que esto le pueda ayudar.

Protección de la API web ASP.NET Core 2.0 con autenticación JWT Bearer token estándar

https://fullstackmark.com/post/13/jwt-authentication-with-aspnet-core-2-web-api-angular-5-net-core-identity-and-facebook-login

y aplique el filtro autorizar de la siguiente manera

  [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]