Recently I started working with JWT based authentication. After user login, a user token is generated which will look like
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ".
It consist of three parts each separated with a dot(.).First part is header which Base64 encoded. After decoding we will get something like
{ "alg": "HS256", //Algorithm used "typ": "JWT" }
Second part is claims and Base64 encoded. After decoding we will get something like
{ "sub": "1234567890", "name": "John Doe", "admin": true }
Third part is signature and is generated with
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), *secret base64 encoded* )
Now what is this secret key and how to generate this secret key??
I tried some online generator like "http://kjur.github.io/jsjws/tool_jwt.html" but dint get much help.
To reiterate, whatever you do, don't store a JWT in local storage (or session storage). If any of the third-party scripts you include in your page is compromised, it can access all your users' tokens. To keep them secure, you should always store JWTs inside an httpOnly cookie.
The signing key is a JSON web key (JWK) that contains a well-known public key used to validate the signature of a signed JSON web token (JWT). A JSON web key set (JWKS) is a set of keys containing the public keys used to verify any JWT issued by the authorization server and signed using the RS256 signing algorithm.
How is a JWT token generated? We set the signing algorithm to be HMAC SHA256 (JWT supports multiple algorithms), then we create a buffer from this JSON-encoded object, and we encode it using base64. The partial result is eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 .
A Json Web Token made up of three parts. The header, the payload and the signature Now the header is just some metadata about the token itself and the payload is the data that we can encode into the token, any data really that we want. So the more data we want to encode here the bigger the JWT. Anyway, these two parts are just plain text that will get encoded, but not encrypted.
So anyone will be able to decode them and to read them, we cannot store any sensitive data in here. But that's not a problem at all because in the third part, so in the signature, is where things really get interesting. The signature is created using the header, the payload, and the secret that is saved on the server.
And this whole process is then called signing the Json Web Token. The signing algorithm takes the header, the payload, and the secret to create a unique signature. So only this data plus the secret can create this signature, all right? Then together with the header and the payload, these signature forms the JWT, which then gets sent to the client.
Once the server receives a JWT to grant access to a protected route, it needs to verify it in order to determine if the user really is who he claims to be. In other words, it will verify if no one changed the header and the payload data of the token. So again, this verification step will check if no third party actually altered either the header or the payload of the Json Web Token.
So, how does this verification actually work? Well, it is actually quite straightforward. Once the JWT is received, the verification will take its header and payload, and together with the secret that is still saved on the server, basically create a test signature.
But the original signature that was generated when the JWT was first created is still in the token, right? And that's the key to this verification. Because now all we have to do is to compare the test signature with the original signature. And if the test signature is the same as the original signature, then it means that the payload and the header have not been modified.
Because if they had been modified, then the test signature would have to be different. Therefore in this case where there has been no alteration of the data, we can then authenticate the user. And of course, if the two signatures are actually different, well, then it means that someone tampered with the data. Usually by trying to change the payload. But that third party manipulating the payload does of course not have access to the secret, so they cannot sign the JWT. So the original signature will never correspond to the manipulated data. And therefore, the verification will always fail in this case. And that's the key to making this whole system work. It's the magic that makes JWT so simple, but also extremely powerful.
Now let's do some practices with nodejs:
Configuration file is perfect for storing JWT SECRET data. Using the standard HSA 256 encryption for the signature, the secret should at least be 32 characters long, but the longer the better.
config.env:
JWT_SECRET = my-32-character-ultra-secure-and-ultra-long-secret //after 90days JWT will no longer be valid, even the signuter is correct and everything is matched. JWT_EXPIRES_IN=90
now install JWT using command
npm i jsonwebtoken
Example after user signup passing him JWT token so he can stay logged in and get access of resources.
exports.signup = catchAsync(async (req, res, next) => { const newUser = await User.create({ name: req.body.name, email: req.body.email, password: req.body.password, passwordConfirm: req.body.passwordConfirm, }); const token = jwt.sign({ id: newUser._id }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRES_IN, }); res.status(201).json({ status: 'success', token, data: { newUser, }, }); });
output:
In my opinion, do not take help from a third-party to generate your super-secret key, because you can't say it's secret anymore. Just use your keyboard.
The algorithm (HS256
) used to sign the JWT means that the secret is a symmetric key that is known by both the sender and the receiver. It is negotiated and distributed out of band. Hence, if you're the intended recipient of the token, the sender should have provided you with the secret out of band.
If you're the sender, you can use an arbitrary string of bytes as the secret, it can be generated or purposely chosen. You have to make sure that you provide the secret to the intended recipient out of band.
For the record, the 3 elements in the JWT are not base64-encoded but base64url-encoded, which is a variant of base64 encoding that results in a URL-safe value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With