Sunday, 28 May 2017

Node-Restful with Json web tokens

I am trying to build a simple web token protected api in nodejs. I have been following this tutorial authenticate a node js api with json web tokens and have been implementing the steps in my app. I now have an api running that allows me to get/post/put/delete and a route that generates a webtoken for the user and shows it in plain text (for dev purposes). I am using node-restful for the api's but I am having some trouble understanding how I would actually verify if the client is sending the webtoken in their request, before allowing these get/post/put/delete requests.

Here is my router. Where I define the allowed requests:

const express = require('express')
const router = express.Router()

// Models - Load models here
var userModel = require('./models/User')

// Controllers - Load controllers here
const userController = require('./controllers/userController')

// Routes - Define routes here
router.post('api/authenticate', userController.authenticate) //Route that generates the webkey and shows it in the response

// Configure the endpoint that node-restful will expose. Here I want to first check if the user is sending his or her api key. Before allowing these methods.
userModel.methods(['get', 'put', 'post', 'delete'])
userModel.register(router, '/api/users')

// Export the router object
module.exports = router

Here is my userController where the token is generated.

// Dependencies
const User = require('../models/User')
const jwt = require('jsonwebtoken')
const config = require('../config.js')

module.exports = {
  authenticate: function(req, res, next) {
    // find the user
    User.findOne({username: req.body.name}, function(err, user) {

      if (err) throw err;

      if (!user) {
        res.json({ 
          success: false, 
          message: 'Authentication failed. User not found.' });

      } else if (user) {
        // check if password matches
        if (user.password != req.body.password) {
          res.json({ 
            success: false, 
            message: 'Authentication failed. Wrong password.' });

        } else {
          // if user is found and password is right
          // create a token
          var token = jwt.sign(user, config.secret, {
            expiresIn: 60*60*24 // expires in 24 hours
          });

          // return the information including token as JSON
          res.json({
            success: true,
            message: 'Enjoy your token!',
            token: token
          });
        }   
      }
    })
  }
}

And here is my user model.

// Dependencies
const restful = require('node-restful')
const mongoose = restful.mongoose

// Schema
const userSchema = new mongoose.Schema({
  username: String,
  password: String,
  email: String
})

// Return the model as a restful model to allow it being used as a route.
module.exports = restful.model('User', userSchema)

Is there some way I can protect these endpoints, using the same manner of syntax as I am currently using to expose them? I believe I would have to check for the web token before defining the methods:

userModel.methods(['get', 'put', 'post', 'delete'])
userModel.register(router, '/api/users')

If I simply remove the methods themselves, the user will not be able to get the page and is shown a: "Cannot GET /api/users" error. What if I wanted to show a custom error? For example: "No web token provided. Register to authenticate" etc etc? Any help is much appreciated. Thank you in advance.



via n0rd

No comments:

Post a Comment