Adding an api in NodeJs express can be simple like declaring another route and assigning a function
Following is continuation of React Native Jwt Http Authentication
Since user registration is not implemented, following example provides user data by calling another service
These calls can be replaced with something like - calls to a database
This has following parts:
get-json package is used to get json data from Rest Apis
Run following command from project directory
npm install get-json --save
No new files are added, so project structure is same as that of React Native Jwt Http Authentication
getUserInfo
is modified to add a service call which returns random user data
This can be changed to a custom service call or database call if implemented
User data from the external service is not stored so it can return different data on subsequent calls for a user
Another method getMockPosts
is added which also makes a service call to get some data as filler for user posts
Changes made from Nodejs Jwt Http Authentication is highlighted
var getJSON = require('get-json')
const jwt = require('jsonwebtoken')
const config = require('../config/config.json')
const users = [
{ id: 81623, username: 'test', password: 'test', firstName: 'Test', lastName: 'User', phone: '5235234132' },
{ id: 26858, username: 'ncuser', password: 'ncpassword', firstName: 'En', lastName: 'Cee', phone: '7685496767' }];
module.exports = {
authenticate,
getUserInfo
};
async function authenticate(username, password) {
const user = users.find(u => u.username === username && u.password === password);
if (user) {
// use jwt module to sign a object containing id & username of a user and get a corresponding token
// alternatively, whole user object can be passed, but some specific fields can be selected to make it lightweight
const token = jwt.sign({id: user.id, username: username}, config.privateKey, { expiresIn: config.tokenExpirySla})
// return token to be forwarded to client
return {token:token};
}
}
async function getUserInfo(req, res) {
await getJSON(`https://randomuser.me/api/`, function(error, response){
if(error != undefined || error != null) {
res.status(400).json({ message: JSON.parse(error) });
}
else{
var userdata = response.results[0];
userdata.id = parseInt(Math.random() * 90000 + 10000);
userdata.username = req.decoded.username;
res.json({userdata : userdata});
}
});
}
async function getMockPosts(count, res) {
await getJSON(`https://baconipsum.com/api/?type=meat-and-filler¶s=${count}&start-with-lorem=1`, function(error, response){
if(error != undefined || error != null) {
res.status(400).json({ message: JSON.parse(error) });
}
else{
res.json({posts : response});
}
});
}
A route /initialPosts
is added which is bound to getInitialPosts()
methodwhich makes a service call to get 10 user posts with mock data
Additional routes also require authentication due to the authentication middleware (with no changes)
const express = require('express');
// get Router instance
const router = express.Router();
// variable to access exported methods of user_service.js
const userService = require('./user_service');
// set controller methods for routes
router.post('/authenticate', authenticate);
router.get('/getInfo', getInfo);
router.get('/initialPosts', getInitialPosts);
module.exports = router;
function authenticate(req, res, next) {
console.log("authenticate ", req.body)
// password is expected to be in base64 encoded form, which is decoded to send raw password to service
var password = Buffer.from(req.body.password, 'base64').toString('ascii')
userService.authenticate(req.body.username, password)
// here 'user' is the object returned from authenticate() if not null, which contains 'id' of user
.then(user => user ? res.json(user) :
res.status(400).json({ message: 'Username or password is incorrect' }))
// error is handled by global handler
.catch(err => next(err));
}
// since this method is called after authentication middleware,
// the req (request) object has a 'decoded' field containing id of a user
function getInfo(req, res, next) {
userService.getUserInfo(req, res)
}
// get 10 mock paragraphs as user posts
function getInitialPosts(req, res, next) {
userService.getMockPosts(10, res);
}
Same as Nodejs Jwt Http Authentication
Same as Nodejs Jwt Http Authentication
Same as Nodejs Jwt Http Authentication
Run following command from project directory
nodejs index.js
To test running in production
sudo NODE_ENV='production' nodejs index.js
To make it as accessible over a local network such as wifi, enter local ip address with command
nodejs index.js 192.168.43.34
Here, 192.168.43.34 is ip address
Save following code in a file named test.html
(or some other name with .html extension) in a directory
Replace url in case server is run in some ip address other that localhost
Open the file in a browser (double-click should do that)
<!doctype html>
<html>
<meta charset="utf-8">
<body>
<div>
<div>
<h3>Login Form</h3>
<table>
<tr>
<td><label for="id_username">Enter username</label></td>
<td><input type="text" id="id_username"></td>
</tr>
<tr>
<td><label for="id_username">Enter password</label></td>
<td><input type="password" id="id_password"></td>
</tr>
<tr>
<td><button id='btn'>Authenticate</button></td>
<td><button id='infoBtn'>Get user info</button></td>
</tr>
</table>
<pre><code id="output"></code></pre>
</div>
</div>
</body>
<script>
output = document.getElementById('output')
token = null
function authReq() {
output.innerHTML = ""
username = document.getElementById('id_username').value
password = document.getElementById('id_password').value
const encoded = btoa(password);
fetch('http://127.0.0.1:4000/users/authenticate', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({username: username, password: encoded})
})
.then(response => response.json())
.then((responseJson) => {
output.innerHTML = JSON.stringify(responseJson)
token = responseJson.token
});
}
function getInfo() {
output.innerHTML = ""
const encoded = 'Bearer ' + token
fetch('http://127.0.0.1:4000/users/getInfo', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': encoded
},
})
.then(response => response.json())
.then((value) => {
output.innerHTML = JSON.stringify(value, null, 4)
});
}
document.getElementById('btn').onclick = authReq
document.getElementById('infoBtn').onclick = getInfo
</script>
</html>
Test with username and password set in server
Check how to connect the server with mobile applications