Template implementation of Encrypted JWT authentication on a node server
A JWT is basically a signed JSON object, hence allowing us to send custom info in an object with a signature that verifies both the contents and the sender. You can check out an example here.
A JWE is essentially an encrypted JWT. In our case asymmetrically encrypted the following way:
- Take the payload
and sign it with the server's private signing key
{ "sub": "123", "aud": "someClient", "iss": "https://example.com", "iat": 1583209685, "exp": 1589909685 }
- we get our JWT:
(payload, server-sig)
- get one client's public encryption key and encrypt the above JWT with it
- we get our JWE
{(payload, server-sig) client-enc}
- send it to the client (the JWE can only be read by this one client)
- decrypt the JWE client side with client's private encryption key (on client device)
- client has the original JWT
(payload, server-sig)
- client gets server's public signing key and verifies the above token
- if the signature verification (with the servers public key) passes, it means two things:
- the JWT must have been sent by the server
- the payload (the JWT) must not have been tampered with
Then client will send this JWT to the server in every other communication also encrypted:
- client takes out the original JWT from it's secure storage (keychain):
(payload, server-sig)
- gets the servers public encryption key and encrypts the above JWT with it
- client has the following JWE
{(payload, server-sig) server-enc}
- sends it to the server (only server can read it since encrypted)
- server decrypts it with it's own private encryption key:
(payload, server-sig)
- server verifies the above JWT with it's own private signing key
- if this passes it means the following things:
- it could only have been sent by this one client as only they had access to it
- the token is valid so we can grant privileges to the user appropriately (the token payload will state what permissions they may have)
npm test
to run Jest tests with live coveragenpm run docs
to generate JSDoc documentation
- See
/coverage
for test coverage via Istanbul JS. /out
for the JSDocs
To preserve sessions on reboot and import own encryption and signing keys, use the following environment configuration:
### Jose
PRESERVE_SESSIONS_ON_REBOOT=1
PRIVATE_KEY_PASSPHRASE=tnahpele
where PRIVATE_KEY_PASSPHRASE
is the passphrase of your keys in PEM format.
Make sure to add your keys to server/keys
To refresh all sessions and use new server generated keys upon each reboot, set the following:
### Jose
PRESERVE_SESSIONS_ON_REBOOT=0