Full code: https://github.com/aleksvp2017/secureroutes
Using:
Node.js;
Express;
express-bearer-token;
jsonwebtoken
I'm assuming that you have a Node server running express with a couple of routes set (if you need, there is a post about that here). The full code example is set up like that.
So, the main idea is to configure which routes you want to be secure (by secure, I mean, routes that demand authentication, which is going to be checked by the presence of a token), then, we're going to set a middleware that checks every request: if it requires authentication, we're going to check if there is a valid token (you can, and probably should, also check for permissions for a particular user too).
So, first step, is to configure the routes that would require authentication. In routes.js, going to add a property like that:
var routes = [ { uri: '/login', httpmethod: 'post', component: Permision, method: 'login', requireAuthentication: false}, { uri: '/products', httpmethod: 'get', component: Product, method: 'list', requireAuthentication: true}, ]
Next step is creating a js to check for the presence of the token, in my example, permision.js:
const checkForToken = (req, res, next) => { var Routes = require('../routes/routes.js') if (Routes.requireAuthentication(req.originalUrl, req.method)){ var jwt = require('jsonwebtoken') jwt.verify(req.token, process.env.SECRET, async (err, decoded) => { if (err) { res.status(440).send({error: err}) } else { next() } }) } else{ next() } } const login = async function (req, res, next) { var jwt = require('jsonwebtoken') let token = jwt.sign({ email: req.body.user.email }, process.env.SECRET, { expiresIn: 86400 //24h }) res.status(200).json({ auth: true, usuario: { ...req.user, token: token}}) next() } module.exports = { checkForToken, login }
So, basically it checks if the route require authentication, and if so, try to read the token generated with a particulary secret. I set the secret using (on VisualCode terminal, same that is going to be used to run the app):
$env:SECRET='mySecret'.
The "next()" call is important because, as you know, express is in fact a series of middlewares, so you have to do this to maintain the middleware's flow.
So if you run the app (nodemon app.js) and try to access http://localhost:3001/products you're going to get a error:
{
"error": {
"name": "JsonWebTokenError",
"message": "jwt must be provided"
}
You can generate the token in various ways. For instance, using https://jwt.io/, like this:
But, as you must have noticed, I provided an endpoint to do that (http://localhost:3001/login). All you have to do is post a request passing something like that (on the body, as json):
{"user" : {
"email": "aleksvp@gmail.com"
}}
Of course, I didn't really check the user in a database or anything like that, didn't even required a password. In a real case, you should.
Once you have the encoded token, on the request, you must include, as a header parameter:
Key:Authorization Value: Bearer <<tokenValue>>
That's pretty much it. Easy stuff, right?
Comments