New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

feathers-authentication

Package Overview
Dependencies
Maintainers
3
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

feathers-authentication - npm Package Compare versions

Comparing version 0.8.0-alpha-4 to 0.8.0-beta-1

lib/hooks/associate-authenticated.js

9

example/app.js

@@ -9,3 +9,3 @@ var feathers = require('feathers');

var authentication = require('../lib/index');
var token = authentication.TokenService;
var token = authentication.TokenService.Service;
var local = authentication.LocalService;

@@ -50,3 +50,6 @@

messageService.before({
all: [authentication.hooks.restrictToAuthenticated()]
all: [
authentication.hooks.isAuthenticated(),
authentication.hooks.hasPermissions('messages')
]
});

@@ -66,3 +69,3 @@

password: 'admin',
roles: ['admin']
permissions: ['*']
};

@@ -69,0 +72,0 @@

@@ -19,2 +19,4 @@ 'use strict';

});
return Promise.resolve(hook);
};

@@ -30,3 +32,5 @@ }

}
return Promise.resolve(hook);
};
}

@@ -16,6 +16,8 @@ 'use strict';

if (!app.get('storage')) {
app.set('storage', (0, _utils.getStorage)(config.storage));
var storage = (0, _utils.getStorage)(config.storage);
app.set('storage', storage);
}
(0, _utils.getJWT)(config.tokenKey, config.cookie, this.get('storage')).then(function (token) {
// load any pre-existing JWT from localStorage
(0, _utils.getJWT)(config.tokenKey, config.cookie, app.get('storage')).then(function (token) {
app.set('token', token);

@@ -28,3 +30,2 @@ app.get('storage').setItem(config.tokenKey, token);

var storage = this.get('storage');
var getOptions = Promise.resolve(options);

@@ -34,3 +35,3 @@

if (!options.type) {
getOptions = (0, _utils.getJWT)(config.tokenKey, config.cookie, this.get('storage')).then(function (token) {
getOptions = (0, _utils.getJWT)(config.tokenKey, config.cookie, app.get('storage')).then(function (token) {
if (!token) {

@@ -48,3 +49,3 @@ return Promise.reject(new _feathersErrors2.default.NotAuthenticated('Could not find stored JWT and no authentication type was given'));

return Promise.resolve(storage.setItem(config.tokenKey, response.token)).then(function () {
return Promise.resolve(app.get('storage').setItem(config.tokenKey, response.token)).then(function () {
return response;

@@ -105,3 +106,3 @@ });

service.before(hooks.populateParams(config));
service.before(hooks.populateParams());
});

@@ -108,0 +109,0 @@

@@ -6,4 +6,17 @@ 'use strict';

});
exports.default = hashPassword;
exports.default = function () {
var _bcryptjs = require('bcryptjs');
var _bcryptjs2 = _interopRequireDefault(_bcryptjs);
var _debug = require('debug');
var _debug2 = _interopRequireDefault(_debug);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var debug = (0, _debug2.default)('feathers-authentication:hooks:hash-password');
function hashPassword() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

@@ -13,76 +26,79 @@

if (hook.type !== 'before') {
throw new Error('The \'hashPassword\' hook should only be used as a \'before\' hook.');
return Promise.reject(new Error('The \'hashPassword\' hook should only be used as a \'before\' hook.'));
}
options = Object.assign({}, defaults, hook.app.get('auth'), options);
var app = hook.app;
var authOptions = app.get('auth');
var crypto = options.bcrypt || _bcryptjs2.default;
options = Object.assign({}, authOptions.user, options);
if (hook.data === undefined) {
return hook;
}
debug('Running hashPassword hook with options:', options);
var password = void 0;
if (Array.isArray(hook.data)) {
// make sure we actually have password fields
var dataToCheck = [].concat(hook.data);
dataToCheck.filter(function (item) {
return item.hasOwnProperty(options.passwordField);
});
if (dataToCheck.length > 0) {
// set it to the array so we can iterate later on it
password = hook.data;
}
} else {
password = hook.data[options.passwordField];
}
if (password === undefined) {
// If it was an internal call then move along otherwise
// throw an error that password is required.
if (!hook.params.provider) {
return hook;
}
throw new _feathersErrors2.default.BadRequest('\'' + options.passwordField + '\' field is missing.');
}
return new Promise(function (resolve, reject) {
var hash = function hash(item, password, salt) {
crypto.hash(password, salt, function (error, hash) {
var field = options.passwordField;
var hashPw = options.hash || function (password) {
return new Promise(function (resolve, reject) {
_bcryptjs2.default.genSalt(10, function (error, salt) {
if (error) {
return reject(error);
}
item[options.passwordField] = hash;
resolve(hook);
});
};
crypto.genSalt(10, function (error, salt) {
if (Array.isArray(password)) {
password.map(function (item) {
if (!item.hasOwnProperty(options.passwordField)) {
return false;
_bcryptjs2.default.hash(password, salt, function (error, hashedPassword) {
if (error) {
return reject(error);
}
hash(item, item[options.passwordField], salt);
resolve(hashedPassword);
});
} else {
hash(hook.data, password, salt);
}
});
});
});
};
};
};
var _feathersErrors = require('feathers-errors');
if (typeof hashPw !== 'function') {
return Promise.reject(new Error('\'hash\' must be a function that takes a password and returns Promise that resolves with a hashed password.'));
}
var _feathersErrors2 = _interopRequireDefault(_feathersErrors);
if (hook.data === undefined) {
debug('hook.data is undefined. Skipping hashPassword hook.');
return Promise.resolve(hook);
}
var _bcryptjs = require('bcryptjs');
var data = void 0;
var _bcryptjs2 = _interopRequireDefault(_bcryptjs);
// make sure we actually have password fields
if (Array.isArray(hook.data)) {
data = hook.data.filter(function (item) {
return item.hasOwnProperty(field);
});
} else if (hook.data[field]) {
data = hook.data;
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// If the data doesn't have a password field
// then don't attempt to hash it.
if (data === undefined || Array.isArray(data) && !data.length) {
debug('\'' + field + '\' field is missing. Skipping hashPassword hook.');
return Promise.resolve(hook);
}
var defaults = { passwordField: 'password' };
if (Array.isArray(data)) {
debug('Hashing passwords.');
return Promise.all(data.map(function (item) {
return hashPw(item[field]).then(function (hashedPassword) {
item[field] = hashedPassword;
return item;
});
})).then(function (results) {
hook.data = results;
return Promise.resolve(hook);
});
}
debug('Hashing password.');
return hashPw(data[field]).then(function (hashedPassword) {
hook.data[field] = hashedPassword;
return Promise.resolve(hook);
});
};
}
module.exports = exports['default'];

@@ -7,5 +7,5 @@ 'use strict';

var _associateCurrentUser = require('./associate-current-user');
var _associateAuthenticated = require('./associate-authenticated');
var _associateCurrentUser2 = _interopRequireDefault(_associateCurrentUser);
var _associateAuthenticated2 = _interopRequireDefault(_associateAuthenticated);

@@ -16,52 +16,37 @@ var _hashPassword = require('./hash-password');

var _populateUser = require('./populate-user');
var _loadAuthenticated = require('./load-authenticated');
var _populateUser2 = _interopRequireDefault(_populateUser);
var _loadAuthenticated2 = _interopRequireDefault(_loadAuthenticated);
var _queryWithCurrentUser = require('./query-with-current-user');
var _queryWithAuthenticated = require('./query-with-authenticated');
var _queryWithCurrentUser2 = _interopRequireDefault(_queryWithCurrentUser);
var _queryWithAuthenticated2 = _interopRequireDefault(_queryWithAuthenticated);
var _restrictToAuthenticated = require('./restrict-to-authenticated');
var _isAuthenticated = require('./is-authenticated');
var _restrictToAuthenticated2 = _interopRequireDefault(_restrictToAuthenticated);
var _isAuthenticated2 = _interopRequireDefault(_isAuthenticated);
var _restrictToOwner = require('./restrict-to-owner');
var _isPermitted = require('./is-permitted');
var _restrictToOwner2 = _interopRequireDefault(_restrictToOwner);
var _isPermitted2 = _interopRequireDefault(_isPermitted);
var _restrictToRoles = require('./restrict-to-roles');
var _parseToken = require('./parse-token');
var _restrictToRoles2 = _interopRequireDefault(_restrictToRoles);
var _parseToken2 = _interopRequireDefault(_parseToken);
var _verifyToken = require('./verify-token');
var _checkPermissions = require('./check-permissions');
var _verifyToken2 = _interopRequireDefault(_verifyToken);
var _checkPermissions2 = _interopRequireDefault(_checkPermissions);
var _verifyOrRestrict = require('./verify-or-restrict');
var _verifyOrRestrict2 = _interopRequireDefault(_verifyOrRestrict);
var _populateOrRestrict = require('./populate-or-restrict');
var _populateOrRestrict2 = _interopRequireDefault(_populateOrRestrict);
var _hasRoleOrRestrict = require('./has-role-or-restrict');
var _hasRoleOrRestrict2 = _interopRequireDefault(_hasRoleOrRestrict);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var hooks = {
associateCurrentUser: _associateCurrentUser2.default,
associateAuthenticated: _associateAuthenticated2.default,
hashPassword: _hashPassword2.default,
populateUser: _populateUser2.default,
queryWithCurrentUser: _queryWithCurrentUser2.default,
restrictToAuthenticated: _restrictToAuthenticated2.default,
restrictToOwner: _restrictToOwner2.default,
restrictToRoles: _restrictToRoles2.default,
verifyToken: _verifyToken2.default,
verifyOrRestrict: _verifyOrRestrict2.default,
populateOrRestrict: _populateOrRestrict2.default,
hasRoleOrRestrict: _hasRoleOrRestrict2.default
loadAuthenticated: _loadAuthenticated2.default,
queryWithAuthenticated: _queryWithAuthenticated2.default,
isAuthenticated: _isAuthenticated2.default,
isPermitted: _isPermitted2.default,
parseToken: _parseToken2.default,
checkPermissions: _checkPermissions2.default
};

@@ -68,0 +53,0 @@

@@ -12,6 +12,2 @@ 'use strict';

var _cookieParser = require('cookie-parser');
var _cookieParser2 = _interopRequireDefault(_cookieParser);
var _passport = require('passport');

@@ -51,31 +47,20 @@

// Exposed modules
// Options that apply to any provider
var THIRTY_SECONDS = 30000; // in milliseconds
var ONE_DAY = 60 * 60 * 24 * 1000; // in milliseconds
// Options that apply to any provider
// Exposed modules
var defaults = {
header: 'Authorization',
setupMiddleware: true, // optional - to setup middleware yourself set to false.
cookies: {
enable: false, // Set to true to enable all cookies
// Used for redirects where JS can pick up the JWT and
// store it in localStorage (ie. redirect or OAuth)
'feathers-jwt': { // set to false to disable this cookie
httpOnly: false,
maxAge: THIRTY_SECONDS,
secure: process.env.NODE_ENV === 'production'
},
// Used for server side rendering
'feathers-session': { // set to false to disable this cookie
httpOnly: true,
maxAge: ONE_DAY,
secure: process.env.NODE_ENV === 'production'
}
cookie: { // Used for redirects, server side rendering and OAuth
enabled: false, // Set to true to enable all cookies
name: 'feathers-jwt',
httpOnly: true,
maxAge: '1d',
secure: true
},
token: {
name: 'token', // optional
endpoint: '/auth/token', // optional
service: '/auth/token', // optional string or Service
subject: 'auth', // optional
issuer: 'feathers', // optional

@@ -87,16 +72,26 @@ algorithm: 'HS256', // optional

failureRedirect: null, // optional - no default. If set the default success handler will redirect to location
successHandler: null },
// optional - a middleware to handle things once authentication succeeds
successHandler: null // optional - a middleware to handle things once authentication succeeds
},
local: {
endpoint: '/auth/local', // optional
service: '/auth/local', // optional string or Service
successRedirect: null, // optional - no default. If set the default success handler will redirect to location
failureRedirect: null, // optional - no default. If set the default success handler will redirect to location
successHandler: null },
// optional - a middleware to handle things once authentication succeeds
successHandler: null, // optional - a middleware to handle things once authentication succeeds
passReqToCallback: true, // optional - whether request should be passed to callback
session: false // optional - whether we should use a session
},
user: {
endpoint: '/users', // optional
service: '/users', // optional string or Service
idField: '_id', // optional
usernameField: 'email', // optional
passwordField: 'password', // optional
service: null // optional - no default. an actual service (can be client side service)
passwordField: 'password' // optional
},
oauth2: {
// service: '/auth/facebook', // required - the service path or initialized service
passReqToCallback: true, // optional - whether request should be passed to callback
// callbackUrl: 'callback', // optional - the callback url, by default this gets set to /<service>/callback
permissions: {
state: true,
session: false
}
}

@@ -112,10 +107,4 @@ };

// If cookies are enabled then load our defaults and
// any passed in options
if (config.cookies && config.cookies.enable) {
config.cookies = Object.assign({}, defaults.cookies, config.cookies);
}
// Merge and flatten options
var authOptions = (0, _lodash2.default)(defaults, app.get('auth'), config);
var authOptions = (0, _lodash2.default)({}, defaults, app.get('auth'), config);

@@ -129,2 +118,8 @@ // NOTE (EK): Currently we require token based auth so

// Make sure cookies don't have to be sent over HTTPS
// when in development or test mode.
if (app.env === 'development' || app.env === 'test') {
authOptions.cookie.secure = false;
}
// Set the options on the app

@@ -137,5 +132,5 @@ app.set('auth', authOptions);

// Be able to parse cookies it that is enabled
if (authOptions.cookies.enable) {
app.use((0, _cookieParser2.default)());
// Be able to parse cookies it they are enabled
if (authOptions.cookie.enable) {
app.use(mw.cookieParser());
}

@@ -147,4 +142,4 @@

app.use(mw.tokenParser(authOptions));
// Verify and decode a JWT if it is present
app.use(mw.decodeToken(authOptions));
// Verify and decode a JWT if it is present
app.use(mw.verifyToken(authOptions));
// Make the Passport user available for REST services.

@@ -151,0 +146,0 @@ app.use(mw.populateUser(authOptions));

@@ -7,38 +7,50 @@ 'use strict';

var _cookieParser = require('cookie-parser');
var _cookieParser2 = _interopRequireDefault(_cookieParser);
var _sockets = require('./sockets');
var _exposeRequestResponse = require('./express/expose-request-response');
var _exposeRequestResponse = require('./rest/expose-request-response');
var _exposeRequestResponse2 = _interopRequireDefault(_exposeRequestResponse);
var _tokenParser = require('./express/token-parser');
var _tokenParser = require('./rest/token-parser');
var _tokenParser2 = _interopRequireDefault(_tokenParser);
var _decodeToken = require('./express/decode-token');
var _verifyToken = require('./rest/verify-token');
var _decodeToken2 = _interopRequireDefault(_decodeToken);
var _verifyToken2 = _interopRequireDefault(_verifyToken);
var _populateUser = require('./express/populate-user');
var _populateUser = require('./rest/populate-user');
var _populateUser2 = _interopRequireDefault(_populateUser);
var _setCookie = require('./express/set-cookie');
var _setCookie = require('./rest/set-cookie');
var _setCookie2 = _interopRequireDefault(_setCookie);
var _loginSuccess = require('./express/login-success');
var _successRedirect = require('./rest/success-redirect');
var _loginSuccess2 = _interopRequireDefault(_loginSuccess);
var _successRedirect2 = _interopRequireDefault(_successRedirect);
var _notAuthenticated = require('./express/not-authenticated');
var _notAuthenticated = require('./rest/not-authenticated');
var _notAuthenticated2 = _interopRequireDefault(_notAuthenticated);
var _restrictToAuthenticated = require('./express/restrict-to-authenticated');
var _isAuthenticated = require('./rest/is-authenticated');
var _restrictToAuthenticated2 = _interopRequireDefault(_restrictToAuthenticated);
var _isAuthenticated2 = _interopRequireDefault(_isAuthenticated);
var _logout = require('./express/logout');
var _isPermitted = require('./rest/is-permitted');
var _isPermitted2 = _interopRequireDefault(_isPermitted);
var _checkPermissions = require('./rest/check-permissions');
var _checkPermissions2 = _interopRequireDefault(_checkPermissions);
var _logout = require('./rest/logout');
var _logout2 = _interopRequireDefault(_logout);

@@ -48,11 +60,15 @@

// external express middleware dependency
exports.default = {
exposeRequestResponse: _exposeRequestResponse2.default,
tokenParser: _tokenParser2.default,
decodeToken: _decodeToken2.default,
cookieParser: _cookieParser2.default,
verifyToken: _verifyToken2.default,
populateUser: _populateUser2.default,
setCookie: _setCookie2.default,
successfulLogin: _loginSuccess2.default,
successRedirect: _successRedirect2.default,
notAuthenticated: _notAuthenticated2.default,
restrictToAuthenticated: _restrictToAuthenticated2.default,
isAuthenticated: _isAuthenticated2.default,
isPermitted: _isPermitted2.default,
checkPermissions: _checkPermissions2.default,
logout: _logout2.default,

@@ -59,0 +75,0 @@ setupSocketIOAuthentication: _sockets.setupSocketIOAuthentication,

@@ -19,3 +19,3 @@ 'use strict';

var debug = (0, _debug2.default)('feathers-authentication:middleware');
var debug = (0, _debug2.default)('feathers-authentication:middleware:socket');

@@ -44,2 +44,3 @@ function setupSocketHandler(feathersParams, provider, emit, disconnect, app, options) {

feathersParams(socket).user = response.user;
feathersParams(socket).authenticated = true;
socket[emit]('authenticated', response);

@@ -59,3 +60,3 @@ app[emit]('login', response);

// convention and pass it as params using sockets.
app.service(options.token.endpoint).create({}, params).then(successHandler).catch(errorHandler);
app.service(options.token.service).create({}, params).then(successHandler).catch(errorHandler);
}

@@ -71,3 +72,3 @@ // Authenticate the user using local auth strategy

app.service(options.local.endpoint).create(data, _params).then(successHandler).catch(errorHandler);
app.service(options.local.service).create(data, _params).then(successHandler).catch(errorHandler);
}

@@ -84,5 +85,7 @@ });

app[emit]('logout', { token: token, user: user });
app.emit('logout', { token: token, user: user });
delete params.token;
delete params.user;
delete params.permitted;
delete params.authenticated;
});

@@ -104,5 +107,7 @@

app[emit]('logout', { token: token, user: user });
app.emit('logout', { token: token, user: user });
delete params.token;
delete params.user;
delete params.permitted;
delete params.authenticated;
} catch (error) {

@@ -109,0 +114,0 @@ debug('There was an error logging out', error);

@@ -6,38 +6,8 @@ 'use strict';

});
exports.Service = undefined;
exports.LocalService = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
exports.default = function (options) {
return function () {
var app = this;
var authConfig = Object.assign({}, app.get('auth'), options);
var userEndpoint = authConfig.user.endpoint;
exports.default = init;
if (authConfig.token === undefined) {
throw new Error('The TokenService needs to be configured before OAuth');
}
var tokenEndpoint = authConfig.token.endpoint;
// TODO (EK): Support pulling in a user and token service directly
// in order to talk to remote services.
var _authConfig$user = authConfig.user;
var idField = _authConfig$user.idField;
var passwordField = _authConfig$user.passwordField;
var usernameField = _authConfig$user.usernameField;
options = (0, _lodash2.default)(defaults, authConfig.local, options, { idField: idField, passwordField: passwordField, usernameField: usernameField, userEndpoint: userEndpoint, tokenEndpoint: tokenEndpoint });
var successHandler = options.successHandler || _middleware.successfulLogin;
debug('configuring local authentication service with options', options);
// Initialize our service with any options it requires
app.use(options.endpoint, new Service(options), (0, _middleware.setCookie)(authConfig), successHandler(options));
};
};
var _debug = require('debug');

@@ -73,21 +43,9 @@

var debug = (0, _debug2.default)('feathers-authentication:local');
var defaults = {
endpoint: '/auth/local',
tokenEndpoint: '/auth/local',
userEndpoint: '/users',
idField: '_id',
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true,
session: false
};
var debug = (0, _debug2.default)('feathers-authentication:services:local');
// successHandler: null //optional - a middleware to call when successfully authenticated
var Service = exports.Service = function () {
function Service() {
var LocalService = exports.LocalService = function () {
function LocalService() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
_classCallCheck(this, Service);
_classCallCheck(this, LocalService);

@@ -97,58 +55,63 @@ this.options = options;

_createClass(Service, [{
key: 'buildCredentials',
value: function buildCredentials(req, username) {
var usernameField = this.options.usernameField;
return new Promise(function (resolve) {
var params = {
query: _defineProperty({}, usernameField, username)
};
resolve(params);
});
}
}, {
key: 'checkCredentials',
value: function checkCredentials(req, username, password, done) {
var _this = this;
_createClass(LocalService, [{
key: 'comparePassword',
value: function comparePassword(user, password) {
var field = this.options.user.passwordField;
var hash = user[field];
debug('Checking credentials');
if (!hash) {
return Promise.reject(new Error('User record in the database is missing a \'' + field + '\''));
}
this.app.service(this.options.endpoint).buildCredentials(req, username, password)
// Look up the user
.then(function (params) {
return _this.app.service(_this.options.userEndpoint).find(params);
}).then(function (users) {
// Paginated services return the array of results in the data attribute.
var user = users[0] || users.data && users.data[0];
debug('Verifying password');
// Handle bad username.
if (!user) {
return done(null, false);
}
debug('User found');
return user;
}).then(function (user) {
var crypto = _this.options.bcrypt || _bcryptjs2.default;
// Check password
var hash = user[_this.options.passwordField];
if (!hash) {
return done(new Error('User record in the database is missing a \'' + _this.options.passwordField + '\''));
}
debug('Verifying password');
crypto.compare(password, hash, function (error, result) {
return new Promise(function (resolve, reject) {
_bcryptjs2.default.compare(password, hash, function (error, result) {
// Handle 500 server error.
if (error) {
return done(error);
return reject(error);
}
if (!result) {
return reject(false);
}
debug('Password correct');
return done(null, result ? user : false);
return resolve(user);
});
}).catch(done);
});
}
}, {
key: 'getFirstUser',
value: function getFirstUser(users) {
// Paginated services return the array of results in the data attribute.
var user = users[0] || users.data && users.data[0];
// Handle bad username.
if (!user) {
return Promise.reject(false);
}
debug('User found');
return Promise.resolve(user);
}
}, {
key: 'verify',
value: function verify(req, username, password, done) {
var _this = this;
debug('Checking credentials');
var usernameField = this.options.user.usernameField;
var query = _defineProperty({}, usernameField, username);
// Look up the user
this._userService.find({ query: query }).then(this.getFirstUser).then(function (user) {
return _this.comparePassword(user, password);
}).then(function (user) {
return done(null, user);
}).catch(function (error) {
return error ? done(error) : done(null, error);
});
}
// POST /auth/local

@@ -159,8 +122,9 @@

value: function create(data, params) {
var _this2 = this;
var options = this.options;
var app = this.app;
// Validate username and password, then generate a JWT and return it
return new Promise(function (resolve, reject) {
var middleware = _passport2.default.authenticate('local', { session: options.session }, function (error, user) {
var middleware = _passport2.default.authenticate('local', { session: options.local.session }, function (error, user) {
if (error) {

@@ -177,6 +141,6 @@ return reject(error);

var tokenPayload = _defineProperty({}, options.idField, user[options.idField]);
var tokenPayload = _defineProperty({}, options.user.idField, user[options.user.idField]);
// Get a new JWT and the associated user from the Auth token service and send it back to the client.
return app.service(options.tokenEndpoint).create(tokenPayload, { user: user }).then(resolve).catch(reject);
return _this2._tokenService.create(tokenPayload, { user: user }).then(resolve).catch(reject);
});

@@ -194,5 +158,17 @@

var tokenService = this.options.token.service;
var userService = this.options.user.service;
this._tokenService = typeof tokenService === 'string' ? app.service(tokenService) : tokenService;
this._userService = typeof userService === 'string' ? app.service(userService) : userService;
var passportOptions = {
usernameField: this.options.user.usernameField,
passwordField: this.options.user.passwordField,
passReqToCallback: this.options.local.passReqToCallback
};
// Register our local auth strategy and get it to use the passport callback function
debug('registering passport-local strategy');
_passport2.default.use(new _passportLocal.Strategy(this.options, this.checkCredentials.bind(this)));
_passport2.default.use(new _passportLocal.Strategy(passportOptions, this.verify.bind(this)));

@@ -208,3 +184,34 @@ // prevent regular service events from being dispatched

return Service;
}();
return LocalService;
}();
function init(options) {
return function () {
var app = this;
options = (0, _lodash2.default)({ user: {}, local: {} }, app.get('auth'), options);
if (options.token === undefined) {
throw new Error('The TokenService needs to be configured before the Local auth service.');
}
var Service = options.local.Service || LocalService;
var successHandler = options.local.successHandler || _middleware.successRedirect;
// TODO (EK): Add error checking for required fields
// - token.service
// - local.service
// - user.service
// - user.idField
// - user.passwordField
// - user.usernameField
//
debug('configuring local authentication service with options', options);
// TODO (EK): Only enable set cookie middleware if cookies are enabled.
// Initialize our service with any options it requires
app.use(options.local.service, new Service(options), (0, _middleware.setCookie)(options), successHandler(options));
};
}
init.Service = LocalService;

@@ -6,56 +6,8 @@ 'use strict';

});
exports.Service = undefined;
exports.OAuth2Service = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
exports.default = function (options) {
if (!options.provider) {
throw new Error('You need to pass a `provider` for your authentication provider');
}
exports.default = init;
if (!options.endpoint) {
throw new Error('You need to provide an \'endpoint\' for your ' + options.provider + ' provider');
}
if (!options.strategy) {
throw new Error('You need to provide a Passport \'strategy\' for your ' + options.provider + ' provider');
}
if (!options.clientID) {
throw new Error('You need to provide a \'clientID\' for your ' + options.provider + ' provider');
}
if (!options.clientSecret) {
throw new Error('You need to provide a \'clientSecret\' for your ' + options.provider + ' provider');
}
return function () {
var app = this;
var authConfig = Object.assign({}, app.get('auth'), options);
var userEndpoint = authConfig.user.endpoint;
// TODO (EK): Support pulling in a user and token service directly
// in order to talk to remote services.
if (authConfig.token === undefined) {
throw new Error('The TokenService needs to be configured before OAuth');
}
var tokenEndpoint = authConfig.token.endpoint;
options = (0, _lodash2.default)(defaults, authConfig[options.provider], options, { userEndpoint: userEndpoint, tokenEndpoint: tokenEndpoint });
var successHandler = options.successHandler || _middleware.successfulLogin;
options.permissions.state = options.permissions.state === undefined ? true : options.permissions.state;
options.permissions.session = options.permissions.session === undefined ? false : options.permissions.session;
options.callbackURL = options.callbackURL || options.endpoint + '/' + options.callbackSuffix;
debug('configuring ' + options.provider + ' OAuth2 service with options', options);
// Initialize our service with any options it requires
app.use(options.endpoint, new Service(options), (0, _middleware.setCookie)(authConfig), successHandler(options));
};
};
var _debug = require('debug');

@@ -85,19 +37,9 @@

var debug = (0, _debug2.default)('feathers-authentication:oauth2');
var debug = (0, _debug2.default)('feathers-authentication:services:oauth2');
// Provider specific config
var defaults = {
passReqToCallback: true,
callbackSuffix: 'callback',
permissions: {
state: true,
session: false
}
};
var Service = exports.Service = function () {
function Service() {
var OAuth2Service = exports.OAuth2Service = function () {
function OAuth2Service() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
_classCallCheck(this, Service);
_classCallCheck(this, OAuth2Service);

@@ -107,18 +49,61 @@ this.options = options;

_createClass(Service, [{
key: 'oauthCallback',
value: function oauthCallback(req, accessToken, refreshToken, profile, done) {
var app = this.app;
_createClass(OAuth2Service, [{
key: 'getFirstUser',
value: function getFirstUser(users) {
// Paginated services return the array of results in the data attribute.
var user = users[0] || users.data && users.data[0];
// Handle bad username.
if (!user) {
return Promise.resolve(false);
}
// Handle updating mongoose models
if (typeof user.toObject === 'function') {
user = user.toObject();
}
// Handle updating Sequelize models
else if (typeof user.toJSON === 'function') {
user = user.toJSON();
}
debug('User found');
return Promise.resolve(user);
}
}, {
key: 'updateUser',
value: function updateUser(user, data) {
var idField = this.options.user.idField;
var id = user[idField];
debug('Updating user: ' + id);
// Merge existing user data with new profile data
data = (0, _lodash2.default)({}, user, data);
// TODO (EK): Handle paginated services?
return this._userService.patch(id, data, { oauth: true });
}
}, {
key: 'createUser',
value: function createUser(data) {
var provider = this.options.provider;
var id = data[provider + 'Id'];
debug('Creating new user with ' + provider + 'Id: ' + id);
return this._userService.create(data, { oauth: true });
}
}, {
key: 'verify',
value: function verify(req, accessToken, refreshToken, profile, done) {
var _this = this;
debug('Checking credentials');
var options = this.options;
var params = {
query: _defineProperty({}, options.provider + 'Id', profile.id)
};
var query = _defineProperty({}, options.provider + 'Id', profile.id);
// Find or create the user since they could have signed up via facebook.
app.service(options.userEndpoint).find(params).then(function (users) {
this._userService.find({ query: query }).then(this.getFirstUser).then(function (user) {
var _Object$assign;
// Paginated services return the array of results in the data attribute.
var user = users[0] || users.data && users.data[0];
// TODO (EK): This is where we should look at req.user and see if we

@@ -131,28 +116,13 @@ // can consolidate profiles. We might want to give the developer a hook

// If user found update and return them
if (user) {
var id = user[options.idField];
// Merge existing user data with new profile data
// TODO (EK): If stored profile data has been altered this might
// just overwrite the whole `<provider>` field when it should do a
// deep merge.
data = Object.assign({}, user, data);
debug('Updating user: ' + id);
return app.service(options.userEndpoint).patch(id, data).then(function (updatedUser) {
return done(null, updatedUser);
}).catch(done);
return _this.updateUser(user, data);
}
debug('Creating new user with ' + options.provider + 'Id: ' + profile.id);
// No user found so we need to create one.
return app.service(options.userEndpoint).create(data).then(function (user) {
debug('Created new user: ' + user[options.idField]);
return done(null, user);
}).catch(done);
}).catch(done);
// Otherwise update the existing user
return _this.createUser(data);
}).then(function (user) {
return done(null, user);
}).catch(function (error) {
return error ? done(error) : done(null, error);
});
}

@@ -174,7 +144,5 @@

value: function get(id, params) {
var options = this.options;
var app = this.app;
var options = Object.assign({}, this.options, params);
// TODO (EK): Make this configurable
if (id !== options.callbackSuffix) {
if (options.service + '/' + id !== options.callbackUrl) {
return Promise.reject(new _feathersErrors2.default.NotFound());

@@ -195,6 +163,6 @@ }

var tokenPayload = _defineProperty({}, options.idField, user[options.idField]);
var tokenPayload = _defineProperty({}, options.user.idField, user[options.user.idField]);
// Get a new JWT and the associated user from the Auth token service and send it back to the client.
return app.service(options.tokenEndpoint).create(tokenPayload, { user: user }).then(resolve).catch(reject);
return this._tokenService.create(tokenPayload, { user: user }).then(resolve).catch(reject);
});

@@ -213,3 +181,2 @@

var options = this.options;
var app = this.app;

@@ -232,6 +199,6 @@ if (!options.tokenStrategy) {

var tokenPayload = _defineProperty({}, options.idField, user[options.idField]);
var tokenPayload = _defineProperty({}, options.user.idField, user[options.user.idField]);
// Get a new JWT and the associated user from the Auth token service and send it back to the client.
return app.service(options.tokenEndpoint).create(tokenPayload, { user: user }).then(resolve).catch(reject);
return this._tokenService.create(tokenPayload, { user: user }).then(resolve).catch(reject);
});

@@ -249,2 +216,8 @@

var tokenService = this.options.token.service;
var userService = this.options.user.service;
this._tokenService = typeof tokenService === 'string' ? app.service(tokenService) : tokenService;
this._userService = typeof userService === 'string' ? app.service(userService) : userService;
// Register our Passport auth strategy and get it to use our passport callback function

@@ -255,7 +228,7 @@ var Strategy = this.options.strategy;

debug('registering passport-' + this.options.provider + ' OAuth2 strategy');
_passport2.default.use(new Strategy(this.options, this.oauthCallback.bind(this)));
_passport2.default.use(new Strategy(this.options, this.verify.bind(this)));
if (TokenStrategy) {
debug('registering passport-' + this.options.provider + '-token OAuth2 strategy');
_passport2.default.use(new TokenStrategy(this.options, this.oauthCallback.bind(this)));
_passport2.default.use(new TokenStrategy(this.options, this.verify.bind(this)));
}

@@ -272,3 +245,47 @@

return Service;
}();
return OAuth2Service;
}();
function init(options) {
if (!options.provider) {
throw new Error('You need to pass a `provider` for your authentication provider');
}
if (!options.service) {
throw new Error('You need to provide an \'service\' for your ' + options.provider + ' provider. This can either be a string or an initialized service.');
}
if (!options.strategy) {
throw new Error('You need to provide a Passport \'strategy\' for your ' + options.provider + ' provider');
}
if (!options.clientID) {
throw new Error('You need to provide a \'clientID\' for your ' + options.provider + ' provider');
}
if (!options.clientSecret) {
throw new Error('You need to provide a \'clientSecret\' for your ' + options.provider + ' provider');
}
return function () {
var app = this;
options = (0, _lodash2.default)({ user: {} }, app.get('auth'), app.get('auth').oauth2, options);
options.callbackURL = options.callbackURL || options.service + '/callback';
if (options.token === undefined) {
throw new Error('The TokenService needs to be configured before the OAuth2 service.');
}
var Service = options.Service || OAuth2Service;
var successHandler = options.successHandler || _middleware.successRedirect;
debug('configuring ' + options.provider + ' OAuth2 service with options', options);
// TODO (EK): throw warning if cookies are not enabled. They are required for OAuth
// Initialize our service with any options it requires
app.use(options.service, new Service(options), (0, _middleware.setCookie)(options), successHandler(options));
};
}
init.Service = OAuth2Service;

@@ -6,24 +6,8 @@ 'use strict';

});
exports.Service = undefined;
exports.TokenService = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
exports.default = function (options) {
return function () {
var app = this;
var authConfig = Object.assign({}, app.get('auth'), options);
var passwordField = authConfig.user.passwordField;
exports.default = init;
options = (0, _lodash2.default)(defaults, authConfig.token, options, { passwordField: passwordField });
var successHandler = options.successHandler || _middleware.successfulLogin;
debug('configuring token authentication service with options', options);
// Initialize our service with any options it requires
app.use(options.endpoint, new Service(options), (0, _middleware.setCookie)(authConfig), successHandler(options));
};
};
var _debug = require('debug');

@@ -37,10 +21,6 @@

var _hooks = require('../hooks');
var _lodash = require('lodash.merge');
var _hooks2 = _interopRequireDefault(_hooks);
var _lodash2 = _interopRequireDefault(_lodash);
var _feathersHooks = require('feathers-hooks');
var _feathersHooks2 = _interopRequireDefault(_feathersHooks);
var _feathersErrors = require('feathers-errors');

@@ -52,6 +32,4 @@

var _lodash = require('lodash.merge');
var _hooks = require('../hooks');
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -61,16 +39,4 @@

var debug = (0, _debug2.default)('feathers-authentication:token');
var debug = (0, _debug2.default)('feathers-authentication:services:token');
// Provider specific config
var defaults = {
endpoint: '/auth/token',
idField: '_id',
passwordField: 'password',
issuer: 'feathers',
subject: 'auth',
algorithm: 'HS256',
expiresIn: '1d', // 1 day
payload: []
};
/**

@@ -85,4 +51,3 @@ * Verifies that a JWT token is valid. This is a private hook.

var secret = options.secret;
var secret = options.token.secret;
return function (hook) {

@@ -100,3 +65,3 @@ return new Promise(function (resolve, reject) {

_jsonwebtoken2.default.verify(token, secret, options, function (error, payload) {
_jsonwebtoken2.default.verify(token, secret, options.token, function (error, payload) {
if (error) {

@@ -117,7 +82,7 @@ // Return a 401 if the token has expired.

var Service = exports.Service = function () {
function Service() {
var TokenService = exports.TokenService = function () {
function TokenService() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
_classCallCheck(this, Service);
_classCallCheck(this, TokenService);

@@ -147,29 +112,26 @@ this.options = options;

// GET /auth/token/refresh
// get(id, params) {
// if (id !== 'refresh') {
// return Promise.reject(new errors.NotFound());
// }
// const options = this.options.token;
// const data = params;
// // Our before hook determined that we had a valid token or that this
// // was internally called so let's generate a new token with the user
// // id and return both the ID and the token.
// return new Promise(function(resolve){
// jwt.sign(data, options.secret, options, token => {
// return resolve( Object.assign(data, { token }) );
// });
// });
// }
_createClass(Service, [{
key: 'get',
value: function get(id, params) {
if (id !== 'refresh') {
return Promise.reject(new _feathersErrors2.default.NotFound());
}
// POST /auth/token
var options = this.options;
var data = params;
// Our before hook determined that we had a valid token or that this
// was internally called so let's generate a new token with the user
// id and return both the ID and the token.
return new Promise(function (resolve) {
_jsonwebtoken2.default.sign(data, options.secret, options, function (token) {
return resolve(Object.assign(data, { token: token }));
});
});
}
// POST /auth/token
}, {
_createClass(TokenService, [{
key: 'create',
value: function create(data, params) {
var _Object$assign = Object.assign({}, this.options, params.jwt);
var _Object$assign = Object.assign({}, this.options.token, params.tokenOptions);

@@ -184,6 +146,5 @@ var algorithm = _Object$assign.algorithm;

var noTimestamp = _Object$assign.noTimestamp;
var header = _Object$assign.header;
// const payload = this.options.payload;
var secret = this.options.secret;
var secret = this.options.token.secret;
var options = {

@@ -194,4 +155,3 @@ algorithm: algorithm,

jwtid: jwtid,
noTimestamp: noTimestamp,
header: header
noTimestamp: noTimestamp
};

@@ -209,11 +169,2 @@

// const data = {
// [this.options.idField]: payload[this.options.idField]
// };
// // Add any additional payload fields
// if (payload && Array.isArray(payload)) {
// payload.forEach(field => data[field] = payload[field]);
// }
// Our before hook determined that we had a valid token or that this

@@ -224,3 +175,3 @@ // was internally called so let's generate a new token with the user

debug('Creating JWT using options:', options);
debug('Payload:', data);
_jsonwebtoken2.default.sign(data, secret, options, function (error, token) {

@@ -244,2 +195,8 @@ if (error) {

this.before({
// all: [
// parseToken(),
// isAuthenticated(),
// checkPermissions({ namespace: 'users', on: 'user', field: 'permissions' }),
// isPermitted()
// ],
create: [_verifyToken(options)],

@@ -253,12 +210,9 @@ find: [_verifyToken(options)],

// generator.
// TODO (EK): Remove these and make the developer explicitly do
// this after we have the client check for a user and request if
// it didn't come in the response to authenticate.
this.after({
create: [_hooks2.default.populateUser(), _feathersHooks2.default.remove(options.passwordField, function () {
return true;
})],
find: [_hooks2.default.populateUser(), _feathersHooks2.default.remove(options.passwordField, function () {
return true;
})],
get: [_hooks2.default.populateUser(), _feathersHooks2.default.remove(options.passwordField, function () {
return true;
})]
create: [(0, _hooks.loadAuthenticated)()],
find: [(0, _hooks.loadAuthenticated)()],
get: [(0, _hooks.loadAuthenticated)()]
});

@@ -275,3 +229,27 @@

return Service;
}();
return TokenService;
}();
function init(options) {
return function () {
var app = this;
options = (0, _lodash2.default)({ token: {}, user: {} }, app.get('auth'), options);
var successHandler = options.token.successHandler || _middleware.successRedirect;
debug('configuring token authentication service with options', options);
// TODO (EK): Add error checking for required fields
// - token.service
// - local.service
// - user.service
// - user.idField
// - user.passwordField
// - user.usernameField
// TODO (EK): Only enable set cookie middleware if cookies are enabled.
// Initialize our service with any options it requires
app.use(options.token.service, new TokenService(options), (0, _middleware.setCookie)(options), successHandler(options));
};
}
init.Service = TokenService;
{
"name": "feathers-authentication",
"description": "Add Authentication to your FeathersJS app.",
"version": "0.8.0-alpha-4",
"version": "0.8.0-beta-1",
"homepage": "https://github.com/feathersjs/feathers-authentication",

@@ -52,8 +52,9 @@ "main": "lib/",

"debug": "^2.2.0",
"feathers-errors": "^2.0.1",
"feathers-hooks": "^1.5.0",
"jsonwebtoken": "^7.1.6",
"lodash.isplainobject": "^4.0.4",
"lodash.merge": "^4.4.0",
"lodash.omit": "^4.3.0",
"feathers-errors": "^2.4.0",
"jsonwebtoken": "^7.1.9",
"lodash.intersection": "^4.4.0",
"lodash.isplainobject": "^4.0.6",
"lodash.merge": "^4.6.0",
"lodash.omit": "^4.5.0",
"ms": "^0.7.1",
"passport": "^0.3.0",

@@ -63,26 +64,26 @@ "passport-local": "^1.0.0"

"devDependencies": {
"babel-cli": "^6.1.18",
"babel-core": "^6.1.21",
"babel-cli": "^6.14.0",
"babel-core": "^6.14.0",
"babel-plugin-add-module-exports": "^0.2.0",
"babel-preset-es2015": "^6.1.18",
"body-parser": "^1.9.0",
"babel-preset-es2015": "^6.14.0",
"body-parser": "^1.15.2",
"chai": "^3.5.0",
"feathers": "2.0.1",
"feathers-hooks": "^1.4.0",
"feathers-memory": "^0.7.0",
"feathers-hooks": "^1.5.7",
"feathers-memory": "^0.7.5",
"feathers-primus": "^1.3.2",
"feathers-rest": "^1.2.2",
"feathers-rest": "^1.5.0",
"feathers-socketio": "^1.3.2",
"jshint": "^2.8.0",
"jshint": "^2.9.3",
"localstorage-memory": "^1.0.2",
"mocha": "^2.5.0",
"nsp": "^2.2.0",
"primus": "^5.0.1",
"mocha": "^3.0.2",
"nsp": "^2.6.1",
"primus": "^5.2.2",
"primus-emitter": "^3.1.1",
"request": "^2.69.0",
"sinon": "^1.17.3",
"request": "^2.75.0",
"sinon": "^1.17.6",
"sinon-chai": "^2.8.0",
"socket.io-client": "^1.1.0",
"ws": "^1.0.1"
"socket.io-client": "^1.4.8",
"ws": "^1.1.1"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc