2018-04-26 15:54:53 -07:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
exports = module.exports = {
|
|
|
|
|
scope: scope,
|
2018-06-15 17:31:28 -07:00
|
|
|
websocketAuth: websocketAuth,
|
|
|
|
|
initialize: initialize,
|
|
|
|
|
uninitialize: uninitialize
|
2018-04-26 15:54:53 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var accesscontrol = require('../accesscontrol.js'),
|
|
|
|
|
assert = require('assert'),
|
2018-06-15 17:31:28 -07:00
|
|
|
BasicStrategy = require('passport-http').BasicStrategy,
|
|
|
|
|
BearerStrategy = require('passport-http-bearer').Strategy,
|
|
|
|
|
clients = require('../clients.js'),
|
|
|
|
|
ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy,
|
|
|
|
|
ClientsError = clients.ClientsError,
|
2018-04-26 15:54:53 -07:00
|
|
|
HttpError = require('connect-lastmile').HttpError,
|
2018-06-15 17:31:28 -07:00
|
|
|
LocalStrategy = require('passport-local').Strategy,
|
|
|
|
|
passport = require('passport'),
|
|
|
|
|
users = require('../users.js'),
|
|
|
|
|
UsersError = users.UsersError;
|
|
|
|
|
|
|
|
|
|
function initialize(callback) {
|
|
|
|
|
assert.strictEqual(typeof callback, 'function');
|
|
|
|
|
|
|
|
|
|
// serialize user into session
|
|
|
|
|
passport.serializeUser(function (user, callback) {
|
|
|
|
|
callback(null, user.id);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// deserialize user from session
|
|
|
|
|
passport.deserializeUser(function(userId, callback) {
|
|
|
|
|
users.get(userId, function (error, result) {
|
|
|
|
|
if (error) return callback(error);
|
|
|
|
|
|
|
|
|
|
callback(null, result);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// used when username/password is sent in request body. used in CLI tool login route
|
|
|
|
|
passport.use(new LocalStrategy(function (username, password, callback) {
|
|
|
|
|
if (username.indexOf('@') === -1) {
|
|
|
|
|
users.verifyWithUsername(username, password, function (error, result) {
|
|
|
|
|
if (error && error.reason === UsersError.NOT_FOUND) return callback(null, false);
|
|
|
|
|
if (error && error.reason === UsersError.WRONG_PASSWORD) return callback(null, false);
|
|
|
|
|
if (error) return callback(error);
|
|
|
|
|
if (!result) return callback(null, false);
|
|
|
|
|
callback(null, result);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
users.verifyWithEmail(username, password, function (error, result) {
|
|
|
|
|
if (error && error.reason === UsersError.NOT_FOUND) return callback(null, false);
|
|
|
|
|
if (error && error.reason === UsersError.WRONG_PASSWORD) return callback(null, false);
|
|
|
|
|
if (error) return callback(error);
|
|
|
|
|
if (!result) return callback(null, false);
|
|
|
|
|
callback(null, result);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// Used to authenticate a OAuth2 client which uses clientId and clientSecret in the Authorization header
|
|
|
|
|
passport.use(new BasicStrategy(function (clientId, clientSecret, callback) {
|
|
|
|
|
clients.get(clientId, function (error, client) {
|
|
|
|
|
if (error && error.reason === ClientsError.NOT_FOUND) return callback(null, false);
|
|
|
|
|
if (error) return callback(error);
|
|
|
|
|
if (client.clientSecret !== clientSecret) return callback(null, false);
|
|
|
|
|
callback(null, client);
|
|
|
|
|
});
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// Used to authenticate a OAuth2 client which uses clientId and clientSecret in the request body (client_id, client_secret)
|
|
|
|
|
passport.use(new ClientPasswordStrategy(function (clientId, clientSecret, callback) {
|
|
|
|
|
clients.get(clientId, function(error, client) {
|
|
|
|
|
if (error && error.reason === ClientsError.NOT_FOUND) return callback(null, false);
|
|
|
|
|
if (error) { return callback(error); }
|
|
|
|
|
if (client.clientSecret !== clientSecret) { return callback(null, false); }
|
|
|
|
|
callback(null, client);
|
|
|
|
|
});
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// used for "Authorization: Bearer token" or access_token query param authentication
|
2018-06-27 23:17:04 -07:00
|
|
|
passport.use(new BearerStrategy(function (token, callback) {
|
|
|
|
|
accesscontrol.validateToken(token, callback);
|
|
|
|
|
}));
|
2018-06-15 17:31:28 -07:00
|
|
|
|
|
|
|
|
callback(null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function uninitialize(callback) {
|
|
|
|
|
assert.strictEqual(typeof callback, 'function');
|
|
|
|
|
|
|
|
|
|
callback(null);
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-26 15:54:53 -07:00
|
|
|
// The scope middleware provides an auth middleware for routes.
|
|
|
|
|
//
|
|
|
|
|
// It is used for API routes, which are authenticated using accesstokens.
|
|
|
|
|
// Those accesstokens carry OAuth scopes and the middleware takes the required
|
|
|
|
|
// scope as an argument and will verify the accesstoken against it.
|
|
|
|
|
//
|
|
|
|
|
// See server.js:
|
|
|
|
|
// var profileScope = routes.oauth2.scope('profile');
|
|
|
|
|
//
|
2018-06-14 16:32:24 -07:00
|
|
|
function scope(requiredScope) {
|
|
|
|
|
assert.strictEqual(typeof requiredScope, 'string');
|
2018-04-26 15:54:53 -07:00
|
|
|
|
2018-06-14 16:32:24 -07:00
|
|
|
var requiredScopes = requiredScope.split(',');
|
2018-04-26 15:54:53 -07:00
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
passport.authenticate(['bearer'], { session: false }),
|
|
|
|
|
|
|
|
|
|
function (req, res, next) {
|
2018-06-17 15:25:41 -07:00
|
|
|
assert(req.authInfo && typeof req.authInfo === 'object');
|
|
|
|
|
|
2018-06-17 19:54:05 -07:00
|
|
|
var error = accesscontrol.hasScopes(req.authInfo.authorizedScopes, requiredScopes);
|
2018-04-27 21:47:11 -07:00
|
|
|
if (error) return next(new HttpError(403, error.message));
|
2018-04-26 15:54:53 -07:00
|
|
|
|
|
|
|
|
next();
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-14 16:32:24 -07:00
|
|
|
function websocketAuth(requiredScopes, req, res, next) {
|
|
|
|
|
assert(Array.isArray(requiredScopes));
|
2018-04-26 15:54:53 -07:00
|
|
|
|
|
|
|
|
if (typeof req.query.access_token !== 'string') return next(new HttpError(401, 'Unauthorized'));
|
|
|
|
|
|
2018-06-27 23:17:04 -07:00
|
|
|
accesscontrol.validateToken(req.query.access_token, function (error, user, info) {
|
2018-04-26 15:54:53 -07:00
|
|
|
if (error) return next(new HttpError(500, error.message));
|
|
|
|
|
if (!user) return next(new HttpError(401, 'Unauthorized'));
|
|
|
|
|
|
|
|
|
|
req.user = user;
|
|
|
|
|
|
2018-06-17 19:54:05 -07:00
|
|
|
var e = accesscontrol.hasScopes(info.authorizedScopes, requiredScopes);
|
2018-06-15 20:51:26 -07:00
|
|
|
if (e) return next(new HttpError(403, e.message));
|
2018-04-26 15:54:53 -07:00
|
|
|
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
}
|