.net - libreria - Descifrando y verificando el token JWT usando System.IdentityModel.Tokens.Jwt
libreria jwt (2)
He estado usando la biblioteca JWT para decodificar un Token web Json, y me gustaría cambiar a la implementación JWT oficial de Microsoft, System.IdentityModel.Tokens.Jwt .
La documentación es muy escasa, así que me está costando trabajo imaginar cómo lograr lo que he estado haciendo con la biblioteca JWT. Con la biblioteca JWT, hay un método Decode que toma el JWT codificado en base64 y lo convierte en JSON, que luego puede deserializarse. Me gustaría hacer algo similar utilizando System.IdentityModel.Tokens.Jwt, pero después de una buena cantidad de tareas de excavación, no puedo entender cómo.
Por lo que vale, estoy leyendo el token JWT de una cookie, para usar con el marco de identidad de Google.
Cualquier ayuda sería apreciada.
Me pregunto por qué usar algunas bibliotecas para la descodificación y verificación de tokens JWT.
El token JWT codificado se puede crear usando el siguiente pseudocódigo
var headers = base64URLencode(myHeaders);
var claims = base64URLencode(myClaims);
var payload = header + "." + claims;
var signature = base64URLencode(HMACSHA256(payload, secret));
var encodedJWT = payload + "." + signature;
Es muy fácil de hacer sin una biblioteca específica. Usando el siguiente código:
using System;
using System.Text;
using System.Security.Cryptography;
public class Program
{
// More info: https://stormpath.com/blog/jwt-the-right-way/
public static void Main()
{
var header = "{/"typ/":/"JWT/",/"alg/":/"HS256/"}";
var claims = "{/"sub/":/"1047986/",/"email/":/"[email protected]/",/"given_name/":/"John/",/"family_name/":/"Doe/",/"primarysid/":/"b521a2af99bfdc65e04010ac1d046ff5/",/"iss/":/"http://example.com/",/"aud/":/"myapp/",/"exp/":1460555281,/"nbf/":1457963281}";
var b64header = Convert.ToBase64String(Encoding.UTF8.GetBytes(header))
.Replace(''+'', ''-'')
.Replace(''/'', ''_'')
.Replace("=", "");
var b64claims = Convert.ToBase64String(Encoding.UTF8.GetBytes(claims))
.Replace(''+'', ''-'')
.Replace(''/'', ''_'')
.Replace("=", "");
var payload = b64header + "." + b64claims;
Console.WriteLine("JWT without sig: " + payload);
byte[] key = Convert.FromBase64String("mPorwQB8kMDNQeeYO35KOrMMFn6rFVmbIohBphJPnp4=");
byte[] message = Encoding.UTF8.GetBytes(payload);
string sig = Convert.ToBase64String(HashHMAC(key, message))
.Replace(''+'', ''-'')
.Replace(''/'', ''_'')
.Replace("=", "");
Console.WriteLine("JWT with signature: " + payload + "." + sig);
}
private static byte[] HashHMAC(byte[] key, byte[] message)
{
var hash = new HMACSHA256(key);
return hash.ComputeHash(message);
}
}
La descodificación del token es una versión invertida del código anterior. Para verificar la firma, necesitará la misma y compare la parte de la firma con la firma calculada.
ACTUALIZACIÓN: Para quienes están luchando cómo hacer la codificación / decodificación de seguridad en la base64 por favor vea otra pregunta de SO , y también wiki y RFCs
Dentro del paquete hay una clase llamada JwtSecurityTokenHandler
que deriva de System.IdentityModel.Tokens.SecurityTokenHandler
. En WIF esta es la clase principal para deserializar y serializar tokens de seguridad.
La clase tiene un ReadToken(String)
que tomará su cadena JWT codificada en base64 y devolverá un SecurityToken
que representa el JWT.
El SecurityTokenHandler
también tiene un método ValidateToken(SecurityToken)
que toma su SecurityToken
y crea un ReadOnlyCollection<ClaimsIdentity>
. Por lo general, para JWT, este contendrá un único objeto ClaimsIdentity
que tiene un conjunto de declaraciones que representan las propiedades del JWT original.
JwtSecurityTokenHandler
define algunas sobrecargas adicionales para ValidateToken
, en particular, tiene una ClaimsPrincipal ValidateToken(JwtSecurityToken, TokenValidationParameters)
. El argumento TokenValidationParameters
permite especificar el certificado de firma de token (como una lista de X509SecurityTokens
). También tiene una sobrecarga que toma el JWT como una string
lugar de un SecurityToken
.
El código para hacer esto es bastante complicado, pero se puede encontrar en el código Global.asax.cx (clase TokenValidationHandler
) en la muestra del desarrollador llamada "ADAL - Aplicación nativa para el servicio REST - Autenticación con ACS a través del diálogo del navegador", ubicado en
http://code.msdn.microsoft.com/AAL-Native-App-to-REST-de57f2cc
Alternativamente, la clase JwtSecurityToken
tiene métodos adicionales que no están en la clase base SecurityToken
, como una propiedad Claims
que obtiene los reclamos contenidos sin pasar por la colección ClaimsIdentity
. También tiene una propiedad Payload
que devuelve un objeto JwtPayload
que le permite obtener el JSON sin formato del token. Depende de su escenario, que enfoque más apropiado.
La documentación general (es decir, no JWT específica) para la clase SecurityTokenHandler
está en
http://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.securitytokenhandler.aspx
Dependiendo de su aplicación, puede configurar el controlador JWT en la canalización de WIF exactamente como cualquier otro controlador.
Hay 3 muestras de este en uso en diferentes tipos de aplicaciones en
Probablemente, uno satisfará sus necesidades o al menos se adaptará a ellos.