├── .gitignore ├── README.md ├── config ├── db.js ├── keys.js └── passport.js ├── middleware └── auth.js ├── package.json ├── routes └── users.js ├── server.js ├── utils └── is-Empty.js ├── validation ├── login.js └── tokenChecker.js └── vercel.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | package-lock.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | "# jwt-token-react-nodejs-backend" 2 | -------------------------------------------------------------------------------- /config/db.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | // const config = require('config'); 3 | // const db = config.get('mongoURI'); 4 | const mongoURL = "mongodb://localhost:27017/happydoge"; 5 | const connectDB = async () => { 6 | try { 7 | await mongoose.connect(mongoURL, { 8 | useNewUrlParser: true, 9 | useCreateIndex: true, 10 | useFindAndModify: false, 11 | useUnifiedTopology: true, 12 | }); 13 | 14 | console.log("MongoDB Connected..."); 15 | } catch (err) { 16 | console.error(err.message); 17 | // Exit process with failure 18 | process.exit(1); 19 | } 20 | }; 21 | 22 | module.exports = connectDB; 23 | -------------------------------------------------------------------------------- /config/keys.js: -------------------------------------------------------------------------------- 1 | const key = { 2 | secretOrKey: "screct", 3 | refresh_token: "refresh-token-secret-protocal" 4 | }; 5 | module.exports = key; 6 | -------------------------------------------------------------------------------- /config/passport.js: -------------------------------------------------------------------------------- 1 | const JwtStrategy = require("passport-jwt").Strategy; 2 | const ExtractJwt = require("passport-jwt").ExtractJwt; 3 | const User = require("../models/User"); 4 | const keys = require("../config/keys"); 5 | 6 | const opts = {}; 7 | opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken(); 8 | opts.secretOrKey = keys.secretOrKey; 9 | 10 | module.exports = (passport) => { 11 | passport.use( 12 | new JwtStrategy(opts, (jwt_payload, done) => { 13 | User.findById(jwt_payload.id) 14 | .then((user) => { 15 | if (user) { 16 | return done(null, user); 17 | } 18 | return done(null, false); 19 | }) 20 | .catch((err) => console.log(err)); 21 | }) 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /middleware/auth.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | const config = require('config'); 3 | 4 | module.exports = function (req, res, next) { 5 | // Get token from header 6 | const token = req.header('x-auth-token'); 7 | 8 | // Check if not token 9 | if (!token) { 10 | return res.status(401).json({ msg: 'No token, authorization denied' }); 11 | } 12 | 13 | // Verify token 14 | try { 15 | jwt.verify(token, config.get('jwtSecret'), (error, decoded) => { 16 | if (error) { 17 | return res.status(401).json({ msg: 'Token is not valid' }); 18 | } else { 19 | req.user = decoded.user; 20 | next(); 21 | } 22 | }); 23 | } catch (err) { 24 | console.error('something wrong with auth middleware'); 25 | res.status(500).json({ msg: 'Server Error' }); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "happy_backend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "nodemon server.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "async": "^3.2.1", 14 | "axios": "^0.21.3", 15 | "body-parser": "^1.19.0", 16 | "config": "^3.3.6", 17 | "cors": "^2.8.5", 18 | "dotenv": "^10.0.0", 19 | "dotnet": "^1.1.4", 20 | "express": "^4.17.1", 21 | "express-validator": "^6.12.0", 22 | "fs": "^0.0.1-security", 23 | "jsonwebtoken": "^8.5.1", 24 | "node-fetch": "^2.6.1", 25 | "nodemon": "^2.0.12", 26 | "passport": "^0.4.1", 27 | "passport-jwt": "^4.0.0", 28 | "path": "^0.12.7", 29 | "socket.io": "^4.1.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | 4 | //@import models 5 | 6 | const jwt = require("jsonwebtoken"); 7 | const keys = require("../config/keys"); 8 | // const passport = require("passport"); 9 | //@import validation 10 | const validateLoginInput = require("../validation/login"); 11 | 12 | router.post("/test", async (req, res) => { 13 | return res.json({ mesg: "working" }); 14 | }); 15 | 16 | // @route POST users/login 17 | // @desc Login user 18 | // @access Public 19 | router.post("/login", async (req, res) => { 20 | const { errors, isValid } = validateLoginInput(req.body); 21 | 22 | // Check Validation 23 | if (!isValid) { 24 | return res.status(400).json(errors); 25 | } 26 | const name = req.body.username; 27 | const password = req.body.password; 28 | 29 | // Find user by email 30 | const payload = { 31 | name: name, 32 | password: password, 33 | }; 34 | const access_token = await jwt.sign( 35 | payload, 36 | keys.secretOrKey, 37 | { expiresIn: 5 } 38 | ); 39 | const refresh_token = await jwt.sign( 40 | payload, 41 | keys.refresh_token, 42 | { expiresIn: 3600 * 24 * 15 } 43 | ); 44 | 45 | res.json({ 46 | success: true, 47 | access_token: "Bearer " + access_token, 48 | refresh_token: "Bearer " + refresh_token, 49 | }); 50 | }); 51 | 52 | // @route GET users/refresh-token 53 | // @desc Login user 54 | // @access Public 55 | router.post("/refresh-token", async (req, res) => { 56 | // console.log("refresh token func", jwt.verify(refresh_token, keys.refresh_token)); 57 | // verify refresh-token 58 | const refresh_token = req.body[0]; 59 | const decoded = req.body[1]; 60 | const decoded_token = jwt.verify(refresh_token.slice(7), keys.refresh_token); 61 | // const decoded_token = 1; 62 | const payload = { 63 | name: decoded.name, 64 | password: decoded.password, 65 | } 66 | if (decoded_token) { 67 | const access_token = await jwt.sign( 68 | payload, 69 | keys.secretOrKey, 70 | { expiresIn: 5 } 71 | // { expiresIn: 3600 * 24 * 3 } 72 | ); 73 | res.json({ 74 | success: true, 75 | access_token: access_token 76 | }); 77 | } 78 | 79 | }); 80 | 81 | // @route GET users/current 82 | // @desc Return current user 83 | // @access Private 84 | // router.get( 85 | // "/current", 86 | // passport.authenticate("jwt", { session: false }), 87 | // (req, res) => { 88 | // return res.status(200).json(req.user); 89 | // } 90 | // ); 91 | module.exports = router; 92 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const bodyParser = require("body-parser"); 3 | const cors = require("cors"); 4 | // const passport = require("passport"); 5 | const path = require("path"); 6 | //@import 7 | 8 | require("dotenv").config(); 9 | const app = express(); 10 | 11 | // Init Middleware 12 | // app.use(cors()); 13 | // app.use( 14 | // cors({ 15 | // origin: ["https://www.section.io", "http://localhost:3000"], 16 | // }) 17 | // ); 18 | 19 | var corsOption = { 20 | origin: `*`, 21 | methods: ["GET", "POST", "DELETE", "UPDATE", "PUT", "PATCH"], 22 | credentials: true, 23 | exposedHeaders: ["x-auth-token"], 24 | url: [ 25 | "https://localhost:3000", 26 | ], 27 | }; 28 | app.use(cors(corsOption)); 29 | 30 | app.use(express.json()); 31 | app.use(bodyParser.json()); 32 | app.use(bodyParser.urlencoded({ extended: true })); 33 | // Passport middleware 34 | // app.use(passport.initialize()); 35 | 36 | // Passport Config 37 | // require("./config/passport")(passport); 38 | // Define Routes 39 | app.use("/users", require("./routes/users")); 40 | 41 | // Serve static assets in productioncd 42 | if (process.env.NODE_ENV === "production") { 43 | // Set static folder 44 | app.use(express.static("client/build")); 45 | 46 | app.get("*", (req, res) => { 47 | res.sendFile(path.resolve(__dirname, "client", "build", "index.html")); 48 | }); 49 | } 50 | 51 | const PORT = process.env.PORT || 5000; 52 | 53 | app.listen(PORT, () => console.log(`Server started on port ${PORT}`)); 54 | -------------------------------------------------------------------------------- /utils/is-Empty.js: -------------------------------------------------------------------------------- 1 | const isEmpty = (value) => 2 | value === undefined || 3 | value === null || 4 | (typeof value === "object" && Object.keys(value).length === 0) || 5 | (typeof value === "string" && value.trim().length === 0); 6 | 7 | module.exports = isEmpty; 8 | -------------------------------------------------------------------------------- /validation/login.js: -------------------------------------------------------------------------------- 1 | const Validator = require("validator"); 2 | const isEmpty = require("../utils/is-Empty"); 3 | 4 | module.exports = function validateLoginInput(data) { 5 | let errors = {}; 6 | 7 | data.username = !isEmpty(data.username) ? data.username : ""; 8 | data.password = !isEmpty(data.password) ? data.password : ""; 9 | 10 | if (Validator.isEmpty(data.username)) { 11 | errors.name = "Name field is required"; 12 | } 13 | 14 | if (Validator.isEmpty(data.password)) { 15 | errors.password = "Password field is required"; 16 | } 17 | 18 | return { 19 | errors, 20 | isValid: isEmpty(errors), 21 | }; 22 | }; 23 | -------------------------------------------------------------------------------- /validation/tokenChecker.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken') 2 | const config = require('../config/keys') 3 | 4 | module.exports = (token, next) => { 5 | // const token = req.body.token || req.query.token || req.headers['x-access-token'] 6 | // decode token 7 | if (token) { 8 | // verifies secret and checks exp 9 | jwt.verify(token, config.refresh_token, function (err, decoded) { 10 | if (err) { 11 | return res.status(401).json({ "error": true, "message": 'Unauthorized access.' }); 12 | } 13 | // req.decoded = decoded; 14 | next(); 15 | }); 16 | } else { 17 | // if there is no token 18 | // return an error 19 | return res.status(403).send({ 20 | "error": true, 21 | "message": 'No token provided.' 22 | }); 23 | } 24 | } -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [ 4 | { 5 | "src": "./server.js", 6 | "use": "@vercel/node" 7 | } 8 | ], 9 | "routes": [ 10 | { 11 | "src": "/(.*)", 12 | "dest": "/" 13 | } 14 | ] 15 | } --------------------------------------------------------------------------------