Decodificación y verificación de token JWT utilizando el Sistema.IdentityModel.Token.Jwt
He estado usando la biblioteca JWT para decodificar un token web Json, y me gustaría cambiar a la implementación oficial de JWT de Microsoft, System.IdentityModel.Token.Jwt .
La documentación es muy escasa, así que estoy teniendo dificultades para averiguar cómo lograr lo que he estado haciendo con la biblioteca JWT. Con la biblioteca JWT, hay un método de decodificación que toma el JWT codificado base64 y lo convierte en JSON que luego se puede deserializar. Me gustaría hacer algo similar usando el sistema.IdentityModel.Token.Jwt, pero después de una buena cantidad de excavación, no puede averiguar cómo.
Por si sirve de algo, estoy leyendo el token JWT de una cookie, para usarlo con el marco de identidad de Google.
Cualquier ayuda sería apreciada.
2 answers
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 método ReadToken(String)
que tomará su cadena JWT codificada en base64 y devuelve 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, esto contendrá un único objeto ClaimsIdentity
que tiene un conjunto de afirmaciones que representan las propiedades del JWT original.
JwtSecurityTokenHandler
define algunas sobrecargas adicionales para ValidateToken
, en particular, tiene una sobrecarga ClaimsPrincipal ValidateToken(JwtSecurityToken, TokenValidationParameters)
. El argumento TokenValidationParameters
le permite especificar el certificado de firma de token (como una lista de X509SecurityTokens
). También tiene una sobrecarga que toma el JWT como un string
en lugar de un SecurityToken
.
El código para hacer esto es bastante complicado, pero se puede encontrar en Global.asax.cx code (TokenValidationHandler
class) en el ejemplo de desarrollador llamado " ADAL - Native App to REST service-Authentication con ACS vía Browser Dialog", 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 las reclamaciones contenidas 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 procesar del token. Depende de su escenario que se acercan más adecuado.
La documentación general (es decir, no específica de JWT) 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 WIF exactamente como cualquier otro controlador.
Hay 3 muestras de ella en uso en diferentes tipos de aplicación at
Probablemente, uno satisfará sus necesidades o al menos será adaptable a ellas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-20 15:56:42
Me pregunto por qué usar algunas bibliotecas para la decodificación y verificación de tokens JWT.
El token JWT codificado se puede crear usando después del 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 prescindir de 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 decodificación del token es una versión invertida del código above.To verifique la firma que necesitará para la misma y compare la parte de firma con la firma calculada.
ACTUALIZACIÓN: Para aquellos cómo son luchando cómo hacer base64 urlsafe codificación / decodificación por favor ver otro ASÍ pregunta , y también wiki y RFC
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-24 17:48:15