Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
Node.js is a popular runtime platform to create programs that run on it.
It lets us run JavaScript outside the browser.
In this article, we’ll look at how to start using Node.js to create programs.
Bearer Token Authentication
We can generate a token to identify authenticated users.
When they want to make requests to our server, they send in the auth token to our server to decode it.
If it’s decoded successfully, then we let the user make the request.
We can install the jsonwebtoken
package by running:
npm i jsonwebtoken
Then we can use it by writing:
const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const users = {
foo: {
username: 'foo',
password: 'bar',
id: 1
},
bar: {
username: 'bar',
password: 'foo',
id: 2
}
}
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static('public'));
app.get('/', (req, res) => {
res.sendFile('public/index.html');
});
app.post(
'/login',
function(req, res) {
const {
username,
password
} = req.body;
const user = users[username];
if (user === undefined) {
return res.status(401).send('invalid user')
}
if (user.password !== password) {
return res.status(401).send('invalid password')
}
const {
id
} = user;
jwt.sign({
id,
username
}, 'shhhhh', function(err, token) {
res.send(token);
});
}
);
app.listen(3000, () => console.log('server started'));
In the /login
route, we get the username
and password
properties that we make a request within the JSON request body.
Then we check the user in the users
object.
If the username or password is invalid, then we send the status 401 with a message indicating the error.
Once everything is valid, then we create the token with the jwt.sign
method.
The first argument is the data that will be in the token.
Then 2nd is the secret that we sign the token with.
The last argument is the callback that’s run when the token is created.
Then we send the token back to the client.
So if we make a POST request with the /login
route and the following request body:
{
"username": "foo",
"password": "a"
}
We get 'invalid password'
return with the 401 status.
If we make the same request with a valid body like:
{
"username": "foo",
"password": "bar"
}
Then we get a signed token like:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJmb28iLCJpYXQiOjE2MDA2MjUzOTd9.05p7hoD3Qma4ShXIVWi0pKBQIv4wqSvEIvuNhaJtens
Once we decode it, we should get all the data in the object returned.
To verify the token, we can use the jwt.verify
method. For example, we can write:
const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const users = {
foo: {
username: 'foo',
password: 'bar',
id: 1
},
bar: {
username: 'bar',
password: 'foo',
id: 2
}
}
const app = express();
const SECRET= 'shhhhh';
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static('public'));
app.get('/', (req, res) => {
res.sendFile('public/index.html');
});
app.post(
'/login',
function(req, res) {
const {
username,
password
} = req.body;
const user = users[username];
if (user === undefined) {
return res.status(401).send('invalid user')
}
if (user.password !== password) {
return res.status(401).send('invalid password')
}
const {
id
} = user;
jwt.sign({
id,
username
}, SECRET, function(err, token) {
res.send(token);
});
}
);
app.get('/secret', (req, res, next) => {
console.log(req.headers)
jwt.verify(req.headers.authorization, SECRET, function(err, decoded) {
if (err){
return res.status(403).send('unauthorized')
}
req.user = decoded;
next()
});
}, (req, res)=>{
res.json(req.user);
})
app.listen(3000, () => console.log('server started'));
We added the /secret
route that has a middleware that checks the Authorization
header for the token.
Then we pass that into the jwt.verify
method to check the token.
The 2nd argument is the same secret string that we used to sign the token.
We need this to do the check properly.
Then once we decoded the string, we return 403 error if there’s an error.
Otherwise, we set req.user
to the decoded token object so we can use it in our route.
Then we call next
to call the route handler.
If we make a GET request to the /secret
route, we should get the user data returned in the response.
Conclusion
We can use the jsonwebtoken
package to issue and verify JSON web tokens for authentication.