diff --git a/src/config/router.js b/src/config/router.js index fee4e3a..2701a77 100644 --- a/src/config/router.js +++ b/src/config/router.js @@ -10,12 +10,14 @@ function router(app) { // Auth Endpoints app.get('/auth/twitter/token', AuthHandlers.getTwitterToken ); app.get('/auth/twitter/username', AuthHandlers.getTwitterUsername ); + app.get('/auth/session/:sessionId/exists', AuthHandlers.doesSessionExist); app.get('/auth/email/:email/exists', AuthHandlers.doesAttributeExist ); app.get('/auth/tagferId/:tagferId/exists', AuthHandlers.doesAttributeExist ); app.post('/auth/phone/code', AuthHandlers.sendPhoneCode); app.post('/auth/phone/verify', AuthHandlers.verifyPhoneCode); app.post('/auth/signin', AuthHandlers.signin); app.put('/auth/signup', AuthHandlers.signup); + app.post('/auth/signout', AuthHandlers.signout); app.post('/auth/passwordReset', AuthHandlers.sendPasswordResetEmail); // Users Endpoints diff --git a/src/ups/auth/dao.js b/src/ups/auth/dao.js index ce86a29..127af32 100644 --- a/src/ups/auth/dao.js +++ b/src/ups/auth/dao.js @@ -114,7 +114,7 @@ function createNewSessionId(tagferId) { */ function getSession(id) { const sessions = loki.getCollection('sessions'); - var session = sessions.by('id', id); + const session = sessions.by('id', id); if (session) { return session; } else { @@ -122,6 +122,16 @@ function getSession(id) { } } +/** + * Removes the loki session containing the tagferId on the server + * @param {String} id + */ +function deleteSession(id) { + const sessions = loki.getCollection('sessions'); + const session = getSession(id); + sessions.remove(session); +} + /** * Create new verification code for the phone number */ @@ -183,6 +193,7 @@ module.exports = { createNewUser, createNewSessionId, getSession, + deleteSession, resetPassword }; diff --git a/src/ups/auth/handlers.js b/src/ups/auth/handlers.js index 1de5593..d1c7bc6 100644 --- a/src/ups/auth/handlers.js +++ b/src/ups/auth/handlers.js @@ -23,6 +23,27 @@ function doesAttributeExist(req, res) { promise.then((result) => res.json({ result }) ).catch(error => res.json(error)); } +/** + * Endpoint: auth/session/:sessionId/exists + * Checks if a user session exists. + * Brute force session id attack safe by app secret. + * @param {Object} req {} + * @param {Object} res { result: Boolean } + */ +function doesSessionExist(req, res) { + const { sessionId } = req.params; + if (!utils.isAppSecretValid(req,res)) { + return; + } + + try { + authDao.getSession(sessionId); + res.json({ result: true}); + } catch(error) { + res.json({ result: false }); + } +} + /** * Handles the request/response for auth/phone/code. Uses the data layer to generate a unique code, * if the phone number is not in our system. @@ -90,6 +111,23 @@ function signin(req, res) { }); } +/** + * Endpoint: auth/signout + * Signs out by deleting his session + * @param {Object} req {} + * @param {Object} res { error: String } | {} + */ +function signout(req, res) { + const sessionId = utils.getSessionIdFromAuthHeader(req); + + try { + authDao.deleteSession(sessionId); + res.json({}); + } catch(error) { + res.json({ error }); + } +} + /** * Endpoint: auth/signup * Signs up the user by creating a new user in firebase admin. @@ -161,10 +199,12 @@ function getTwitterUsername(req, res) { module.exports = { doesAttributeExist, + doesSessionExist, sendPhoneCode, verifyPhoneCode, signin, signup, + signout, sendPasswordResetEmail, getTwitterToken, getTwitterUsername