loopback/server/middleware/token.js

101 lines
3.3 KiB
JavaScript
Raw Normal View History

2014-01-06 23:52:08 +00:00
/*!
2013-11-13 19:49:08 +00:00
* Module dependencies.
*/
var loopback = require('../../lib/loopback');
2013-12-03 00:37:42 +00:00
var assert = require('assert');
var debug = require('debug')('loopback:middleware:token');
2013-11-13 19:49:08 +00:00
2014-01-06 23:52:08 +00:00
/*!
2013-11-13 19:49:08 +00:00
* Export the middleware.
*/
module.exports = token;
/*
* Rewrite the url to replace current user literal with the logged in user id
*/
function rewriteUserLiteral(req, currentUserLiteral) {
if (req.accessToken && req.accessToken.userId && currentUserLiteral) {
// Replace /me/ with /current-user-id/
var urlBeforeRewrite = req.url;
req.url = req.url.replace(
new RegExp('/' + currentUserLiteral + '(/|$|\\?)', 'g'),
'/' + req.accessToken.userId + '$1');
if (req.url !== urlBeforeRewrite) {
debug('req.url has been rewritten from %s to %s', urlBeforeRewrite,
req.url);
}
}
}
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
2014-10-16 22:54:40 +00:00
/**
2014-06-05 00:42:18 +00:00
* Check for an access token in cookies, headers, and query string parameters.
* This function always checks for the following:
2014-10-16 22:54:40 +00:00
*
* - `access_token` (params only)
* - `X-Access-Token` (headers only)
* - `authorization` (headers and cookies)
2014-06-05 00:42:18 +00:00
*
* It checks for these values in cookies, headers, and query string parameters _in addition_ to the items
* specified in the options parameter.
2014-10-16 22:54:40 +00:00
*
2014-06-05 00:42:18 +00:00
* **NOTE:** This function only checks for [signed cookies](http://expressjs.com/api.html#req.signedCookies).
2014-10-16 22:54:40 +00:00
*
2014-01-06 23:52:08 +00:00
* The following example illustrates how to check for an `accessToken` in a custom cookie, query string parameter
* and header called `foo-auth`.
2014-10-16 22:54:40 +00:00
*
2014-01-06 23:52:08 +00:00
* ```js
* app.use(loopback.token({
* cookies: ['foo-auth'],
* headers: ['foo-auth', 'X-Foo-Auth'],
2014-06-05 00:42:18 +00:00
* params: ['foo-auth', 'foo_auth']
2014-01-06 23:52:08 +00:00
* }));
* ```
*
2014-06-05 00:42:18 +00:00
* @options {Object} [options] Each option array is used to add additional keys to find an `accessToken` for a `request`.
* @property {Array} [cookies] Array of cookie names.
* @property {Array} [headers] Array of header names.
* @property {Array} [params] Array of param names.
* @property {Function|String} [model] AccessToken model name or class to use.
* @property {String} [currentUserLiteral] String literal for the current user.
2014-06-05 00:42:18 +00:00
* @header loopback.token([options])
2014-01-06 23:52:08 +00:00
*/
2013-11-14 23:27:36 +00:00
function token(options) {
2013-11-13 19:49:08 +00:00
options = options || {};
2013-12-03 01:16:43 +00:00
var TokenModel = options.model || loopback.AccessToken;
if (typeof TokenModel === 'string') {
// Make it possible to configure the model in middleware.json
TokenModel = loopback.getModel(TokenModel);
}
var currentUserLiteral = options.currentUserLiteral;
if (currentUserLiteral && (typeof currentUserLiteral !== 'string')) {
debug('Set currentUserLiteral to \'me\' as the value is not a string.');
currentUserLiteral = 'me';
}
if (typeof currentUserLiteral === 'string') {
currentUserLiteral = escapeRegExp(currentUserLiteral);
}
assert(typeof TokenModel === 'function',
'loopback.token() middleware requires a AccessToken model');
2014-10-16 22:54:40 +00:00
return function(req, res, next) {
if (req.accessToken !== undefined) {
rewriteUserLiteral(req, currentUserLiteral);
return next();
}
2013-11-14 21:01:47 +00:00
TokenModel.findForRequest(req, options, function(err, token) {
req.accessToken = token || null;
rewriteUserLiteral(req, currentUserLiteral);
var ctx = loopback.getCurrentContext();
if (ctx) ctx.set('accessToken', token);
next(err);
2013-11-14 21:01:47 +00:00
});
2014-10-16 22:54:40 +00:00
};
2013-11-13 19:49:08 +00:00
}