feathers-authentication
Advanced tools
Comparing version 0.7.7 to 0.7.8
@@ -27,5 +27,5 @@ 'use strict'; | ||
if (hook.params.token) { | ||
hook.params.headers = Object.assign({}, _defineProperty({}, options.header || 'Authorization', hook.params.token), hook.params.headers); | ||
hook.params.headers = Object.assign({}, _defineProperty({}, options.header || 'authorization', hook.params.token), hook.params.headers); | ||
} | ||
}; | ||
} |
@@ -78,3 +78,3 @@ 'use strict'; | ||
// remove the token from localStorage | ||
return Promise.resolve(app.get('storage').setItem(config.tokenKey, '')).then(function () { | ||
return Promise.resolve(app.get('storage').removeItem(config.tokenKey)).then(function () { | ||
// If using sockets de-authenticate the socket | ||
@@ -81,0 +81,0 @@ if (app.io || app.primus) { |
@@ -115,4 +115,8 @@ 'use strict'; | ||
return this.store[key] = value; | ||
}, | ||
removeItem: function removeItem(key) { | ||
delete this.store[key]; | ||
return this; | ||
} | ||
}; | ||
} |
@@ -37,3 +37,3 @@ 'use strict'; | ||
// convert the alorithm value to an array | ||
// Convert the algorithm value to an array | ||
if (options.algorithm) { | ||
@@ -40,0 +40,0 @@ options.algorithms = [options.algorithm]; |
@@ -6,311 +6,15 @@ 'use strict'; | ||
}); | ||
exports.setupPrimusAuthentication = exports.setupSocketIOAuthentication = exports.failedLogin = exports.successfulLogin = exports.normalizeAuthToken = exports.exposeConnectMiddleware = undefined; | ||
var _debug = require('debug'); | ||
var _sockets = require('./sockets'); | ||
var _debug2 = _interopRequireDefault(_debug); | ||
var _express = require('./express'); | ||
var _feathersErrors = require('feathers-errors'); | ||
var _feathersErrors2 = _interopRequireDefault(_feathersErrors); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var debug = (0, _debug2.default)('feathers-authentication:middleware'); | ||
var THIRTY_SECONDS = 30000; | ||
// Usually this is a big no no but passport requires the | ||
// request object to inspect req.body and req.query so we | ||
// need to miss behave a bit. Don't do this in your own code! | ||
var exposeConnectMiddleware = exports.exposeConnectMiddleware = function exposeConnectMiddleware(req, res, next) { | ||
req.feathers.req = req; | ||
req.feathers.res = res; | ||
next(); | ||
exports.default = { | ||
exposeConnectMiddleware: _express.exposeConnectMiddleware, | ||
normalizeAuthToken: _express.normalizeAuthToken, | ||
successfulLogin: _express.successfulLogin, | ||
failedLogin: _express.failedLogin, | ||
setupSocketIOAuthentication: _sockets.setupSocketIOAuthentication, | ||
setupPrimusAuthentication: _sockets.setupPrimusAuthentication | ||
}; | ||
// Make the authenticated passport user also available for REST services. | ||
// We might need this for when we have session supported auth. | ||
// export let exposeAuthenticatedUser = function(options = {}) { | ||
// return function(req, res, next) { | ||
// req.feathers.user = req.user; | ||
// next(); | ||
// }; | ||
// }; | ||
// Make sure than an auth token passed in is available for hooks | ||
// and services. This gracefully falls back from | ||
// header -> body -> query string | ||
var normalizeAuthToken = exports.normalizeAuthToken = function normalizeAuthToken() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
debug('Setting up normalizeAuthToken middleware with options:', options); | ||
if (!options.header) { | ||
throw new Error('\'header\' must be provided to normalizeAuthToken() middleware'); | ||
} | ||
return function (req, res, next) { | ||
var token = req.headers[options.header]; | ||
// Check the header for the token (preferred method) | ||
if (token) { | ||
// if the value contains "bearer" or "Bearer" then cut that part out | ||
if (/bearer/i.test(token)) { | ||
token = token.split(' ')[1]; | ||
} | ||
} | ||
// Check the body next if we still don't have a token | ||
if (req.body.token) { | ||
token = req.body.token; | ||
delete req.body.token; | ||
} | ||
// Finally, check the query string. (worst method but nice for quick local dev) | ||
else if (req.query.token) { | ||
token = req.query.token; | ||
delete req.query.token; | ||
} | ||
// Tack it on to our feathers object so that it is passed to services | ||
req.feathers.token = token; | ||
next(); | ||
}; | ||
}; | ||
var successfulLogin = exports.successfulLogin = function successfulLogin() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
debug('Setting up successfulLogin middleware with options:', options); | ||
if (options.cookie === undefined) { | ||
throw new Error('\'cookie\' must be provided to successfulLogin() middleware or set to \'false\''); | ||
} | ||
return function (req, res, next) { | ||
// NOTE (EK): If we are not dealing with a browser or it was an | ||
// XHR request then just skip this. This is primarily for | ||
// handling the oauth redirects and for us to securely send the | ||
// JWT to the client in a cookie. | ||
if (!options.successRedirect || req.xhr || req.is('json') || !req.accepts('html')) { | ||
return next(); | ||
} | ||
// If cookies are enabled set our JWT in a cookie. | ||
if (options.cookie) { | ||
// clear any previous JWT cookie | ||
res.clearCookie(options.cookie.name); | ||
// Only send back cookies when not in production or when in production and using HTTPS | ||
if (!req.secure && process.env.NODE_ENV === 'production') { | ||
console.error('You should be using HTTPS in production! Refusing to send JWT in a cookie'); | ||
} else { | ||
var cookieOptions = Object.assign({}, options.cookie, { path: options.successRedirect }); | ||
// If a custom expiry wasn't passed then set the expiration to be 30 seconds from now. | ||
if (cookieOptions.expires === undefined) { | ||
var expiry = new Date(); | ||
expiry.setTime(expiry.getTime() + THIRTY_SECONDS); | ||
cookieOptions.expires = expiry; | ||
} | ||
if (!(cookieOptions.expires instanceof Date)) { | ||
throw new Error('cookie.expires must be a valid Date object'); | ||
} | ||
res.cookie(options.cookie.name, res.data.token, cookieOptions); | ||
} | ||
} | ||
// Redirect to our success route | ||
res.redirect(options.successRedirect); | ||
}; | ||
}; | ||
var failedLogin = exports.failedLogin = function failedLogin() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
debug('Setting up failedLogin middleware with options:', options); | ||
if (options.cookie === undefined) { | ||
throw new Error('\'cookie\' must be provided to failedLogin() middleware or set to \'false\''); | ||
} | ||
return function (error, req, res, next) { | ||
// NOTE (EK): If we are not dealing with a browser or it was an | ||
// XHR request then just skip this. This is primarily for | ||
// handling redirecting on an oauth failure. | ||
// console.log('Auth Error', error, options); | ||
if (!options.failureRedirect || req.xhr || req.is('json') || !req.accepts('html')) { | ||
return next(error); | ||
} | ||
// clear any previous JWT cookie | ||
if (options.cookie) { | ||
res.clearCookie(options.cookie.name); | ||
} | ||
debug('An authentication error occurred.', error); | ||
// Redirect to our failure route | ||
res.redirect(options.failureRedirect); | ||
}; | ||
}; | ||
var setupSocketIOAuthentication = exports.setupSocketIOAuthentication = function setupSocketIOAuthentication(app) { | ||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
options = Object.assign({}, options); | ||
debug('Setting up Socket.io authentication middleware with options:', options); | ||
return function (socket) { | ||
var errorHandler = function errorHandler(error) { | ||
socket.emit('unauthorized', error, function () { | ||
// TODO (EK): Maybe we support disconnecting the socket | ||
// if a certain number of authorization attempts have failed | ||
// for brute force protection | ||
// socket.disconnect('unauthorized'); | ||
}); | ||
throw error; | ||
}; | ||
// Expose the request object to services and hooks | ||
// for Passport. This is normally a big no no. | ||
socket.feathers.req = socket.request; | ||
socket.on('authenticate', function (data) { | ||
// Authenticate the user using token strategy | ||
if (data.token) { | ||
if (typeof data.token !== 'string') { | ||
return errorHandler(new _feathersErrors2.default.BadRequest('Invalid token data type.')); | ||
} | ||
var params = Object.assign({ provider: 'socketio' }, data); | ||
// The token gets normalized in hook.params for REST so we'll stay with | ||
// convention and pass it as params using sockets. | ||
app.service(options.tokenEndpoint).create({}, params).then(function (response) { | ||
socket.feathers.token = response.token; | ||
socket.feathers.user = response.data; | ||
socket.emit('authenticated', response); | ||
}).catch(errorHandler); | ||
} | ||
// Authenticate the user using local auth strategy | ||
else { | ||
// Put our data in a fake req.body object to get local auth | ||
// with Passport to work because it checks res.body for the | ||
// username and password. | ||
var _params = { | ||
provider: 'socketio', | ||
req: socket.request | ||
}; | ||
_params.req.body = data; | ||
app.service(options.localEndpoint).create(data, _params).then(function (response) { | ||
socket.feathers.token = response.token; | ||
socket.feathers.user = response.data; | ||
socket.emit('authenticated', response); | ||
}).catch(errorHandler); | ||
} | ||
}); | ||
socket.on('logout', function (callback) { | ||
// TODO (EK): Blacklist token | ||
try { | ||
delete socket.feathers.token; | ||
delete socket.feathers.user; | ||
} catch (error) { | ||
debug('There was an error logging out', error); | ||
return callback(new Error('There was an error logging out')); | ||
} | ||
callback(); | ||
}); | ||
}; | ||
}; | ||
// TODO (EK): DRY this up along with the code in setupSocketIOAuthentication | ||
var setupPrimusAuthentication = exports.setupPrimusAuthentication = function setupPrimusAuthentication(app) { | ||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
options = Object.assign({}, options); | ||
debug('Setting up Primus authentication middleware with options:', options); | ||
return function (socket) { | ||
var errorHandler = function errorHandler(error) { | ||
socket.send('unauthorized', error); | ||
// TODO (EK): Maybe we support disconnecting the socket | ||
// if a certain number of authorization attempts have failed | ||
// for brute force protection | ||
// socket.end('unauthorized', error); | ||
throw error; | ||
}; | ||
socket.request.feathers.req = socket.request; | ||
socket.on('authenticate', function (data) { | ||
// Authenticate the user using token strategy | ||
if (data.token) { | ||
if (typeof data.token !== 'string') { | ||
return errorHandler(new _feathersErrors2.default.BadRequest('Invalid token data type.')); | ||
} | ||
var params = Object.assign({ provider: 'primus' }, data); | ||
// The token gets normalized in hook.params for REST so we'll stay with | ||
// convention and pass it as params using sockets. | ||
app.service(options.tokenEndpoint).create({}, params).then(function (response) { | ||
socket.request.feathers.token = response.token; | ||
socket.request.feathers.user = response.data; | ||
socket.send('authenticated', response); | ||
}).catch(errorHandler); | ||
} | ||
// Authenticate the user using local auth strategy | ||
else { | ||
// Put our data in a fake req.body object to get local auth | ||
// with Passport to work because it checks res.body for the | ||
// username and password. | ||
var _params2 = { | ||
provider: 'primus', | ||
req: socket.request | ||
}; | ||
_params2.req.body = data; | ||
app.service(options.localEndpoint).create(data, _params2).then(function (response) { | ||
socket.request.feathers.token = response.token; | ||
socket.request.feathers.user = response.data; | ||
socket.send('authenticated', response); | ||
}).catch(errorHandler); | ||
} | ||
}); | ||
socket.on('logout', function (callback) { | ||
// TODO (EK): Blacklist token | ||
try { | ||
delete socket.request.feathers.token; | ||
delete socket.request.feathers.user; | ||
} catch (error) { | ||
debug('There was an error logging out', error); | ||
return callback(new Error('There was an error logging out')); | ||
} | ||
callback(); | ||
}); | ||
}; | ||
}; | ||
exports.default = { | ||
exposeConnectMiddleware: exposeConnectMiddleware, | ||
normalizeAuthToken: normalizeAuthToken, | ||
successfulLogin: successfulLogin, | ||
failedLogin: failedLogin, | ||
setupSocketIOAuthentication: setupSocketIOAuthentication, | ||
setupPrimusAuthentication: setupPrimusAuthentication | ||
}; | ||
module.exports = exports['default']; |
{ | ||
"name": "feathers-authentication", | ||
"description": "Add Authentication to your FeathersJS app.", | ||
"version": "0.7.7", | ||
"version": "0.7.8", | ||
"homepage": "https://github.com/feathersjs/feathers-authentication", | ||
@@ -61,3 +61,3 @@ "main": "lib/", | ||
"babel-core": "^6.1.21", | ||
"babel-plugin-add-module-exports": "^0.1.2", | ||
"babel-plugin-add-module-exports": "^0.2.0", | ||
"babel-preset-es2015": "^6.1.18", | ||
@@ -74,3 +74,3 @@ "body-parser": "^1.9.0", | ||
"localstorage-memory": "^1.0.2", | ||
"mocha": "^2.3.3", | ||
"mocha": "^2.5.0", | ||
"nsp": "^2.2.0", | ||
@@ -77,0 +77,0 @@ "passport-facebook": "^2.1.0", |
29
104325
1535