Skip to content

Instantly share code, notes, and snippets.

@xeoncross
Forked from jokecamp/package.json
Created October 25, 2017 00:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save xeoncross/bae6f2c5be40bf0c6993089d4de2175e to your computer and use it in GitHub Desktop.
Save xeoncross/bae6f2c5be40bf0c6993089d4de2175e to your computer and use it in GitHub Desktop.
Demo for Passport.js authentication in a Node.js Express application
{
"extends": "airbnb",
"parser": "babel-eslint",
"rules": {
"no-console": 0,
"react/jsx-filename-extension": 0,
}
}

Simple Node Passport Demo

Using passport-local and passport-github we show how you could handle logins.

const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
var records = [
{ id: 1, password: "password", email: "admin@example.com" },
{ id: 2, password: "password", email: "user@example.com" }
];
var findById = function(id, cb) {
process.nextTick(function() {
var idx = id - 1;
if (records[idx]) {
cb(null, records[idx]);
} else {
cb(new Error("User " + id + " does not exist"));
}
});
};
var findByEmail = function(email, cb) {
process.nextTick(function() {
for (var i = 0; i < records.length; i++) {
if (records[i].email == email) {
return cb(null, records[i]);
} else {
console.log(records[i].email, "!=", email);
}
}
return cb(null, null);
});
};
/**
* Sign in using Email and Password.
*/
// The local strategy require a `verify` function which receives the credentials
// (`username` and `password`) submitted by the user. The function must verify
// that the password is correct and then invoke `cb` with a user object, which
// will be set at `req.user` in route handlers after authentication.
passport.use(
new LocalStrategy({ usernameField: "email" }, function(email, password, cb) {
findByEmail(email, function(err, user) {
if (err) {
return cb(err);
}
if (!user) {
console.log("user not found", email, password);
return cb(null, false, { error: "Invalid email or password." });
}
if (user.password != password) {
console.log("password doesn't match");
return cb(null, false, { error: "Invalid email or password." });
}
return cb(null, user);
});
})
);
// Configure Passport authenticated session persistence.
//
// In order to restore authentication state across HTTP requests, Passport needs
// to serialize users into and deserialize users out of the session. The
// typical implementation of this is as simple as supplying the user ID when
// serializing, and querying the user record by ID from the database when
// deserializing.
passport.serializeUser(function(user, cb) {
console.log("serializeUser", user);
cb(null, user.id);
});
passport.deserializeUser(function(id, cb) {
console.log("deserializeUser", id);
findById(id, function(err, user) {
if (err) {
return cb(err);
}
cb(null, user);
});
});
/**
* Login Required middleware.
*/
const isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return next();
}
res.redirect("/login");
};
/**
* Authorization Required middleware.
* We only support passport-local so we don't need this
*/
const isAuthorized = (req, res, next) => {
const provider = req.path.split("/").slice(-1)[0];
const token = req.user.tokens.find(token => token.kind === provider);
if (token) {
next();
} else {
res.redirect(`/auth/${provider}`);
}
};
module.exports = {
isAuthorized,
isAuthenticated
};
module.exports = {
github: {
clientId: "...",
clientSecret: "...",
}
}
var passport = require("passport");
var GithubStrategy = require("passport-github").Strategy;
const config = require("./config");
passport.use(
new GithubStrategy(
{
clientID: config.github.clientId,
clientSecret: config.github.clientSecret,
callbackURL: "http://localhost:3000/auth/github/callback",
passReqToCallback: true
},
function(req, accessToken, refreshToken, profile, done) {
console.log(profile);
// placeholder for translating profile into your own custom user object.
// for now we will just use the profile object returned by GitHub
return done(null, profile);
}
)
);
{
"name": "simple_auth",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT",
"dependencies": {
"body-parser": "^1.18.2",
"express": "^4.13.3",
"express-session": "^1.11.3",
"express-validator": "^4.2.1",
"passport": "^0.3.0",
"passport-github": "^1.0.0",
"passport-local": "^1.0.0"
}
}
var express = require("express");
var passport = require("passport");
var auth = require("./auth");
var github = require("./github");
const expressValidator = require("express-validator");
const bodyParser = require("body-parser");
const path = require("path");
var app = express();
app.use(expressValidator());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, "public"), { maxAge: 1 }));
// Express and Passport Session
var session = require("express-session");
app.use(
session({
secret: process.env.SESSION_SECRET || "foobar",
resave: false,
saveUninitialized: false
})
);
app.use(passport.initialize());
app.use(passport.session());
app.get("/login", (req, res) => {
const html = `<form method="POST" action="/login">
<label>Email</label><input name="email" type="email" /><br><br>
<label>Password</label><input type="password" name="password" /><br>
<input type="submit" value="Login" />
</form>`;
res.send(html);
});
app.post("/login", (req, res, next) => {
console.log("app.post/login", req.body);
req.assert("email", "Email is not valid").isEmail();
req.assert("password", "Password cannot be blank").notEmpty();
req.sanitize("email").normalizeEmail({ gmail_remove_dots: false });
const errors = req.validationErrors();
if (errors) {
return res.json({ errors: errors });
// return res.redirect('/login')
}
passport.authenticate("local", (err, user, info) => {
if (err) {
console.log("err", err);
return next(err);
}
if (!user) {
console.log("!user", info, user);
return res.json(info);
}
req.logIn(user, err => {
if (err) {
console.log("logIn", err);
return next(err);
}
console.log(user);
// If this is an API
// res.json({ user: user });
// If this is a regular POST request
res.redirect("/");
});
})(req, res, next);
});
// we will call this to start the GitHub Login process
app.get("/auth/github", passport.authenticate("github"));
// GitHub will call this URL
app.get(
"/auth/github/callback",
passport.authenticate("github", { failureRedirect: "/" }),
function(req, res) {
res.redirect("/");
}
);
app.get("/", function(req, res) {
var html =
"<ul>\
<li><a href='/auth/github'>GitHub</a></li>\
<li><a href='/login'>Login</a></li>\
<li><a href='/logout'>logout</a></li>\
<li><a href='/admin'>Admin</a></li>\
</ul>";
// dump the user for debugging
if (req.isAuthenticated()) {
html += "<p>authenticated as user:</p>";
html += "<pre>" + JSON.stringify(req.user, null, 4) + "</pre>";
}
// dump the user for debugging
if (req.isAuthenticated()) {
html += "<p>authenticated as user:</p>";
html += "<pre>" + JSON.stringify(req.user, null, 4) + "</pre>";
}
res.send(html);
});
app.get("/logout", function(req, res) {
req.logout();
res.redirect("/");
});
app.get("/admin", auth.isAuthenticated, function(req, res) {
res.send("Private Admin Area");
});
const port = process.env.PORT || process.env.OPENSHIFT_NODEJS_PORT || 3000;
var server = app.listen(port, function() {
console.log(
"Example app listening at http://%s:%s",
server.address().address,
server.address().port
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment