ref – https://scotch.io/tutorials/authenticate-a-node-js-api-with-json-web-tokens
We’ll build a quick API using Node and Express and we’ll be using POSTman to test it.
Create an application directory, then in your mac terminal:
$ npm install express body-parser morgan mongoose jsonwebtoken –save
- express is the popular Node framework
- mongoose is how we interact with our MongoDB database
- morgan will log requests to the console so we can see what is happening
- body-parser will let us get parameters from our POST requests
- jsonwebtoken is how we create and verify our JSON Web Tokens
The –save modifier will also save these packages to our package.json file.
After all the packages have been downloaded, you will see a node_modules folder. The packages are installed inside there.
User Model (/models/user.js)
In your project directory, create models folder. Then inside that models folder, you create user.js file.
The user model that we define will be used when creating and getting users. To create a Mongoose model, let’s create the file app/models/user.js
1 2 3 4 5 6 7 8 9 10 11 |
var mongoose = require('mongoose'); var Schema = mongoose.Schema; // set up a mongoose model and pass it using module.exports module.exports = mongoose.model('User', new Schema({ name: String, password: String, admin: Boolean }, { collection: 'user' }) ); |
Now let’s create a configuration file to store configuration settings for our application.
config.js (/config.js)
Basically, the database is hosted on our local machine.
1 2 3 4 5 |
module.exports = { //secret: used when we create and verify JSON Web Tokens 'secret': 'ilovescotchyscotch', 'database': 'mongodb://localhost/PersonDatabase' }; |
- secret: used when we create and verify JSON Web Tokens
- database: the URI with username and password to your MongoDB installation
Note: You should be running GULP for your working environment so that when you make changes, it will automatically help you save. In your gulpfile.js, make sure that gulp.task, script has the string “server.js”.
server.js
Set up all the package variables and db connections
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// ======================= // get the packages we need ============ // ======================= var express = require('express'); var app = express(); var bodyParser = require('body-parser'); var morgan = require('morgan'); var mongoose = require('mongoose'); var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens var config = require('./config'); // get our config file var User = require('./models/user'); // get our mongoose model // ======================= // configuration ========= // ======================= var port = 8080; // used to create, sign, and verify tokens mongoose.connect(config.database); // connect to database var db = mongoose.connection; db.on('error', console.error.bind(console, 'connection error:')); db.once('open', function (callback) { // yay! console.log('mongoose db connected'); }); |
Then we have our app use body parser for POST, morgan for throwing logs to console outputs, and set our config file’s object secret to web token’s super secret key.
1 2 3 4 5 6 7 8 |
app.set('superSecret', config.secret); // secret variable // use body parser so we can get info from POST and/or URL parameters app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); // use morgan to log requests to the console app.use(morgan('dev')); |
public URL for home
Let’s create public URL for the home page and then start the server
1 2 3 4 5 6 7 8 9 10 |
// route to show a random message (GET http://localhost:8080/) app.get('/', function(req, res) { res.json({ message: '(GET http://localhost:8080/)' }); }); // ======================= // start the server ====== // ======================= app.listen(port); console.log('Magic happens at http://localhost:' + port); |
Open up a browser and go to
http://localhost:8080/
You’d get the json response:
{“message”:”(GET http://localhost:8080/)”}
If you look at your mac terminal, you’ll also see morgan’s log outputs.
Finally, we put a url where the server creates and inserts a new user along with a password into the database.
Public URL to create a user
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
app.get('/setup', function(req, res) { // create a sample user var nick = new User({ name: 'rtsao', password: 'compaq', //You would protect your passwords by hashing it. admin: true }); // save the sample user nick.save(function(err) { if (err) throw err; console.log('User saved successfully'); res.json({ success: true }); }); }); |
Open up a browser and put in
http://localhost:8080/setup
You will get the json data back:
{“success”:true}
This means that you have successfully inserted the user rtsao with pw compaq.
Showing Users through public URL
Put the following code above our routes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// API ROUTES ------------------- // get an instance of the router for api routes var apiRoutes = express.Router(); // route to return all users (GET http://localhost:8080/api/users) apiRoutes.get('/users', function(req, res) { console.log('(GET http://localhost:8080/api/users)'); User.find({}, function(err, users) { res.json(users); }); }); // apply the routes to our application with the prefix /api app.use('/api', apiRoutes); |
What this means is that the variable apiRoutes always has url start with /api.
Whatever url we specify for a certain request, its always /api/url paired with GET or POST..etc.
Hence in apiRoutes.get(‘/users’…) function definition, it just means for (GET http://localhost:8080/api/users) we will return all the users from the database.
So now when we hit:
http://localhost:8080/api/users
we get:
[{“_id”:”55973f3702e8b0094967b544″,”name”:”rtsao”,”password”:”compaq”,”admin”:true,”__v”:0},{“_id”:”55977f4b06112d75860f9af6″,”name”:”rtsao6680″,”password”:”abcde12345″,”admin”:true,”__v”:0}]
Full Code
/config.js
1 2 3 4 5 6 7 8 |
module.exports = { //secret: used when we create and verify JSON Web Tokens 'secret': 'ilovescotchyscotch', 'database': 'mongodb://localhost/PersonDatabase' }; |
/server.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
// ======================= // get the packages we need ============ // ======================= var express = require('express'); var app = express(); var bodyParser = require('body-parser'); var morgan = require('morgan'); var mongoose = require('mongoose'); var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens var config = require('./config'); // get our config file var User = require('./models/user'); // get our mongoose model // ======================= // configuration ========= // ======================= var port = 8080; // used to create, sign, and verify tokens mongoose.connect(config.database); // connect to database var db = mongoose.connection; db.on('error', console.error.bind(console, 'connection error:')); db.once('open', function (callback) { // yay! console.log('mongoose db connected'); }); app.set('superSecret', config.secret); // secret variable // use body parser so we can get info from POST and/or URL parameters app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); // use morgan to log requests to the console app.use(morgan('dev')); // API ROUTES ------------------- // get an instance of the router for api routes var apiRoutes = express.Router(); // route to return all users (GET http://localhost:8080/api/users) apiRoutes.get('/users', function(req, res) { console.log('(GET http://localhost:8080/api/users)'); User.find({}, function(err, users) { res.json(users); }); }); // apply the routes to our application with the prefix /api app.use('/api', apiRoutes); // http://localhost:8080/setup app.get('/setup', function(req, res) { // create a sample user var nick = new User({ name: 'rtsao6680', password: 'abcde12345', //You would protect your passwords by hashing it. admin: true }); // save the sample user nick.save(function(err) { if (err) throw err; console.log('User saved successfully'); res.json({ success: true }); }); }); // route to show a random message (GET http://localhost:8080/) app.get('/', function(req, res) { res.json({ message: '(GET http://localhost:8080/)' }); }); // ======================= // start the server ====== // ======================= app.listen(port); console.log('Magic happens at http://localhost:' + port); |
/models/user.js
1 2 3 4 5 6 7 8 9 10 11 |
var mongoose = require('mongoose'); var Schema = mongoose.Schema; // set up a mongoose model and pass it using module.exports module.exports = mongoose.model('User', new Schema({ name: String, password: String, admin: Boolean }, { collection: 'user' }) ); |