mirror of https://gitee.com/bigwinds/arangodb
Removed cookie logic from sessions app, simplified jwt logic.
This commit is contained in:
parent
251e046929
commit
99f9088830
|
@ -21,11 +21,12 @@ If *type* is set to *"cookie"*, the session cookie will be updated after every r
|
|||
* *type* (optional): sessions type, currently only *"cookie"* and *"header"* are supported. Default: *"cookie"*.
|
||||
* *cookieName* (optional): name of the session cookie if using cookie sessions. If a *cookieSecret* is provided, the signature will be stored in a cookie named *cookieName + "_sig"*. Default: *"sid"*.
|
||||
* *cookieSecret* (optional): secret string to sign session cookies with if using cookie sessions.
|
||||
* *cookieAlgorithm* (optional): algorithm to sign session cookies with if using cookie sessions. Default: *"sha256"*.
|
||||
* *headerName* (optional): name of the session header if using header sessions. Default: *"X-Session-Id"*.
|
||||
* *headerJwt* (optional): whether the session header should wrap the session ID in a JSON Web Token. Default: *false* unless *headerJwtSecret* is provided.
|
||||
* *headerJwtSecret* (optional): secret string to sign session header JSON Web Tokens.
|
||||
* *headerJwtAlgorithm* (optional): algorithm to sign session header JSON Web Tokens with, has no effect if no *headerJwtSecret* is provided. Default: *"HS256"*.
|
||||
* *headerJwtVerify* (optional): whether incoming session header JSON Web Tokens should be verified, has no effect if no *headerJwtSecret* is provided. Default: *true*.
|
||||
* *jwt* (optional): whether the session ID should be wrapped in a JSON Web Token. Default: *false* unless *jwtSecret* is provided.
|
||||
* *jwtSecret* (optional): secret string to sign session JSON Web Tokens with.
|
||||
* *jwtAlgorithm* (optional): algorithm to sign session JSON Web Tokens with if a *jwtSecret* is provided. Default: *"HS256"*.
|
||||
* *jwtVerify* (optional): whether incoming session JSON Web Tokens should be verified, has no effect if no *jwtSecret* is provided. Default: *true*.
|
||||
* *autoCreateSession* (optional): whether a session should always be created if none exists. Default: *true*.
|
||||
|
||||
@EXAMPLES
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
internal = require('internal'),
|
||||
arangodb = require('org/arangodb'),
|
||||
db = arangodb.db,
|
||||
addCookie = require('org/arangodb/actions').addCookie,
|
||||
crypto = require('org/arangodb/crypto'),
|
||||
Foxx = require('org/arangodb/foxx'),
|
||||
errors = require('./errors'),
|
||||
cfg = applicationContext.configuration,
|
||||
|
@ -102,28 +100,6 @@
|
|||
return null;
|
||||
}
|
||||
|
||||
function fromCookie(req, cookieName, secret) {
|
||||
var session = null,
|
||||
value = req.cookies[cookieName],
|
||||
signature;
|
||||
if (value) {
|
||||
if (secret) {
|
||||
signature = req.cookies[cookieName + '_sig'] || '';
|
||||
if (!crypto.constantEquals(signature, crypto.hmac(secret, value))) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
session = getSession(value);
|
||||
} catch (e) {
|
||||
if (!(e instanceof errors.SessionNotFound)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
_.extend(Session.prototype, {
|
||||
enforceTimeout: function () {
|
||||
if (this.hasExpired()) {
|
||||
|
@ -131,11 +107,17 @@
|
|||
}
|
||||
},
|
||||
hasExpired: function () {
|
||||
return Date.now() > this.getExpiry();
|
||||
return this.getTTL() === 0;
|
||||
},
|
||||
getTTL: function () {
|
||||
if (!cfg.timeToLive) {
|
||||
return Infinity;
|
||||
}
|
||||
return Math.max(0, this.getExpiry() - Date.now());
|
||||
},
|
||||
getExpiry: function () {
|
||||
if (!cfg.timeToLive) {
|
||||
return Number.MAX_VALUE;
|
||||
return Infinity;
|
||||
}
|
||||
var prop = cfg.ttlType;
|
||||
if (!prop || !this.get(prop)) {
|
||||
|
@ -143,21 +125,6 @@
|
|||
}
|
||||
return this.get(prop) + cfg.timeToLive;
|
||||
},
|
||||
addCookie: function (res, cookieName, secret) {
|
||||
var value = this.get('_key'),
|
||||
ttl = cfg.timeToLive;
|
||||
ttl = ttl ? Math.floor(ttl / 1000) : undefined;
|
||||
addCookie(res, cookieName, value, ttl);
|
||||
if (secret) {
|
||||
addCookie(res, cookieName + '_sig', crypto.hmac(secret, value), ttl);
|
||||
}
|
||||
},
|
||||
clearCookie: function (res, cookieName, secret) {
|
||||
addCookie(res, cookieName, '', -(7 * 24 * 60 * 60));
|
||||
if (secret) {
|
||||
addCookie(res, cookieName + '_sig', '', -(7 * 24 * 60 * 60));
|
||||
}
|
||||
},
|
||||
setUser: function (user) {
|
||||
var session = this;
|
||||
if (user) {
|
||||
|
@ -194,7 +161,6 @@
|
|||
}
|
||||
});
|
||||
|
||||
exports.fromCookie = fromCookie;
|
||||
exports.create = createSession;
|
||||
exports.get = getSession;
|
||||
exports.delete = deleteSession;
|
||||
|
|
|
@ -49,20 +49,26 @@ function decorateController(auth, controller) {
|
|||
|
||||
controller.before('/*', function (req) {
|
||||
var sessions = auth.getSessionStorage();
|
||||
var sid;
|
||||
if (cfg.type === 'cookie') {
|
||||
req.session = sessions.fromCookie(req, cfg.cookieName, cfg.cookieSecret);
|
||||
} else if (cfg.type === 'header') {
|
||||
var sid = req.headers[cfg.headerName.toLowerCase()];
|
||||
if (sid) {
|
||||
if (cfg.headerJwt) {
|
||||
sid = crypto.jwtDecode(cfg.headerJwtSecret, sid, !cfg.headerJwtVerify);
|
||||
sid = req.cookie(cfg.cookieName, cfg.cookieSecret ? {
|
||||
signed: {
|
||||
secret: cfg.cookieSecret,
|
||||
algorithm: cfg.cookieAlgorithm
|
||||
}
|
||||
try {
|
||||
req.session = sessions.get(sid);
|
||||
} catch (e) {
|
||||
if (!(e instanceof sessions.errors.SessionNotFound)) {
|
||||
throw e;
|
||||
}
|
||||
} : undefined);
|
||||
} else if (cfg.type === 'header') {
|
||||
sid = req.headers[cfg.headerName.toLowerCase()];
|
||||
}
|
||||
if (sid) {
|
||||
if (cfg.jwt) {
|
||||
sid = crypto.jwtDecode(cfg.jwt.secret, sid, !cfg.jwt.verify);
|
||||
}
|
||||
try {
|
||||
req.session = sessions.get(sid);
|
||||
} catch (e) {
|
||||
if (!(e instanceof sessions.errors.SessionNotFound)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,13 +79,19 @@ function decorateController(auth, controller) {
|
|||
|
||||
controller.after('/*', function (req, res) {
|
||||
if (req.session) {
|
||||
var sid = req.session.get('_key');
|
||||
if (cfg.jwt) {
|
||||
sid = crypto.jwtEncode(cfg.jwt.secret, sid, cfg.jwt.algorithm);
|
||||
}
|
||||
if (cfg.type === 'cookie') {
|
||||
req.session.addCookie(res, cfg.cookieName, cfg.cookieSecret);
|
||||
res.cookie(cfg.cookieName, sid, {
|
||||
ttl: req.session.getTTL() / 1000,
|
||||
signed: cfg.cookieSecret ? {
|
||||
secret: cfg.cookieSecret,
|
||||
algorithm: cfg.cookieAlgorithm
|
||||
} : undefined
|
||||
});
|
||||
} else if (cfg.type === 'header') {
|
||||
var sid = req.session.get('_key');
|
||||
if (cfg.headerJwt) {
|
||||
sid = crypto.jwtEncode(cfg.headerJwtSecret, sid, cfg.headerJwtAlgorithm);
|
||||
}
|
||||
res.set(cfg.headerName, sid);
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +127,13 @@ function createDestroySessionHandler(auth, opts) {
|
|||
req.session = auth.getSessionStorage().create();
|
||||
} else {
|
||||
if (cfg.type === 'cookie') {
|
||||
req.session.clearCookie(res, cfg.cookieName, cfg.cookieSecret);
|
||||
res.cookie(cfg.cookieName, '', {
|
||||
ttl: -(7 * 24 * 60 * 60),
|
||||
sign: cfg.cookieSecret ? {
|
||||
secret: cfg.cookieSecret,
|
||||
algorithm: cfg.cookieAlgorithm
|
||||
} : undefined
|
||||
});
|
||||
}
|
||||
delete req.session;
|
||||
}
|
||||
|
@ -171,35 +189,35 @@ function Sessions(opts) {
|
|||
if (opts.headerName && typeof opts.headerName !== 'string') {
|
||||
throw new Error('Header name must be a string or empty.');
|
||||
}
|
||||
if (opts.headerJwt !== false) {
|
||||
if (opts.headerJwtVerify !== false) {
|
||||
opts.headerJwtVerify = true;
|
||||
}
|
||||
if (!opts.headerJwtSecret) {
|
||||
opts.headerJwtSecret = '';
|
||||
if (!opts.headerJwtAlgorithm) {
|
||||
opts.headerJwtAlgorithm = 'none';
|
||||
} else if (opts.headerJwtAlgorithm !== 'none') {
|
||||
throw new Error('Must provide a JWT secret to use any algorithm other than "none".');
|
||||
}
|
||||
} else {
|
||||
opts.headerJwt = true;
|
||||
if (typeof opts.headerJwtSecret !== 'string') {
|
||||
throw new Error('Header JWT secret must be a string or empty.');
|
||||
}
|
||||
if (!opts.headerJwtAlgorithm) {
|
||||
opts.headerJwtAlgorithm = 'HS256';
|
||||
} else {
|
||||
opts.headerJwtAlgorithm = crypto.jwtCanonicalAlgorithmName(opts.headerJwtAlgorithm);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!opts.headerName) {
|
||||
opts.headerName = 'X-Session-Id';
|
||||
}
|
||||
} else {
|
||||
throw new Error('Only the following session types are supported at this time: ' + sessionTypes.join(', '));
|
||||
}
|
||||
if (opts.jwt !== false) {
|
||||
if (opts.jwtVerify !== false) {
|
||||
opts.jwtVerify = true;
|
||||
}
|
||||
if (!opts.jwtSecret) {
|
||||
opts.jwtSecret = '';
|
||||
if (!opts.jwtAlgorithm) {
|
||||
opts.jwtAlgorithm = 'none';
|
||||
} else if (opts.jwtAlgorithm !== 'none') {
|
||||
throw new Error('Must provide a JWT secret to use any algorithm other than "none".');
|
||||
}
|
||||
} else {
|
||||
opts.jwt = true;
|
||||
if (typeof opts.jwtSecret !== 'string') {
|
||||
throw new Error('Header JWT secret must be a string or empty.');
|
||||
}
|
||||
if (!opts.jwtAlgorithm) {
|
||||
opts.jwtAlgorithm = 'HS256';
|
||||
} else {
|
||||
opts.jwtAlgorithm = crypto.jwtCanonicalAlgorithmName(opts.jwtAlgorithm);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opts.autoCreateSession !== false) {
|
||||
opts.autoCreateSession = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue