This is an example application that serves an ExpressJS JSON api to a React client application. The React application is configured for a basic JWT authentication flow WITHOUT using redux. This is a basic auth model used by developers for Strategic Machines products and clients.
The React client app could easily be restructured to keep current user information in a Redux Store.
Note that ebextensions and eb config files are included, providing a model for deployment to AWS via the eb cli.
-
git clone
this repository to your local machine. -
run
npm install
from the cloned repo directory. -
create a
.env
file at the root of the application, adjacent toserver.js
.The only environment variable you have to declare in development is
JWT_SECRET
In the
.env
file, you can declare the following environment variables:JWT_SECRET
,ATLAS_AUTH
, andPORT
. For example:JWT_SECRET=mysupersecret MONGODB_URI=mongodb://localhost/auth PORT=3001
-
It's recommended that you run the api server on port 3001 while developing locally, as the client app will default to port 3000.
-
Make sure
mongod
is running by running… ahem…mongod
-
From that point you can run the api server either by using
nodemon
or just runningnode server.js
-
Now for the client application.
cd client
-
Install the client app's dependencies with
npm install
-
From the client directory, run
npm start
to boot up the client application.
It's common to identify the user making an authenticated request on the server side. In this application, the verifyToken
middleware (declared in /serverAuth.js
) decodes a provided token, and makes sure the request is coming from a valid user. When the user is validated, it is added to the req
object as req.user
.
Here's an example of how you can access the 'current user' from the server side app, assuming a user is logged in and sending an authenticated request:
const express = require('express')
const mySpecialRouter = new express.Router()
// JWT AUTH MIDDLEWARE:
const { verifyToken } = require('../serverAuth.js')
const Comment = require('../models/Comment.js')
// all routes declared after this middleware require a token
mySpecialRouter.use(verifyToken)
mySpecialRouter.post("/comments", (req, res) => {
// since this route succeeds 'verifyToken', it has the current user in req.user
// so we can easily associate new mongo documents to the current user:
Comment.create({ ...req.body, user: req.user }, (err, comment) => {
if(err) return console.log(err)
res.json({ success: true, message: "Comment created.", comment })
})
})
module.exports = mySpecialRouter
- React client application business in the front
- NodeJS + Express + Mongoose party in the back
- React Router 4.*
- Milligram CSS so it doesn't look like garbage
- JSON Web Token authentication flow
- ATLAS Mongodb or Mongodb localhost
- AWS Elastic Beanstalk (from the command line)
- While the Mongoose user schema enforces email uniqueness, there's no handler for duplicate user emails on the client side. (A user wouldn't know why they couldn't create their account if they came across this scenario).