diff --git a/website/src/controllers/api-v2/auth.js b/website/src/controllers/api-v2/auth.js index b3a552721a..b01e1aba3d 100644 --- a/website/src/controllers/api-v2/auth.js +++ b/website/src/controllers/api-v2/auth.js @@ -53,6 +53,7 @@ api.authWithSession = function(req, res, next) { //[todo] there is probably a mo }); }; +// TODO passing auth params as query params is not safe as they are logged by browser history, ... api.authWithUrl = function(req, res, next) { User.findOne({_id:req.query._id, apiToken:req.query.apiToken}, function(err,user){ if (err) return next(err); diff --git a/website/src/middlewares/api-v3/auth.js b/website/src/middlewares/api-v3/auth.js new file mode 100644 index 0000000000..583b087353 --- /dev/null +++ b/website/src/middlewares/api-v3/auth.js @@ -0,0 +1,66 @@ +// Middlewares used to authenticate requests +import { + NotAuthorized, +} from '../../libs/api-v3/errors'; + +import { + UserModel as User, +} from '../../models/user'; + +// TODO use i18n +const missingAuthHeaders = 'Missing authentication headers.'; +const userNotFound = 'User not found.'; +const accountSuspended = (user) => { + return `Account has been suspended, please contact leslie@habitica.com + with your UUID ${user._id} for assistance.`; +}; + +// TODO adopt JSDoc syntax? +// Authenticate a request through the x-api-user and x-api key header +export function authWithHeaders (req, res, next) { + let userId = req.header['x-api-user']; + let apiToken = req.header['x-api-key']; + + if (!userId || !apiToken) { + // TODO use i18n? + // TODO use badrequest error? + return next(new NotAuthorized(missingAuthHeaders)); + } + + // TODO use promises? + User.findOne({ + _id: userId, + apiToken, + }, (err, user) => { + if (err) return next(err); + if (!user) return next(new NotAuthorized(userNotFound)); + + // TODO better handling for this case + if (user.blocked) return next(new NotAuthorized(accountSuspended(user))); + + res.locals.user = user; + // TODO use either session/cookie or headers, not both + req.session.userId = user._id; + return next(); + }); +} + +// Authenticate a request through a valid session +// TODO should use json web token +export function authWithSession (req, res, next) { + let session = req.session; + + if (!session || !session.userId) { + return next(new NotAuthorized(userNotFound)); + } + + User.findOne({ + _id: session.userId, + }, (err, user) => { + if (err) return next(err); + if (!user) return next(new NotAuthorized(userNotFound)); + + res.locals.user = user; + return next(); + }); +} \ No newline at end of file diff --git a/website/src/middlewares/api-v3/errorHandler.js b/website/src/middlewares/api-v3/errorHandler.js index 4950d09e09..97e324aee3 100644 --- a/website/src/middlewares/api-v3/errorHandler.js +++ b/website/src/middlewares/api-v3/errorHandler.js @@ -21,7 +21,6 @@ export default function errorHandler (err, req, res, next) { // In case of a CustomError class, use it's data // Otherwise try to identify the type of error (mongoose validation, mongodb unique, ...) // If we can't identify it, respond with a generic 500 error - let responseErr = err instanceof CustomError ? err : null; if (!responseErr) {