Step 12: JWT
In the previous step, we provided a route to authenticate users. But now what? After a sucessfull authentication, the user should be able to perform/access resources they are autorized to. Somehow the API server should know an authenticated user when such a user makes a request through the client application.
Token-based authentication is a common practice where the the authentication service, after having confirmed the user's identity, issues a token. A token is like a receipt that the client will keep and hand back to the server for future interactions. Conventionally, tokens have an expiration date! Once the token expires, the client must authenticate with the server again (e.g., sign in again).
The token can be anything! A popular choice is JSON web token (JWT), pronounced "jot," is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.
Let's install jsonwebtoken
dependecy:
yarn add jsonwebtoken
Create a file, token.js
, in the src
folder, with the following content:
import jsonWebToken from "jsonwebtoken";
export const createToken = ({ user, expiresIn }) => {
return jsonWebToken.sign(user, process.env.JWT_SECRET, {
algorithm: "HS256",
expiresIn: expiresIn || "2d",
});
};
export const decodeToken = (token) => {
return jsonWebToken.verify(token, process.env.JWT_SECRET, {
algorithm: "HS256",
ignoreNotBefore: true,
});
};
Notice the expiresIn
attribute! If this parameter is not provided,
we set the token to expire two days after it was created. If a token is expired
(or invalid), the decodeToken
will throw an error.
The JWT_SECRET
is a string containing the secret for HS256 algorithm. You can choose any string (the longer, the better). Moreover, store this string in the .env
file.
Update src/auth.js
We create a token that includes the user's ID and return it to the client:
debug("Prepare the payload..");
const token = createToken({ user: { id: user.id } });
res.status(201).json({
status: 201,
message: `Successfully signed in!`,
data: { name: user.name, email: user.email },
token,
});
Now run the API server and try to make a Postman request for this new route.