with net example asp c# asp.net authentication asp.net-web-api asp.net-core

c# - example - Autenticación JWT simple en API web ASP.NET Core 1.0



jwt authentication with asp net core 2 web api (6)

Aquí hay un paquete que

  • ¡Hace que la integración de JWT Bearer Token Security en su aplicación Asp Net Core 2.0+ sea muy sencilla!
  • Integración de autenticación de Azure Active Directory.
  • Integración de autenticación de Facebook.
  • Además, la integración de interfaz de usuario Swagger!

Se llama AspNetCore.Security.Jwt

GitHub:

https://github.com/VeritasSoftware/AspNetCore.Security.Jwt

El paquete integra el token portador JWT en su aplicación de la siguiente manera:

1. Implemente una interfaz de autenticación IA en su aplicación

using AspNetCore.Security.Jwt; using System.Threading.Tasks; namespace XXX.API { public class Authenticator : IAuthentication { public async Task<bool> IsValidUser(string id, string password) { //Put your id authenication here. return true; } } }

2. En tu Startup.cs

using AspNetCore.Security.Jwt; using Swashbuckle.AspNetCore.Swagger; . . public void ConfigureServices(IServiceCollection services) { . . services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = "XXX API", Version = "v1" }); }); services.AddSecurity<Authenticator>(this.Configuration, true); services.AddMvc().AddSecurity(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { . . . // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), // specifying the Swagger JSON endpoint. app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "XXX API V1"); }); app.UseSecurity(true); app.UseMvc(); }

3. En su appsettings.json

Nota: - Puede poner esta configuración en Secret Manager utilizando el menú Administrar secretos de usuario (haga clic con el botón derecho en su Proyecto).

{ "SecuritySettings": { "Secret": "a secret that needs to be at least 16 characters long", "Issuer": "your app", "Audience": "the client of your app", "IdType": "Name", "TokenExpiryInHours" : 2 }, . . . }

Entonces obtendrá puntos finales automáticamente:

/simbólico

/Facebook

Cuando llame a estos puntos finales y se autentique correctamente, obtendrá un token de portador JWT.

En su controlador que desea asegurar

Debe marcar el controlador o la acción que desea proteger con el atributo Autorizar, como:

using Microsoft.AspNetCore.Mvc; . . . namespace XXX.API.Controllers { using Microsoft.AspNetCore.Authorization; [Authorize] [Route("api/[controller]")] public class XXXController : Controller { . . . } }

En Swagger UI, verá automáticamente estos puntos finales.

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

Solo quiero poder:

  1. configurar una ruta de inicio de sesión que pueda 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 que estoy viendo, esto podría hacerse con la siguiente ruta https://github.com/stewartm83/Jwt-WebApi/blob/master/src/JwtWebApi/Controllers/AccountController.cs#L24-L54

  2. Intercepte las solicitudes entrantes a rutas que requieren autorización, descifre y valide el token JWT que viene en el encabezado y haga 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 se basan en algunos o todos los OAuth, IS, OpenIddict y EF que me gustaría evitar.

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

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



La opción más fácil que he encontrado hasta ahora es OpenIddict . Dices que quieres evitar Entity Framework y OpenIddict, entonces estarás codificando mucho, reescribiendo efectivamente partes de OpenIddict y ASOS (que OpenIddict usa) para hacer lo que están haciendo de todos modos.

Si está de acuerdo con OpenIddict, esta es prácticamente toda la configuración que necesitará, a continuación. Es muy sencillo.

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

ConfigureServices:

services.AddIdentity<ApplicationUser, ApplicationRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders() .AddOpenIddictCore<Application>(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 que su DbContext debe derivar de OpenIddictContext<ApplicationUser, Application, ApplicationRole, string> .

Puede ver una explicación completa (incluidos enlaces al repositorio de github) en esta publicación de 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 repositorio GitHub del repositorio " Security "

Si necesita crear sus propios tokens JWT, necesita un servidor OAuth / OpenID. OpenIddict es un servidor de autorización fácil de configurar. Para esto, necesita algún tipo de base de datos, ya que se utilizarán proveedores externos 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, debe usar ASOS o IdentityServer4 (actualmente solo se admite en ASP.NET Core cuando se trabaja con .NET Framework o Mono. El tiempo de ejecución de Core aún no es compatible hasta donde yo sé .

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


Nota / Actualización:

El siguiente código fue para .NET Core 1.1
Dado que .NET Core 1 era tan RTM, la autenticación cambió con el salto de .NET Core 1 a 2.0 (también conocido como [¿parcialmente?] Solucionado con cambios importantes).
Es por eso que el siguiente código ya no funciona con .NET Core 2.0.
Pero seguirá siendo una lectura útil.

Actualización 2018

Mientras tanto, puede encontrar un ejemplo de funcionamiento de ASP.NET Core 2.0 JWT-Cookie-Authentication en mi repositorio de prueba de github . Viene completo 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
Excavaba más en JWT. Aquí están mis hallazgos:

Necesita agregar Microsoft.AspNetCore.Authentication.JwtBearer

entonces puedes configurar

app.UseJwtBearerAuthentication(bearerOptions);

en Startup.cs => Configurar

donde bearerOptions lo define 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 { /// <summary> /// Invoked if exceptions are thrown during request processing. The exceptions will be re-thrown after this event unless suppressed. /// </summary> public Func<AuthenticationFailedContext, Task> OnAuthenticationFailed { get; set; } = context => Task.FromResult(0); /// <summary> /// Invoked when a protocol message is first received. /// </summary> public Func<MessageReceivedContext, Task> OnMessageReceived { get; set; } = context => Task.FromResult(0); /// <summary> /// Invoked after the security token has passed validation and a ClaimsIdentity has been generated. /// </summary> public Func<TokenValidatedContext, Task> OnTokenValidated { get; set; } = context => Task.FromResult(0); /// <summary> /// Invoked before a challenge is sent back to the caller. /// </summary> public Func<JwtBearerChallengeContext, Task> 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, p. Ej.

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 está opcionalmente definido por usted, si desea personalizar la validación de token, 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<System.Security.Claims.Claim> ls = new System.Collections.Generic.List<System.Security.Claims.Claim>(); 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 la 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://.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 (e.g., as key updating occurs). // http://.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 portador JWT:

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<AuthenticationTicket> { 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<AuthenticationTicket>.Protect(AuthenticationTicket data) { return MyProtect(data, null); } string ISecureDataFormat<AuthenticationTicket>.Protect(AuthenticationTicket data, string purpose) { return MyProtect(data, purpose); } AuthenticationTicket ISecureDataFormat<AuthenticationTicket>.Unprotect(string protectedText) { return MyUnprotect(protectedText, null); } AuthenticationTicket ISecureDataFormat<AuthenticationTicket>.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<System.Security.Claims.Claim> ls = new System.Collections.Generic.List<System.Security.Claims.Claim>(); 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<Claim>() { 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 //(<Base64UrlEncoded header>.<Base64UrlEncoded body>.<signature>) JwtSecurityToken parsedJwt = tokenHandler.ReadToken(jwtToken) as JwtSecurityToken; TokenValidationParameters validationParams = new TokenValidationParameters() { RequireExpirationTime = true, ValidAudience = SecurityConstants.TokenAudience, ValidIssuers = new List<string>() { SecurityConstants.TokenIssuer }, ValidateIssuerSigningKey = true, ValidateLifetime = true, IssuerSigningKey = sSKey, }; SecurityToken secT; return tokenHandler.ValidateToken("token", validationParams, out secT); } private static SecurityTokenDescriptor makeSecurityTokenDescriptor(SecurityKey sSKey, List<Claim> 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 debido a que puede proporcionar un usuario diferente en la cookie frente a los encabezados http (Bearer), o cualquier otro método de autenticación que especifique, en realidad 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 hay 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 fuentes de JWT-Bearer https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer

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

Para aquellos de ustedes que terminan aquí a través de 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.
Como todavía tenía que usar .NET 2.0, tenía que escribir mi propia biblioteca.

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

No utiliza ninguna base de datos, ese no es el trabajo de una biblioteca JWT.
Obtener y configurar 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 RFC de JWT 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.
Busque en la categoría "Seguridad" de documentos en docs.asp.net.

O puede buscar en el Middleware de cookies sin identidad ASP.NET o en la 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 del canal 9 .
Si todo lo demás falla, el código fuente de seguridad de asp.net está en github .

El proyecto original para .NET 3.5, que es de donde 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, no puede cambiar el tiempo de ejecución de .NET sin recibir advertencias; Es por eso que los he eliminado por completo.
Además, agregué métodos RSA + ECSD JWS, por eso el proyecto CoreJWT depende de BouncyCastle.
Si se limita a HMAC-SHA256 + HMAC-SHA384 + HMAC-SHA512, puede eliminar BouncyCastle.

JWE no es (todavía) 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, para que no haya interferencia con las dependencias del proyecto de otras personas.

Crear un token JWT:

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

Verifique 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 secretKey.

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 repositorio. Te dejo guardar y recuperar de forma segura tus 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.
El ECSD también debería estar bien, pero no lo probé con nada.
No realicé pruebas exhaustivas de todos modos, para su información.