-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Added support for passing session ID using HTTP header #79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
3c9ef96
87e4da0
1e6f945
c11b484
401d74c
9a17e65
f14a811
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -85,13 +85,21 @@ function session(options){ | |
| var options = options || {} | ||
| // name - previously "options.key" | ||
| , name = options.name || options.key || 'connect.sid' | ||
| // optional name of HTTP header to pass session ID, e.g. 'X-Session-Token' | ||
| , headerName = options.header | ||
| , store = options.store || new MemoryStore | ||
| , cookie = options.cookie || {} | ||
| , trustProxy = options.proxy | ||
| , storeReady = true | ||
| , rollingSessions = options.rolling || false; | ||
| var resaveSession = options.resave; | ||
| var saveUninitializedSession = options.saveUninitialized; | ||
| var isCookieConfigurationSet = options.cookie !== null; | ||
| var headerNameNormalized; | ||
| if (headerName) { | ||
| // lower-case representation of header name to fetch header value from req.headers | ||
| headerNameNormalized = headerName.toLowerCase(); | ||
| } | ||
|
|
||
| var generateId = options.genid || generateSessionId; | ||
|
|
||
|
|
@@ -126,7 +134,9 @@ function session(options){ | |
| store.generate = function(req){ | ||
| req.sessionID = generateId(req); | ||
| req.session = new Session(req); | ||
| req.session.cookie = new Cookie(cookie); | ||
| if (isCookieConfigurationSet) { | ||
| req.session.cookie = new Cookie(cookie); | ||
| } | ||
| }; | ||
|
|
||
| var storeImplementsTouch = typeof store.touch === 'function'; | ||
|
|
@@ -145,9 +155,11 @@ function session(options){ | |
| // the store has temporarily disconnected etc | ||
| if (!storeReady) return debug('store is disconnected'), next(); | ||
|
|
||
| // pathname mismatch | ||
| var originalPath = parseUrl.original(req).pathname; | ||
| if (0 != originalPath.indexOf(cookie.path || '/')) return next(); | ||
| if (isCookieConfigurationSet) { | ||
| // pathname mismatch | ||
| var originalPath = parseUrl.original(req).pathname; | ||
| if (0 != originalPath.indexOf(cookie.path || '/')) return next(); | ||
| } | ||
|
|
||
| // backwards compatibility for signed cookies | ||
| // req.secret is passed from the cookie parser middleware | ||
|
|
@@ -163,8 +175,15 @@ function session(options){ | |
| // expose store | ||
| req.sessionStore = store; | ||
|
|
||
| // get the session ID from the cookie | ||
| var cookieId = req.sessionID = getcookie(req, name, secret); | ||
| var cookieId; | ||
| if (isCookieConfigurationSet) { | ||
| // get the session ID from the cookie | ||
| cookieId = req.sessionID = getcookie(req, name, secret); | ||
| } | ||
| if (headerName) { | ||
| // get the session ID from the header | ||
| cookieId = req.sessionID = getHeader(req, headerNameNormalized, secret); | ||
| } | ||
|
|
||
| // set-cookie | ||
| onHeaders(res, function(){ | ||
|
|
@@ -173,19 +192,22 @@ function session(options){ | |
| return; | ||
| } | ||
|
|
||
| var cookie = req.session.cookie; | ||
|
|
||
| // only send secure cookies via https | ||
| if (cookie.secure && !issecure(req, trustProxy)) { | ||
| debug('not secured'); | ||
| return; | ||
| if (isCookieConfigurationSet) { | ||
| var cookie = req.session.cookie; | ||
| // only send secure cookies via https | ||
| if (cookie.secure && !issecure(req, trustProxy)) { | ||
| debug('not secured'); | ||
| return; | ||
| } | ||
| if (!shouldSetCookie(req)) { | ||
| return; | ||
| } | ||
| setcookie(res, name, req.sessionID, secret, cookie.data); | ||
| } | ||
|
|
||
| if (!shouldSetCookie(req)) { | ||
| return; | ||
| if (headerName) { | ||
| setHeader(res, headerName, req.sessionID, secret); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So setting a headerName will set the session id in header and cookie. Should this be exclusive?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This made to provide backward compatibility when part of front-end code still using cookie based authorization. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the user put this in settings explicitly for having both? If I will use this functionality to have session id in headers, I will not want it in cookie no more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. You are right, user should have an ability to choose what type of session id passing he wants to use. I will try to update PR to support your suggestion. |
||
|
|
||
| setcookie(res, name, req.sessionID, secret, cookie.data); | ||
| }); | ||
|
|
||
| // proxy end() to commit the session | ||
|
|
@@ -573,3 +595,31 @@ function setcookie(res, name, val, secret, options) { | |
|
|
||
| res.setHeader('set-cookie', header) | ||
| } | ||
|
|
||
| function setHeader(res, name, val, secret) { | ||
| var signed = 's:' + signature.sign(val, secret); | ||
| debug(name + ' %s', signed); | ||
|
|
||
| res.setHeader(name, signed); | ||
| } | ||
|
|
||
| function getHeader(req, name, secret) { | ||
| var header = req.headers[name]; | ||
| var val; | ||
|
|
||
| // read from header | ||
| if (header) { | ||
| if (header.substr(0, 2) === 's:') { | ||
| val = signature.unsign(header.slice(2), secret); | ||
|
|
||
| if (val === false) { | ||
| debug('header signature invalid'); | ||
| val = undefined; | ||
| } | ||
| } else { | ||
| debug('header unsigned') | ||
| } | ||
| } | ||
|
|
||
| return val; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discuss: change to just
header, or probably better,id-header?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Fishrock123 I think
headerwill be better name for this option.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in index.js
var signed = 's:' + signature.sign(val, secret);
secret is an Array, instead of a string, so your code has broken.