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"*.
|
* *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"*.
|
* *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.
|
* *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"*.
|
* *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.
|
* *jwt* (optional): whether the session ID should be wrapped in a JSON Web Token. Default: *false* unless *jwtSecret* is provided.
|
||||||
* *headerJwtSecret* (optional): secret string to sign session header JSON Web Tokens.
|
* *jwtSecret* (optional): secret string to sign session JSON Web Tokens with.
|
||||||
* *headerJwtAlgorithm* (optional): algorithm to sign session header JSON Web Tokens with, has no effect if no *headerJwtSecret* is provided. Default: *"HS256"*.
|
* *jwtAlgorithm* (optional): algorithm to sign session JSON Web Tokens with if a *jwtSecret* 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*.
|
* *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*.
|
* *autoCreateSession* (optional): whether a session should always be created if none exists. Default: *true*.
|
||||||
|
|
||||||
@EXAMPLES
|
@EXAMPLES
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
internal = require('internal'),
|
internal = require('internal'),
|
||||||
arangodb = require('org/arangodb'),
|
arangodb = require('org/arangodb'),
|
||||||
db = arangodb.db,
|
db = arangodb.db,
|
||||||
addCookie = require('org/arangodb/actions').addCookie,
|
|
||||||
crypto = require('org/arangodb/crypto'),
|
|
||||||
Foxx = require('org/arangodb/foxx'),
|
Foxx = require('org/arangodb/foxx'),
|
||||||
errors = require('./errors'),
|
errors = require('./errors'),
|
||||||
cfg = applicationContext.configuration,
|
cfg = applicationContext.configuration,
|
||||||
|
@ -102,28 +100,6 @@
|
||||||
return null;
|
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, {
|
_.extend(Session.prototype, {
|
||||||
enforceTimeout: function () {
|
enforceTimeout: function () {
|
||||||
if (this.hasExpired()) {
|
if (this.hasExpired()) {
|
||||||
|
@ -131,11 +107,17 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hasExpired: function () {
|
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 () {
|
getExpiry: function () {
|
||||||
if (!cfg.timeToLive) {
|
if (!cfg.timeToLive) {
|
||||||
return Number.MAX_VALUE;
|
return Infinity;
|
||||||
}
|
}
|
||||||
var prop = cfg.ttlType;
|
var prop = cfg.ttlType;
|
||||||
if (!prop || !this.get(prop)) {
|
if (!prop || !this.get(prop)) {
|
||||||
|
@ -143,21 +125,6 @@
|
||||||
}
|
}
|
||||||
return this.get(prop) + cfg.timeToLive;
|
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) {
|
setUser: function (user) {
|
||||||
var session = this;
|
var session = this;
|
||||||
if (user) {
|
if (user) {
|
||||||
|
@ -194,7 +161,6 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.fromCookie = fromCookie;
|
|
||||||
exports.create = createSession;
|
exports.create = createSession;
|
||||||
exports.get = getSession;
|
exports.get = getSession;
|
||||||
exports.delete = deleteSession;
|
exports.delete = deleteSession;
|
||||||
|
|
|
@ -49,13 +49,20 @@ function decorateController(auth, controller) {
|
||||||
|
|
||||||
controller.before('/*', function (req) {
|
controller.before('/*', function (req) {
|
||||||
var sessions = auth.getSessionStorage();
|
var sessions = auth.getSessionStorage();
|
||||||
|
var sid;
|
||||||
if (cfg.type === 'cookie') {
|
if (cfg.type === 'cookie') {
|
||||||
req.session = sessions.fromCookie(req, cfg.cookieName, cfg.cookieSecret);
|
sid = req.cookie(cfg.cookieName, cfg.cookieSecret ? {
|
||||||
|
signed: {
|
||||||
|
secret: cfg.cookieSecret,
|
||||||
|
algorithm: cfg.cookieAlgorithm
|
||||||
|
}
|
||||||
|
} : undefined);
|
||||||
} else if (cfg.type === 'header') {
|
} else if (cfg.type === 'header') {
|
||||||
var sid = req.headers[cfg.headerName.toLowerCase()];
|
sid = req.headers[cfg.headerName.toLowerCase()];
|
||||||
|
}
|
||||||
if (sid) {
|
if (sid) {
|
||||||
if (cfg.headerJwt) {
|
if (cfg.jwt) {
|
||||||
sid = crypto.jwtDecode(cfg.headerJwtSecret, sid, !cfg.headerJwtVerify);
|
sid = crypto.jwtDecode(cfg.jwt.secret, sid, !cfg.jwt.verify);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
req.session = sessions.get(sid);
|
req.session = sessions.get(sid);
|
||||||
|
@ -65,7 +72,6 @@ function decorateController(auth, controller) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!req.session && cfg.autoCreateSession) {
|
if (!req.session && cfg.autoCreateSession) {
|
||||||
req.session = sessions.create();
|
req.session = sessions.create();
|
||||||
}
|
}
|
||||||
|
@ -73,13 +79,19 @@ function decorateController(auth, controller) {
|
||||||
|
|
||||||
controller.after('/*', function (req, res) {
|
controller.after('/*', function (req, res) {
|
||||||
if (req.session) {
|
if (req.session) {
|
||||||
if (cfg.type === 'cookie') {
|
|
||||||
req.session.addCookie(res, cfg.cookieName, cfg.cookieSecret);
|
|
||||||
} else if (cfg.type === 'header') {
|
|
||||||
var sid = req.session.get('_key');
|
var sid = req.session.get('_key');
|
||||||
if (cfg.headerJwt) {
|
if (cfg.jwt) {
|
||||||
sid = crypto.jwtEncode(cfg.headerJwtSecret, sid, cfg.headerJwtAlgorithm);
|
sid = crypto.jwtEncode(cfg.jwt.secret, sid, cfg.jwt.algorithm);
|
||||||
}
|
}
|
||||||
|
if (cfg.type === 'cookie') {
|
||||||
|
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') {
|
||||||
res.set(cfg.headerName, sid);
|
res.set(cfg.headerName, sid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +127,13 @@ function createDestroySessionHandler(auth, opts) {
|
||||||
req.session = auth.getSessionStorage().create();
|
req.session = auth.getSessionStorage().create();
|
||||||
} else {
|
} else {
|
||||||
if (cfg.type === 'cookie') {
|
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;
|
delete req.session;
|
||||||
}
|
}
|
||||||
|
@ -171,35 +189,35 @@ function Sessions(opts) {
|
||||||
if (opts.headerName && typeof opts.headerName !== 'string') {
|
if (opts.headerName && typeof opts.headerName !== 'string') {
|
||||||
throw new Error('Header name must be a string or empty.');
|
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) {
|
if (!opts.headerName) {
|
||||||
opts.headerName = 'X-Session-Id';
|
opts.headerName = 'X-Session-Id';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Only the following session types are supported at this time: ' + sessionTypes.join(', '));
|
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) {
|
if (opts.autoCreateSession !== false) {
|
||||||
opts.autoCreateSession = true;
|
opts.autoCreateSession = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue