Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

Commit

Permalink
Merge pull request #12 from ministryofjustice/ag--auth0-hosted-login-…
Browse files Browse the repository at this point in the history
…page

Use Auth0 hosted login page.
  • Loading branch information
xoen authored Feb 16, 2018
2 parents 2732a67 + da103c9 commit 333c205
Show file tree
Hide file tree
Showing 11 changed files with 1,224 additions and 2,166 deletions.
20 changes: 20 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
"extends": "airbnb-base",
"env": {
"browser": true,
"mocha": true,
},
"globals": {
"$": false,
"moj": true,
},
"rules": {
"camelcase": ["off"],
"no-alert": ["off"],
"import/no-dynamic-require": ["off"],
"no-use-before-define": ["error", { "classes": false }],
"object-curly-newline": ["error", { "consistent": true }],
"no-param-reassign": ["error", { "props": false }],
"no-underscore-dangle": ["error", { "allow": ["_json"] }],
}
};
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:6.11-alpine
FROM node:8.9.4-alpine

WORKDIR /app

Expand Down
29 changes: 19 additions & 10 deletions app/config.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,49 @@
var config = module.exports;
const config = module.exports;


config.app = {
protocol: process.env.APP_PROTOCOL || 'http',
host: process.env.APP_HOST || 'localhost:3000',
};

config.express = {
port: process.env.EXPRESS_PORT || 3000,
host: process.env.EXPRESS_HOST || '127.0.0.1'
host: process.env.EXPRESS_HOST || '127.0.0.1',
};

config.log = {
level: process.env.LOG_LEVEL || 'debug'
level: process.env.LOG_LEVEL || 'debug',
};

config.session = {
secret: process.env.COOKIE_SECRET || 'shh-its-a-secret',
name: 'session',
resave: true,
saveUninitialized: true
saveUninitialized: true,
secret: process.env.COOKIE_SECRET || 'shh-its-a-secret',
};

config.auth0 = {
domain: process.env.AUTH0_DOMAIN,
callbackURL: process.env.AUTH0_CALLBACK_URL || 'http://localhost:3000/callback',
clientID: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
callbackURL: process.env.AUTH0_CALLBACK_URL || 'http://localhost:3000/callback'
domain: process.env.AUTH0_DOMAIN,
passReqToCallback: true,
scope: 'profile',
sso_logout_url: '/v2/logout',
};

config.proxy = {
target: {
host: process.env.PROXY_TARGET_HOST,
port: process.env.PROXY_TARGET_PORT
port: process.env.PROXY_TARGET_PORT,
},
ws: true,
preserveHeaderKeyCase: true,
proxyTimeout: process.env.PROXY_TIMEOUT || (24 * 60 * 60 * 1000)
proxyTimeout: process.env.PROXY_TIMEOUT || (24 * 60 * 60 * 1000),
};

config.rstudio = {
user: process.env.RSTUDIO_USER || process.env.USER,
duration: (24 * 60 * 60 * 1000),
key: process.env.SECURE_COOKIE_KEY
key: process.env.SECURE_COOKIE_KEY,
};
6 changes: 3 additions & 3 deletions app/errors.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// catch 404s and forward to error handler
module.exports = function(req, res, next) {
var err = new Error('Not Found');
module.exports = (req, res, next) => {
const err = new Error('Not Found');
err.status = 404;
next(err);
}
};
47 changes: 24 additions & 23 deletions app/index.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,51 @@
require('dotenv').config();
var bole = require('bole');
var config = require('./config');
var morgan = require('morgan');
var nunjucks = require('nunjucks');
var passport = require('passport');
var path = require('path');
var Auth0Strategy = require('passport-auth0');
const bole = require('bole');
const express = require('express');
const morgan = require('morgan');
const passport = require('passport');
const path = require('path');
const Auth0Strategy = require('passport-auth0-openidconnect').Strategy;

const config = require('./config');
const errors = require('./errors');
const routes = require('./routes');

var app = require('express')();

const app = express();
app.set('views', path.join(__dirname, 'views'));

// add before logging to avoid favicon requests in logs
app.use(require('serve-favicon')(path.join(__dirname, 'favicon.ico')));

bole.output({level: config.log.level, stream: process.stdout});
bole.output({ level: config.log.level, stream: process.stdout });
app.use(morgan('combined'));

nunjucks.configure(path.join(__dirname, 'views'), {
autoescape: true,
express: app
});

app.use(require('cookie-parser')());
app.use(require('express-session')(config.session));

passport.use(new Auth0Strategy(
const strategy = new Auth0Strategy(
config.auth0,
function(accessToken, refreshToken, extraParams, profile, done) {
return done(null, profile);
}
));
((req, issuer, audience, profile, accessToken, refreshToken, params, callback) => {
req.session.id_token = params.id_token;

return callback(null, profile._json);
}),
);
passport.use(strategy);

passport.serializeUser(function(user, done) {
passport.serializeUser((user, done) => {
done(null, user);
});

passport.deserializeUser(function(user, done) {
passport.deserializeUser((user, done) => {
done(null, user);
});

app.use(passport.initialize());
app.use(passport.session());

app.use(require('./routes'));
app.use(require('./errors'));
app.use(routes);
app.use(errors);


module.exports = app;
26 changes: 12 additions & 14 deletions app/middleware.js → app/middleware/authorization.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
var config = require('./config');
const config = require('../config');
const log = require('bole')('middleware');


module.exports.denyUnauthorized = function (req, res, next) {

if (isAuthorized(req)) {
next();

} else {
res.sendStatus(403);
next(new Error('User is not authorized'));
}
};

function isAuthorized(req) {
try {
return req.user.nickname.toLowerCase() === config.rstudio.user;

} catch (error) {
// do nothing
log.error('Error while checking user nickname: ', error);
}

return false;
}

module.exports = function (req, res, next) {
if (isAuthorized(req)) {
next();
} else {
res.sendStatus(403);
next(new Error('User is not authorized'));
}
};
66 changes: 39 additions & 27 deletions app/routes.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,62 @@
var config = require('./config');
var ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
var express = require('express');
var middleware = require('./middleware');
var passport = require('passport');
var proxy = require('./proxy');
var router = new express.Router();
const { ensureLoggedIn } = require('connect-ensure-login');
const express = require('express');
const passport = require('passport');

const config = require('./config');
const authorization = require('./middleware/authorization');
const proxy = require('./proxy');

router.get('/login', function(req, res) {
res.render('login.html', {auth0: config.auth0});
});

router.get('/logout', function(req, res) {
req.logout();
res.redirect('/login');
const router = new express.Router();

const RETURN_TO = encodeURI(`${config.app.protocol}://${config.app.host}`);
const SSO_LOGOUT_URL = `https://${config.auth0.domain}${config.auth0.sso_logout_url}?returnTo=${RETURN_TO}&client_id=${config.auth0.clientID}`;


router.get('/login', (req, res, next) => {
if (req.isAuthenticated()) {
if (/^http/.test(req.session.returnTo)) {
res.send(400, 'URL must be relative');
} else {
res.redirect(req.session.returnTo);
}
} else {
passport.authenticate('auth0-oidc')(req, res, next);
}
});

router.get('/auth-sign-out', function (req, res) {
router.get(['/logout', '/auth-sign-out'], (req, res) => {
req.logout();
res.redirect('/login');
req.session.destroy(() => {
res.clearCookie(config.session.name);
res.redirect(SSO_LOGOUT_URL);
});
});

router.get('/callback', [
passport.authenticate('auth0', { failureRedirect: '/login' }),
function(req, res) {
passport.authenticate('auth0-oidc', { failureRedirect: '/login' }),
(req, res) => {
res.redirect(req.session.returnTo || '/');
}
},
]);

router.all(/.*/, [
ensureLoggedIn('/login'),
middleware.denyUnauthorized,
function(req, res) {
parseBody(req).then(function (body) {
authorization,
(req, res) => {
parseBody(req).then((body) => {
req.body = body;
proxy.web(req, res);
});
}
},
]);

function parseBody(req) {
var body = [];
return new Promise(function (resolve, reject) {
req.on('data', function (chunk) { body.push(chunk); });
req.on('end', function () { resolve(body); });
req.on('error', function (err) { reject(err); });
let body = [];
return new Promise((resolve, reject) => {
req.on('data', (chunk) => { body.push(chunk); });
req.on('end', () => { resolve(body); });
req.on('error', (err) => { reject(err); });
});
}

Expand Down
9 changes: 0 additions & 9 deletions app/views/layout.html

This file was deleted.

24 changes: 0 additions & 24 deletions app/views/login.html

This file was deleted.

Loading

0 comments on commit 333c205

Please sign in to comment.