Kitten JWT
Keep It Simple, Stupid, Secure and Fast JWT module
Philosophy and why
- Keep it Simple Stupid
- Performance & Security focused
- Light, low dependency
Most of the time, people uses node-jsonwebtoken and express-jwt without using a cache mechanism
to verify tokens. This requires a lot of CPU for each request on server-side!
On client-side, the token is generated once with an infinite expiration timestamp, which is not very secure.
The first purpose of this module is to solve these two problems.
When discovering JWT, you do not know what signing algorithm to choose and where to put your data (issuer, audience, ...).
This module solves this for you. It chooses a highly secured algorithm by default. If you want another algorithm, fork it.
The algorithm used (asymmetric) allow the client to generate himself a token without having to exchange a secret with the server.
Only the public key is exchanged.
To save extra bandwidth, it let you define only two parameters : a client id ("Alice", issuer), and a server id ("Bob", audience).
The generated token allows only Alice (clientId) to speak exclusively to Bob (serverId).
Main purpose : be plug'n'play for developers who do not have a lot of time.
Features
- Follows JWT RFC
- Ultra-fast JWT generator with automatic renewal every 12-hours for client side: 1 Million per second
- Ultra-fast JWT verification using LRU-cache for server side: 0.5 Million per second
- Fastify, Restify or Express authentication middleware
- Highly secured by default with assymetric ECDSA keys (ES512)
- ECDSA Public / Private key generator
Installation
npm install kitten-jwt --save
Getting started
1) On client-side
Using request
module for example:
var jwt = require('kitten-jwt');
var token = jwt.getToken('client-id-1220202', 'server-app-name', 'privKeyOfTheClient');
request.setHeader('Authorization', 'Bearer ' + token);
Or, if your client is a browser, store the JWT in a cookie
instead of Authorization
header.
With ExpressJS
:
response.cookie('access_token', token);
2) On server-side
var jwt = require('kitten-jwt');
function getPublicKeyFn(req, res, payload, callback) {
var _clientId = payload.iss;
return callback('pubKeyOfTheClient');
}
express().use(jwt.verifyHTTPHeaderFn('server-app-name', getPublicKeyFn));
jwt.resetCache();
console.log(req.jwtPayload);
API Usage
Token generated by kitten-jwt are quite compact (limited) for performance reasons, and follows JWT RFC
{
alg : 'ES512',
typ : JWT
}
{
iss : clientId,
aud : serverId,
exp : (Date.now() + expiresIn)
}
Why it is important to have a serverId? If the audience is not defined, the same token
can be used for another web-service which have the same clientId and public key.
High-level API
These functions uses cache to be as fast as possible
-
jwt.getToken (clientId, serverId, privKey)
Generate a token for the tuple clientId-serverId, which expires in about 12 hours (+- random)
Re-use this same token during about 12 hours if called more than twice
Generate a new token automatically before expiration (20-minute before) or if privKey change
- clientId : JWT issuer, token.iss
- serverId : JWT audience, token.aud
- privKey : private key
-
jwt.verifyHTTPHeaderFn (serverId, getPublicKeyFn)
Generate a middleware function(req, req, next)
Verify and set req.jwtPayload
- getPublicKeyFn : Function(req, res, payload, callback) which must call the
callback(String|Array)
where
the parameter is either a string (one public key) or an array of strings (mutliple public key to test)
- serverId : JWT audience, token.aud
if the token is invalid, next(err) is called. Thus you can catch the error in another 4-parameter middlewares.
-
jwt.resetCache (clientId, callback)
: invalidate cache
Low-level API
These APIs should not be used direclty in a web app because nothing is cached (slow).
-
jwt.generate (clientId, serverId, expiresIn, privKey, data)
: generate a token
- clientId : JWT issuer, token.iss
- serverId : JWT audience, token.aud
- expiresIn : JWT duration in number of seconds
- privKey : private key
- data : accessible in token.data
It returns a signed base64 url encoded string of the token.
-
jwt.verify (jwt, pubKey, callback)
: verify the signature of a token
- jwt : JSON Web token string to verify
- pubKey : public key
- callback (err, payload) : callback, payload is an object
-
jwt.generateKeys (outputDir, outputKeyName)
: generate pub / priv ECDSA keys
CHANGELOG
1.0.0
- Possibility to verify a token with multiple public keys.
getPublicKeyFn
can return an array of public keys
- Increase key cache to 200
- Improve error output
- Accepts token in cookie
access_token
- Accepts token without key word "Bearer"
Notes
TODO :