@tpp/jt
v1.2.0
Published
A simpler and more secure JSON (web) Token
Downloads
3
Readme
JT - Simpler, more secure Json Web Token
The JSON web token (JWT) is a very nice way of sharing information securely between services in a web app. However, it currently suffers from a couple of security issues that make it less secure than needed.
Also the JSON web token (JWT) standard is very well documented and really easy to implement, so this is the implementation that removes the discussed security flaws.
JT Structure
The JT Structure consists of three parts separated by dots (.
), which are:
- Header
- Payload
- Signature
Therefore, a JT typically looks like the following:
xxxx.yyyy.zzzz
Let’s break down the different parts.
Header
The header consists of the meta data about the token. Specifically the following fields:
{
iss: <issuer>,
sub: <subject>,
exp: <expiration>,
}
All of which are mandatory and used to validate the token. Any additional fields can also be added if desired. Then, this JSON is Base64Url encoded to form the first part of the JT.
Payload
The second part of the token is the actual payload - the data that the token contains.
An example payload could be:
{
name: "ralph rambo",
pic: "https://pics.com/ralph-profile-pic.png",
tz: "UTC−03"
}
The payload is then Base64Url encoded to form the second part of the JT.
Do note that for signed tokens this information, though protected against tampering, is readable by anyone. Do not put secret information in the payload or header elements of a JT unless it is encrypted.
Signature
To create the signature part we take the encoded header, the encoded payload, a secret and sign that using HMAC SHA256.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
The signature is used to verify the message wasn't changed along the way, and, in the case of tokens signed with a private key, it can also verify that the sender of the JT is who it says it is.
Putting all together
The output is three Base64-URL strings separated by dots that can be easily passed in HTML and HTTP environments and easy to use and understand.
Usage
Creating the token
const jt = require("@tpp/jt")
jt.token({
iss: "authSvc",
sub: "userRoles",
exp: jt.exp.days(2), // expires in 2 days
}, {
name: "Ralph Rambo"
roles: ["badass"],
},
"my secret key", (err, token) => ...)
Getting valid token data
jt.check(token, "my secret key", (err, payload, header) => ...)
jt.check(token, "my secret key", "authSvc", (err, payload, header) => ...)
jt.check(token, "my secret key", "authSvc", "userRoles", (err, payload, header) => ...)
// err => null (ok)
"invalid header"
"invalid format"
"invalid signature"
"expired"
"bad issuer"
"bad subject"
// payload => { name: "Ralph Rambo", roles: ["badass"] }
// header => { iss: "authSvc", sub: "userRoles", exp: 1630730447160 }
You can also simply decode the token without checking it you desire:
jt.decode(token, (err, payload, header) => ...)
Expiry
Some helper functions are provided to set the expiry easily:
header = {
...
exp: jt.exp.ms(100), // expires in 100 milliseconds
}
// Also
exp: jt.exp.secs(10), // expires in 10 seconds
exp: jt.exp.mins(30), // expires in 30 minutes
exp: jt.exp.hours(2), // expires in 2 hours
exp: jt.exp.days(7), // expires in 7 days