Skip to content

Commit

Permalink
feat: use mock authentication for local dev
Browse files Browse the repository at this point in the history
  • Loading branch information
tchaffee committed Oct 31, 2018
1 parent 9cbbadc commit 453f9c7
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 6 deletions.
29 changes: 29 additions & 0 deletions api-server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions api-server/package.json
Expand Up @@ -102,6 +102,7 @@
"joi-objectid": "^2.0.0",
"loopback-component-explorer": "^6.3.1",
"nodemon": "^1.18.4",
"passport-mock-strategy": "^1.1.1",
"pm2": "^3.0.3",
"prettier": "^1.14.2",
"sinon": "^2.0.0",
Expand Down
35 changes: 29 additions & 6 deletions api-server/server/boot/authentication.js
Expand Up @@ -7,7 +7,11 @@ import { check } from 'express-validator/check';

import { homeLocation } from '../../../config/env';
import { createCookieConfig } from '../utils/cookieConfig';
import { createPassportCallbackAuthenticator } from '../component-passport';
import {
createPassportCallbackAuthenticator,
saveResponseAuthCookies,
loginRedirect
} from '../component-passport';
import {
ifUserRedirectTo,
ifNoUserRedirectTo,
Expand All @@ -25,15 +29,34 @@ module.exports = function enableAuthentication(app) {
// loopback.io/doc/en/lb2/Authentication-authorization-and-permissions.html
app.enableAuth();
const ifUserRedirect = ifUserRedirectTo();
const saveAuthCookies = saveResponseAuthCookies();
const loginSuccessRedirect = loginRedirect();
const ifNoUserRedirectHome = ifNoUserRedirectTo(homeLocation);
const api = app.loopback.Router();
const { AuthToken, User } = app.models;

api.get('/signin', ifUserRedirect, passport.authenticate('auth0-login', {}));
api.get(
'/auth/auth0/callback',
createPassportCallbackAuthenticator('auth0-login', { provider: 'auth0' })
);
// Use a local mock strategy for signing in if we are in dev mode.
// Otherwise we use auth0 login. We use a string for 'true' because values
// set in the env file will always be strings and never boolean.
if (process.env.LOCAL_AUTH === 'true') {
api.get(
'/signin',
passport.authenticate('devlogin'),
saveAuthCookies,
loginSuccessRedirect
);
} else {
api.get(
'/signin',
ifUserRedirect,
passport.authenticate('auth0-login', {})
);

api.get(
'/auth/auth0/callback',
createPassportCallbackAuthenticator('auth0-login', { provider: 'auth0' })
);
}

api.get('/signout', (req, res) => {
req.logout();
Expand Down
44 changes: 44 additions & 0 deletions api-server/server/component-passport.js
Expand Up @@ -131,6 +131,50 @@ export function setupPassport(app) {
});
}

export const saveResponseAuthCookies = () => {

return (req, res, next) => {

const user = req.user;

if (!user) {
return res.redirect('/signin');
}

const { accessToken } = user;

const cookieConfig = {
...createCookieConfig(req),
maxAge: 77760000000
};
const jwtAccess = jwt.sign({ accessToken }, jwtSecret);
res.cookie('jwt_access_token', jwtAccess, cookieConfig);
res.cookie('access_token', accessToken.id, cookieConfig);
res.cookie('userId', accessToken.userId, cookieConfig);

return next();
};
};

export const loginRedirect = () => {

return (req, res) => {
const successRedirect = req => {
if (!!req && req.session && req.session.returnTo) {
delete req.session.returnTo;
return `${homeLocation}/welcome`;
}
return `${homeLocation}/welcome`;
};

let redirect = url.parse(successRedirect(req), true);
delete redirect.search;

redirect = url.format(redirect);
return res.redirect(redirect);
};
};

export const createPassportCallbackAuthenticator = (strategy, config) => (
req,
res,
Expand Down
5 changes: 5 additions & 0 deletions api-server/server/passport-providers.js
Expand Up @@ -7,6 +7,11 @@ const successRedirect = `${homeLocation}/welcome`;
const failureRedirect = '/signin';

export default {
devlogin: {
authScheme: 'mock',
provider: 'dev',
module: 'passport-mock-strategy'
},
local: {
provider: 'local',
module: 'passport-local',
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -9,6 +9,7 @@
"lint": "echo 'Warning: TODO - Define Linting.'",
"pretest-ci": "npm-run-all -s lint bootstrap",
"seed": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedChallenges",
"seed-auth-user": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedAuthUser",
"start-develop": "node ./tools/scripts/start-develop.js",
"test": "npm-run-all -p test:*",
"test-ci": "npm test",
Expand Down
101 changes: 101 additions & 0 deletions tools/scripts/seed/seedAuthUser.js
@@ -0,0 +1,101 @@
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../../.env') });
const MongoClient = require('mongodb').MongoClient;
const ObjectId = require('mongodb').ObjectID;
const debug = require('debug');

const log = debug('fcc:tools:seedLocalAuthUser');
const { MONGOHQ_URL, LOCALE: lang } = process.env;

function handleError(err, client) {
if (err) {
console.error('Oh noes!! Error seeding local auth user.');
console.error(err);
try {
client.close();
} catch (e) {
// no-op
} finally {
/* eslint-disable-next-line no-process-exit */
process.exit(1);
}
}
}

MongoClient.connect(
MONGOHQ_URL,
{ useNewUrlParser: true },
function(err, client) {
handleError(err, client);

log('Connected successfully to mongo');

const db = client.db('freecodecamp');
const user = db.collection('user');

user.deleteOne({_id: ObjectId('5bd30e0f1caf6ac3ddddddb5') }, (err) => {
handleError(err, client);

try {
user.insertOne(
{
_id: ObjectId('5bd30e0f1caf6ac3ddddddb5'),
email: 'foo@bar.com',
emailVerified: true,
progressTimestamps: [],
isBanned: false,
isCheater: false,
username: 'DevelopmentUser',
about: '',
name: 'Development User',
location: '',
picture: 'https://identicon.org/?t=dev&s=256',
acceptedPrivacyTerms: true,
sendQuincyEmail: false,
currentChallengeId: '',
isHonest: false,
isFrontEndCert: false,
isDataVisCert: false,
isBackEndCert: false,
isFullStackCert: false,
isRespWebDesignCert: false,
is2018DataVisCert: false,
isFrontEndLibsCert: false,
isJsAlgoDataStructCert: false,
isApisMicroservicesCert: false,
isInfosecQaCert: false,
is2018FullStackCert: false,
completedChallenges: [],
portfolio: [],
yearsTopContributor: [],
rand: 0.6126749173148205,
theme: 'default',
profileUI: {
isLocked: true,
showAbout: false,
showCerts: false,
showDonation: false,
showHeatMap: false,
showLocation: false,
showName: false,
showPoints: false,
showPortfolio: false,
showTimeLine: false
},
badges: {
coreTeam: []
},
isDonating: false,
emailAuthLinkTTL: null,
emailVerifyTTL: null
}
);
} catch (e) {
handleError(e, client);
} finally {
log('local auth user seed complete');
client.close();
}
});
}
);

0 comments on commit 453f9c7

Please sign in to comment.