JSON Web Token (JWT
) is an open standard (RFC
7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.
JWTs can be signed using a secret (with the HMAC
algorithm) or a public/private key pair using RSA
or ECDSA
.
Although JWTs can be encrypted to also provide secrecy between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.
In its compact form, JSON Web Tokens consist of three parts separated by dots (.), which are:
-
Header
: The header typically consists of two parts: the type of the token, which is
JWT
, and the signing algorithm being used, such asHMAC
SHA256 orRSA
. - Payload : The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. You can learn more about claims and its types here
-
Signature
: To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.
Read more about
JWT
signing algorithms.
Therefore, a JWT
typically looks like the following.
xxxxx.yyyyy.zzzzz
1 Building a token
Tokens can be generated using a the builder pattern as follows:
new Ax.crypt.jwt.Builder() .addUser('user_xxxx') .setExpiration(new Date()) .signWith(Ax.crypt.jwt.Builder.Algorithm.HS256, "MYSECRET-KEY") .build()
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c3IiOiJ1c2VyX3h4eHgiLCJleHAiOjE2MjM3NjI3NTh9.xNv0+mp8d6FrAcjClmhnuKwlw6f2CQY/jRIY7OFFc70=
Allowed signing are algorithm are defined in
Ax.crypt.jwt.Builder.Algorithm
:
- HS256
- HS384
- HS512
- RS256
- RS384
- RS512
- NONE
Algorithms prefixed with "HS" use a symetric key, whereas "RS256" uses a private key to sign and a public key for verification
Signing with an algorithm RS*
requires
the use of a private key:
var kp = new Ax.crypt.KeyPair("RSA", 2048); // sign with keys new Ax.crypt.jwt.Builder() .addUser('user_xxxx') .setExpiration(new Date(new Date().getTime() + 3600*1000 )) .signWith(Ax.crypt.jwt.Builder.Algorithm.RS256, kp.getRawPrivateKey()) .build()
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c3IiOiJ1c2VyX3h4eHgiLCJleHAiOjE2MjM3NjU4ODl9.sQhxhd3kVjzJhm/wD54C8IO1Az6mp5zFsbn6jZO4zYuIY57PACOCRBgxGB6Wuy3ZuzSjGnvb0uYbVGBHDKXtB48SD67si1B8+K89vhDipmHYcavvyDSfW+ogtnqjLJ2b0HSs5K6YGcgLU/Pg25Lv9Eng/ubLTSguIJbc/mqSQLqL9BeVb2zLiO3jLCicPVl5+trh538Qan/tA2PwiQmcIZNY/1deO7yHcX0NbyZwJSgBJK6+aTAHFizRiGXa60dN7GmAaiJscIZQvdSx7S6kAq8EyDBsF0ENE72Y1nn7ZaPAyQwRkdbtBNGyO1AiUnqxbTM4sPSGEou0TyI4Dk+dqw==
2 Parsing a token
To parse a token we need to specify the secret key:
new Ax.crypt.jwt.Parser() .setSigningKey('MYSECRET-KEY') .parse('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c3IiOiJ1c2VyX3h4eHgiLCJleHAiOjE2MjM3NjI3NTh9.xNv0+mp8d6FrAcjClmhnuKwlw6f2CQY/jRIY7OFFc70=')
{
"usr": "user_xxxx",
"exp": 1.623766597E9
}
parse() function returns a map with the claims of the token