JWT(Json Web Token) Cuando?

Sí a alguien esto no le suena a nada, lo primero que le recomendaría sería leer la especificación.

JSON Web Token (JWT)

El objetivo de este post es hacer un breve resumen de lo que es JWT y cuando deberías de utilizarlo.

Lo primero es que no lo veo como un sistema para securizar una api, aunque tengo que reconocer que utilizando “Access control de Azure” lo puedes conseguir.

¿Como yo creo un JWT?

Lo primero es crear un objeto Header básicamente con los siguientes datos, esta claro que lo podéis hacer desde c# o desde el lenguaje donde os sintáis mas felices.

Yo de momento os lo voy a mostrar en Json para no tener que dar vueltas.

{typ:”JWT”,alg:”HS256”}

Sí el token lo emite “Access Control de Azure”  os llega un atributo más que no es otro que el Thumbprint del certificado con las siguientes conversiones y por tanto no encriptaciones.

El Thumprint se muestra como una cadena en Hexadecimal y lo que nos llega es esta convertida a base64UrlEndoced.

Es decir un token desde ACS nos llega así.

{“typ”:”JWT”,”alg”:”RS256″,”x5t”:”LF3aEfMmXEeFkVldf-_WLjVXHHo”}

No voy a entrar de momento a explicar cual es la diferencia en el “alg” puesto que es obvia.

Lo que asusta es encontrarte esto en el Header.

 “x5t”:”LF3aEfMmXEeFkVldf-_WLjVXHHo”

Fácil de resolver búsqueda en Google con los siguientes términos “x5t jwt” y buceando en el siguiente documento JSON Web Token (JWT) – Claims and Signing  nos encontramos con esto.

 

image

Vamos para comérteloSonrisa

The “x5t” (x.509 certificate thumbprint) header parameter provides a base64url encoded SHA-256 thumbprint (a.k.a. digest) of the DER encoding of an X.509 certificate that can be used to match a certificate. This header parameter is OPTIONAL.

Tranquilos, que no pasa nada vamos a utilizar unas sencillos metodos de c# para descubrir esta magia.

Dado el siguiente Thumprint

2C5DDA11F3265C478591595D7FEFD62E35571C7A” vamos a ver como obtenemos esto otro que es lo que nos llega “LF3aEfMmXEeFkVldf-_WLjVXHHo”.

Para ello necesitamos estos helper en c# que nos ayudarán a lo largo del post.

DecodeHesString

image

ConvertHexDigit

image

 

Y por último estos dos métodos sobrecargados para poder convertir a Base64UrlEncode.

image

Sino me he equivocado y después de acceder al certificado que puedes ver desde “Certificados y claves de Acs” y ver esto 2C5DDA11F3265C478591595D7FEFD62E35571C7A podemos ejecutar esta linea en c# y obtener el x5t.

var misterio = Base64UrlEncode( DecodeHexString(“2C5DDA11F3265C478591595D7FEFD62E35571C7A”));

Y la pregunta es ¿Para que se utiliza esto en Acs si es optional el parametro?.

Sencillo, para comprobar que estás validando y no firmando el token JWT con un certificado valido. Es decir el servidor firma con la clave privada y tu validas con la pública, más se hace una comprobación de este dato.

El siguiente paso es jugar con la segunda parte del token y a esto se le llama playload. Mas bien un formato libre donde puede poner una serie de información en el token que después puedo utilizar.

Tenemos que destacar los siguientes claims.

Registered Claim Names

Aparte de estos (Todos OPTIONAL) tu puedes poner los que quieras, más claims evidentemente más información susceptible de ser capturada y por tanto explotada.

Un ejemplo sencillo sería algo como esto.

{“iss”:”joe”,
  “exp”:1300819380,
  “http://example.com/is_root”:true}

Con lo cual una vez conocido el Header y el Playload lo que hacemos es convertir ambos a Base64UrlEncoded que por supuesto no significa más que eso codificar.

Y por tanto fácil de descodificar con lo que obtenemos una serie de caracteres y ambos valores los concatenamos con un “.”

Ejemplo.

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
.
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh

0dHA6Ly9leGFt
cGxlLmNvbS9pc19yb290Ijp0cnVlfQ

Una cosa que nos debe de quedar clara es que esto está codificado y no encriptado, con lo cual es una fuente de información valiosa para obtener email,client-id(Oauth), name, etc,etc.. Es decir cuanto más información incluyas más información expones.

Por último tenemos dos formas de mandar un JWT.

1. PlainText. Simplemtne al final se le agrega un “.” y el algoritmo de encriptación es “node” con lo cual tu token quedaría de la siguiente forma.

Base64UrlEncoded(Header).Base64UrlEndoced(PlayLoad).

En una palabra cualquiera podría reproducir este token a su gusto con poco esfuerzo y os pongo un ejemplo, imaginad por un momento que twitter utilizase esto. Yo hoy soy xxxx y mañana podría ser yyyy y hacer lo que hace yyyy si que el se enterase.

Con lo cual mi recomendación es muy sencilla no se debe de utilizar excepto que sea dentro de tu propia organización sin salir a ningún sitio y te quieras ahorrar el tiempo de encriptar el token.

2. Encrypted JWT.

La forma de generarlo sería igual al anterior pero cumpliendo con el siguiente patrón.

Se cogen los valores devueltos por PlainText  y se codifican con un algoritmo.

HS256,RS256(Recomendado),etc,etc.

Base64UrlEncoded(Header).

Base64UrlEndoced(PlayLoad).

Base64UrlEndoced(hmac(Header+.+PlayLoad))

Vamos a pensar. A partir de este momento cuantos de los algoritmos que se pueden utilizar para encriptación son susceptibles a un ataque del tipo “Force-Brute”. Cuando lo vi por primera vez pensé en esta ecuación de primer grado.

2X=6.

Es decir solo depende de la capacidad de cálculo para que yo sepa cual es tu clave secreta con la que estás firmando los tokens.

Como diría Yoda “Si quieres la luz ver, y conoces dos partes fácil te será encontrar el camino”.

En una palabra, tu no te vas a enterar en la vida que yo voy a hacer un “Force-Brute” puesto que voy a utilizar mi propio token para conocer tu secret key y por tanto poder generar nuevos, siempre que no utilices un certificado.

Ya que en ese caso yo solo conoceré en el caso de Azure(Acs) la clave pública y no la clave secreta, cosa que me va a permitir validar el token y no emitir nuevos tokenSonrisa Bien,Bien…. Pero hasta cuando eso no es vulnerable?

Tuve la suerte de compartir con el amigo @3lcarry la generación de token JWT para integrar nuestro sistema con SalesForce y después integrar con Google Drive.

Ambos utilizan un sistema muy parecido donde después de registrar una app y el administrador dotar a esta de una serie de permisos, tu sin la iteración del usuario puedes hacer cosas en su nombre. Es decir en ningún caso el usuario tiene que autenticarse contra Google o contra SalesForce ni contra ningún proveedor de identidad.

Para entendernos, esas dos plataformas utilizan JWT como mecanismo de autorización Server To Server y ambas me devuelven un token de sesion(access-token) que expira en 3600 segundos y que tienen sus mecanismos de revocación y de refresco enviando un nuevo JWT para obtener un access-.token. Es decir en ningún caso se envia el JWT en la cabecera http.

Lo siguiente que yo me tengo que plantear es como obtengo un “access-token” con los proveedores SalesForce y Google, sencillo se hace un post al servidor desde tu servidor pasando los siguientes parametros.

gran-type:urn:ietf:params:oauth:grant-type:jwt-bearer

assertion:JWT(formado desde tu servidor y enviado a su servidor)

Aparte de esto en la cabecera del post se envía.

Content-Type: application/x-www-form-urlencoded

Vamos que la posiblidad de que alguien sea capaz de generar token haciendo una comunicación Server-To-Server es complicada. Puesto que después de hacer el POST tu ya no trabajas con un JWT sino con un access-token que es igual que un token de Oauth 2.0.

Y ahora la pregunta es porque Azure lo hace diferente, porque te autenticas contra un proveedor de identidad y después de hacer todo el flujo Oauth 2.0 u OpenId en el caso de que el proveedor sea Google. Azure te devuelve un JWT que tu decides pasar a tu Api.

¿Tienes claro que RSA es seguro?

¿Conocidas dos partes podrías descubrir la tercera(clave privada)?

Yo tengo serías dudas de que ha fecha de hoy eso no se pueda obtener.

Con lo cual no me parece un mecanismo acertado utilizar JWT y Acs para aplicaciones web, quizás eso solo está pensado para aplicaciones del tipo Windows 8, Windows Phone y alguno ha malinterpretado su uso, incluso aún siendo para estás dos plataformas, tengo mis miedos, puesto que nadie me impide capturar en ambas el trafico http y por medio de mi token poder generar otros, para otros usuarios. Sigo insistiendo que el firmar el token con un Certificado me está protegiendo de momento, vamos creoSonrisa.

Bueno desmenuzado JWT, sigo pensando exclusivamente en su utilización “SERVER TO SERVER” y con este obtener un access-token  que es el que utilizo en la cabecera de Autorización. Cualquiera puede ser proveedor de JWT.

Podemos inventar lo que se quiera y aplicarlo donde nos plazca, pero acuérdate cada vez que lo pongas en marcha de estas palabras “Force-Brute” o de esta ecuación de primer grado 2x=6.

Repito que luego parece otra cosaSonrisa. El token de ACS excepto que trasmites información delicada del usuario en cada round trip, que es más pesado que un “access-token” y que vas en contra del resto del mundo. Es seguro,hasta donde llegan mis conocimientos para romper una clave privada de un certificado.

Pero aplica la ecuación de primer grado y piensa que tengo mucha información para poder despejar la x y también la necesaria como para saber como se forma PKCS1, lo mismo es cuestión de tiempo.

Otras referencias.

Using OAuth 2.0 for Server to Server Applications

OAuth 2.0 JWT Bearer Token Flow

pure JavaScript implementation of JWT ( JSON Web Token ) and JWS ( JSON Web Signature ) Aquí os podéis divertir un ratoSonrisa.

Cookies vs Tokens. Getting auth right with Angular.JS Yo esto no lo haría en la vida. Si quieres puedes utilizar esto Brute Force c# y probar.

Conclusiones.

Cuando vamos a trabajar como el resto, quizá esté soñando una vez más.

 

 

 

 


 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *