Skip to content

Commit baf7e5b

Browse files
Sam RaziSam Razi
Sam Razi
authored and
Sam Razi
committed
This is a simple authentication server template using express with mongoose.
Also users passport, with JWT and local strategies. - Built as part of Advanced React/Redux course by Stephen Grider
0 parents  commit baf7e5b

File tree

6 files changed

+208
-0
lines changed

6 files changed

+208
-0
lines changed

Diff for: controllers/authentication.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
const jwt = require('jwt-simple');
2+
const User = require('../models/user');
3+
const config = require('../config');
4+
5+
function tokenForUser(user) {
6+
const timestamp = new Date().getTime()
7+
return jwt.encode({ sub: user.id, iat: timestamp }, config.secret);
8+
}
9+
10+
exports.signin = function(req, res, next) {
11+
// User has already had their email and password auth'd
12+
// We just need to give them a token
13+
res.send({ token: tokenForUser(req.user)});
14+
15+
}
16+
17+
18+
exports.signup = function(req, res, next) {
19+
const email = req.body.email;
20+
const password = req.body.password;
21+
22+
if (!email || !password) {
23+
return res.status(422).send({ error: 'You must provide email and password'});
24+
}
25+
26+
// See if a user with the given email exists
27+
User.findOne({ email: email }, function(err, existingUser) {
28+
if (err) { return next(err); }
29+
30+
// If a user with email does exist, return an error
31+
if (existingUser) {
32+
return res.status(422).send({ error: 'Email is in use' });
33+
}
34+
35+
// If a user with email does NOT exist, create and save record
36+
const user = new User({
37+
email: email,
38+
password: password
39+
});
40+
41+
// this will actually save the newly created user object to the mongodb database
42+
user.save(function(err) {
43+
if (err) { return next(err); }
44+
// Respond to request indicating that the user was created
45+
res.json({ token: tokenForUser(user) });
46+
47+
});
48+
});
49+
}

Diff for: index.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Application Controller / Start-point
2+
const express = require('express');
3+
const http = require('http');
4+
const bodyParser = require('body-parser');
5+
const morgan = require('morgan');
6+
const app = express();
7+
const router = require('./router');
8+
const mongoose = require('mongoose');
9+
10+
// DB Setup
11+
mongoose.connect('mongodb://localhost:auth/auth');
12+
13+
14+
// App Setup
15+
app.use(morgan('combined'));
16+
app.use(bodyParser.json({ type: '*/*'}));
17+
router(app);
18+
19+
// Server Setup
20+
21+
const port = process.env.PORT || 3090;
22+
const server = http.createServer(app);
23+
server.listen(port);
24+
25+
console.log('Server listening on:', port);
26+

Diff for: models/user.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
const mongoose = require('mongoose');
2+
const Schema = mongoose.Schema;
3+
const bcrypt = require('bcrypt-nodejs');
4+
5+
// Define our model
6+
const userSchema = new Schema({
7+
email: { type: String, unique: true, lowercase: true },
8+
password: String
9+
});
10+
11+
// On Save Hook, encrypt password
12+
userSchema.pre('save', function(next) {
13+
const user = this;
14+
15+
bcrypt.genSalt(10, function(err, salt) {
16+
if (err) { return next(err); }
17+
18+
bcrypt.hash(user.password, salt, null, function(err, hash) {
19+
if (err) { return next(err); }
20+
21+
user.password = hash;
22+
next();
23+
});
24+
});
25+
});
26+
27+
userSchema.methods.comparePassword = function(candidatePassword, callback) {
28+
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
29+
if (err) { return callback(err); }
30+
31+
callback(null, isMatch);
32+
});
33+
}
34+
35+
// Create the model class
36+
const ModelClass = mongoose.model('user', userSchema);
37+
38+
39+
40+
// Export the model
41+
module.exports = ModelClass;
42+

Diff for: package.json

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "server",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1",
8+
"dev": "nodemon index.js"
9+
},
10+
"author": "",
11+
"license": "ISC",
12+
"dependencies": {
13+
"bcrypt-nodejs": "0.0.3",
14+
"body-parser": "^1.17.1",
15+
"express": "^4.15.2",
16+
"jwt-simple": "^0.5.1",
17+
"mongoose": "^4.9.4",
18+
"morgan": "^1.8.1",
19+
"nodemon": "^1.11.0",
20+
"passport": "^0.3.2",
21+
"passport-jwt": "^2.2.1",
22+
"passport-local": "^1.0.0"
23+
}
24+
}

Diff for: router.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const Authentication = require('./controllers/authentication');
2+
const passportService = require('./services/passport');
3+
const passport = require('passport');
4+
5+
const requireAuth = passport.authenticate('jwt', { session: false });
6+
const requireSignin = passport.authenticate('local', { session: false });
7+
8+
module.exports = function(app) {
9+
app.get('/', requireAuth, function(req, res) {
10+
res.send({ thisisajourney: 'into sound' });
11+
});
12+
app.post('/signin', requireSignin, Authentication.signin);
13+
app.post('/signup', Authentication.signup);
14+
}

Diff for: services/passport.js

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const passport = require('passport');
2+
const User = require('../models/user');
3+
const config = require('../config');
4+
const JwtStrategy = require('passport-jwt').Strategy;
5+
const ExtractJwt = require('passport-jwt').ExtractJwt;
6+
const LocalStragegy = require('passport-local');
7+
8+
// Create Local Strategy
9+
const localOptions = { usernameField: 'email' };
10+
const localLogin = new LocalStragegy(localOptions, function(email, password, done){
11+
// Verify this username and password, call done with the user
12+
// if it is the correct email and password
13+
// otherwise, call done with false
14+
User.findOne({ email: email }, function(err, user) {
15+
if (err) { return done(err); }
16+
if (!user) { return done(null, false); }
17+
18+
// compare passwords - is `password` equal to user.password?
19+
user.comparePassword(password, function(err, isMatch) {
20+
if (err) { return done(err); }
21+
if (!isMatch) { return done(null, false); }
22+
23+
return done(null, user);
24+
})
25+
});
26+
});
27+
28+
// Setup options for JWT Strategy
29+
const jwtOptions = {
30+
jwtFromRequest: ExtractJwt.fromHeader('authorization'),
31+
secretOrKey: config.secret
32+
};
33+
34+
// Create JWT Strategy
35+
const jwtLogin = new JwtStrategy(jwtOptions, function(payload, done) {
36+
// See if the user ID in the payload exists in our database
37+
// If it does, call 'done' with that user
38+
// otherwise, call down without a user object
39+
User.findById(payload.sub, function(err, user) {
40+
if (err) { return done(err, false); }
41+
42+
if (user) {
43+
done(null, user);
44+
} else {
45+
done(null, false);
46+
}
47+
});
48+
});
49+
50+
// Tell passport to use this strategy
51+
passport.use(jwtLogin);
52+
passport.use(localLogin);
53+

0 commit comments

Comments
 (0)