Module 2: JSON Web Tokens (JWT)
JSON Web Tokens (JWT)
JSON Web Tokens (JWT) are a way to transmit information between parties in the form of a JSON object. The JSON information is most commonly used for authentication and information exchange. In the former example, with authentication, every JWT contains information. In the latter, JWTs contain the classic JSON data you've seen before.
Ultimately, a JWT is a string that has three parts separated by a period (.). Those are:
- The header
- The payload
- The signature
Header
The header contains the algorithm with the token type. Typically the header for a JWT looks like this.
{
"alg": "HS256",
"typ": "JWT"
}
The alg
key specifies which algorithm was used to create the token, in this case, the algorithm
is HMACSHA-256, and the typ
property classifies this token as being of the type JWT.
Payload
The payload includes claims (fancy name for things like permissions for the user) information or any other data we'd like to store in the token, which is most likely a user id. There are specific claims defined in the JWT standard, and you can also add custom properties to this object.
An example:
{
"sub": "1234567890", // standard - subject, normally the user id
"name": "John Doe", // custom property
"iat": 1516239022 // standard - The Date the token was issued, expressed in seconds since epoch.
}
Signature
To create a signature, we must create a string by base64 encoding the header and payload together and then signing it with a secret.
Combining all three parts, you will get a JWT that looks like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
How to Build It
Visit this site and click on the debugger navigation link at the top to see an excellent representation of a JWT.
On the left-hand side, there is a sample JWT, and on the right, we can see the different parts highlighted in a different color to match the parts of the JWT string that represent those.
Produce and Send a JWT
In this section, we'll use JSON Web Tokens to handle authentication.
To produce and verify the token, we'll use the jsonwebtoken npm module.
How to Build It
Let's produce and send a token on a successful login.
First, add jsonwebtoken to the project and require it in auth-router.js:
const jwt = require('jsonwebtoken'); // installed this library
Next, modify the /login endpoint inside auth-router.js to produce and send the token:
// ./auth/auth-router.js
router.post('/login', (req, res) => {
let { username, password } = req.body;
Users.findBy({ username })
.first()
.then(user => {
if (user && bcrypt.compareSync(password, user.password)) {
const token = generateToken(user); // new line
// the server needs to return the token to the client
// this doesn't happen automatically like it happens with cookies
res.status(200).json({
message: `Welcome ${user.username}!, have a token...`,
token, // attach the token as part of the response
});
} else {
res.status(401).json({ message: 'Invalid Credentials' });
}
})
.catch(error => {
res.status(500).json(error);
});
});
Add the generateToken helper function:
function generateToken(user) {
const payload = {
subject: user.id, // sub in payload is what the token is about
username: user.username,
// ...otherData
};
const options = {
expiresIn: '1d', // show other available options in the library's documentation
};
// extract the secret away so it can be required and used where needed
return jwt.sign(payload, secrets.jwtSecret, options); // this method is synchronous
}
Create a ./config/secrets.js file to hold the jwtSecret:
// the secrets will be safely stored in an environment variable, these are placeholders for development.
module.exports = {
jwtSecret: process.env.JWT_SECRET || 'add a third table for many to many',
};
Finally, require secrets.js into auth-router.js:
const secrets = require('../config/secrets.js');
Now you can login with the student/hired user credentials to receive a token. The server is now configured to produce and send JWTs on successful login attempts.
Guided Project
Using JSON Web Tokens Starter Code
Using JSON Web Tokens Solution
NOTE
The versions of project dependencies used in the recording are slightly different from the ones used in the starter and solution repositories, but this should not have any impact on the relevant code of the Guided Project.
The versions used in the repositories are more recent, and thus more similar to the versions you will install if you create a project from scratch.
Module 2 Project: JSON Web Tokens
The module project contains advanced problems that will challenge and stretch your understanding of the module's content. The project has built-in tests for you to check your work, and the solution video is available in case you need help or want to see how we solved each challenge, but remember, there is always more than one way to solve a problem. Before reviewing the solution video, be sure to attempt the project and try solving the challenges yourself.
Instructions
The link below takes you to Bloom's code repository of the assignment. You'll need to fork the repo to your own GitHub account, and clone it down to your computer:
Starter Repo: JSON Web Tokens
- Fork the repository,
- clone it to your machine, and
- open the README.md file in VSCode, where you will find instructions on completing this Project.
- submit your completed project to the BloomTech Portal