diff --git a/app/routes/auth.js b/app/routes/auth.js index 02375ec..5d5eecc 100644 --- a/app/routes/auth.js +++ b/app/routes/auth.js @@ -9,7 +9,7 @@ const Invite = require(ModelPath + 'Invite.js'); const passport = require('passport'); const canonicalizeRequest = require('../util/canonicalize').canonicalizeRequest; -const requireAuth = require('../util/requireAuth'); +const requireAuth = require('../util/auth').requireAuth; const wrap = require('../util/wrap.js'); const verifyBody = require('../util/verifyBody'); diff --git a/app/routes/invite.js b/app/routes/invite.js index a03dbec..96312e1 100644 --- a/app/routes/invite.js +++ b/app/routes/invite.js @@ -7,7 +7,7 @@ const Invite = require(ModelPath + 'Invite.js'); const User = require(ModelPath + 'User.js'); const wrap = require('../util/wrap.js'); -const requireAuth = require('../util/requireAuth'); +const requireAuth = require('../util/auth').requireAuth; const verifyScope = require('../util/verifyScope'); const verifyBody = require('../util/verifyBody'); diff --git a/app/util/auth.js b/app/util/auth.js new file mode 100644 index 0000000..8d91881 --- /dev/null +++ b/app/util/auth.js @@ -0,0 +1,62 @@ +const ModelPath = '../models/'; +const Key = require(ModelPath + 'Key.js'); + +const wrap = require('./wrap.js'); +const verifyScope = require('./verifyScope.js'); + +const checkSession = (req, scope, status) => { + if (req.isAuthenticated()) { + status.authenticated = true; + if (!scope || verifyScope(req.session.passport.scope, scope)) { + req.username = req.session.passport.user; + req.displayname = req.session.passport.displayname; + req.scope = req.session.passport.scope; + req.key = null; + status.permission = true; + } + } +}; + +const checkKey = async (req, scope, status) => { + if (req.body.key) { + const key = await Key.findOne({key: req.body.key}); + if (key) { + status.authenticated = true; + if (!scope || verifyScope(key.scope, scope)) { + req.username = key.issuer; + req.displayname = key.issuer; + req.scope = key.scope; + req.key = key.key; + status.permission = true; + } + } + } +}; + +// Middleware that checks for authentication by either API key or session +// sets req.username, req.displayname, req.scope, and req.key if authenticated properly, +// otherwise throws an error code +const auth = scope => + wrap(async (req, res, next) => { + const status = { + authenticated: false, + permission: false + }; + + // First, check the session + checkSession(req, scope, status); + // If not authenticated yet, check for a key + if (!status.authenticated) + await checkKey(req, scope, status); + + if (!status.authenticated) + return res.status(401).json({message: 'Unauthorized.'}); + else if (!status.permission) + return res.status(403).json({message: 'Forbidden.'}); + else + next(); + }); + +module.exports.checkSession = checkSession; +module.exports.checkKey = checkKey; +module.exports.requireAuth = auth; diff --git a/app/util/requireAuth.js b/app/util/requireAuth.js deleted file mode 100644 index 27881e0..0000000 --- a/app/util/requireAuth.js +++ /dev/null @@ -1,39 +0,0 @@ -const Key = require('../models/Key.js'); -const wrap = require('./wrap.js'); - -const verifyScope = require('./verifyScope.js'); - -// Checks for authentication by either API Key or Session -// Sets body.authUser and body.authKey if check passed -// If the request is authenticated and has the desired scope, continue. -// If the request is authenticated, but lacks the required scope, return 403 Forbidden. -// If the request is unauthenticated, return 401 Unauthorized. -const requireAuth = scope => - wrap(async (req, res, next) => { - if (req.isAuthenticated()) { - if (scope ? verifyScope(req.session.passport.scope, scope) : true) { - req.username = req.session.passport.user; - req.displayname = req.session.passport.displayname; - req.scope = req.session.passport.scope; - req.key = null; - next(); - } else { - res.status(403).json({message: 'Forbidden.'}); - } - } else if (req.body.key) { - const key = await Key.findOne({key: key}); - if (scope ? verifyScope(key.scope, scope) : true) { - req.username = key.issuer; - req.displayname = key.issuer; - req.scope = key.scope; - req.key = key.key; - next(); - } else { - res.status(403).json({message: 'Forbidden.'}); - } - } else { - res.status(401).json({'message': 'Unauthorized.'}); - } - }); - -module.exports = requireAuth; \ No newline at end of file