feathers-authentication
Advanced tools
Comparing version 0.8.0-alpha-4 to 0.8.0-beta-1
@@ -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" | ||
} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
0
140071
12
2066
1
+ Addedlodash.intersection@^4.4.0
+ Addedms@^0.7.1
+ Addedlodash.intersection@4.4.0(transitive)
+ Addedms@0.7.3(transitive)
- Removedfeathers-hooks@^1.5.0
- Removedfeathers-commons@0.8.7(transitive)
- Removedfeathers-hooks@1.8.1(transitive)
- Removedfeathers-hooks-common@2.0.3(transitive)
- Removedtraverse@0.6.6(transitive)
- Removeduberproto@1.2.0(transitive)
Updatedfeathers-errors@^2.4.0
Updatedjsonwebtoken@^7.1.9
Updatedlodash.isplainobject@^4.0.6
Updatedlodash.merge@^4.6.0
Updatedlodash.omit@^4.5.0