-
Notifications
You must be signed in to change notification settings - Fork 237
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
Add config to allow permanent session in cookie #593
Conversation
b4347e0
to
4fa0263
Compare
Rebased with latest from |
4fa0263
to
4f1467c
Compare
Renamed the option to |
As discussed on #472 there were some security concerns around file sessions stored on the server. e.g. if Heroku was hacked, your encrypted sessions can be stolen and brute forced. With this approach we avoid that:
|
4f1467c
to
99bfac1
Compare
I have tested this by:
I have also tested the 'clear data' function in both modes, and confirmed the session was removed. |
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.
Great work!
I think the 4kb limitation is reasonable given the pros for this approach, and we can always consider the file system approach in the future if it does become and issue.
I will need a review from another team member before we can merge this.
This will be really useful for us at DfE 👍 |
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.
Tested to work correctly 🙂 Left a couple of comments.
server.js
Outdated
// Session uses service name to avoid clashes with other prototypes | ||
const sessionName = 'govuk-prototype-kit-' + (Buffer.from(config.serviceName, 'utf8')).toString('hex') | ||
let sessionOptions = { | ||
secret: config.serviceName, |
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.
secret
used to be randomised. Could it use sessionName
instead?
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.
@hannalaakso Yep, no problem.
Had to remove the randomisation, otherwise you're locked out of your session on restart 😳
app/config.js
Outdated
@@ -15,6 +15,9 @@ module.exports = { | |||
// Automatically stores form data, and send to all views | |||
useAutoStoreData: 'true', | |||
|
|||
// Enable cookie-based session store (4KB limit, persists on restart) |
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.
More of a discussion but would it be worth adding to the comment that if you exceed the limit, there is no notification so you need to bear this in mind with large prototypes? In case people expect something to happen when you go over the limit.
I tested exceeding the limit by pasting in a super long string in vehicle-registration and (unsurprisingly) the value doesn't get retained which you find out in check-answers. If there is an existing value for that attribute in session data, it looks like the existing value is retained.
Like @NickColley said we might just want to go ahead with this and see if the limit becomes an issue in the future.
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.
@hannalaakso Yeah I'll add a comment.
Yup that's it. Node.js will happily send a cookie that's too big, but the browser will ignore it and keep the last cookie it had that was under the 4KB limit for the domain.
99bfac1
to
8f14c4b
Compare
Compatibility with other session stores that have no `.destroy()` method
Persists data between Node.js restarts
8f14c4b
to
66a75ab
Compare
Hi @hannalaakso, thanks for the review. I've addressed both your comments and rebased from In future (since the session is mainly text) a little gzip magic could be used to compress it down. It'll reduce cookie size down to about 65% of the original. |
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.
Thanks @colinrotherham, this looks great 🙌 💯 We can look into approaches of reducing the cookie size if we see it becoming an issue 👍
// Session uses service name to avoid clashes with other prototypes | ||
const sessionName = 'govuk-prototype-kit-' + (Buffer.from(config.serviceName, 'utf8')).toString('hex') | ||
let sessionOptions = { | ||
secret: sessionName, |
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.
not sure if there's an advantage to using a predictable string for the 'secret' of the cookie? I think it should be somewhat secret?
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.
ah, is this because when the app restarts it won't know the randomly generated secret? Hmm.. maybe we could store the secret somehow. If needed
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.
Yeah that's the trade-off sadly.
The old approach re-hashed the secret on every restart. This would lock you out of your cookie causing it to be regenerated.
Sounds like an idea though.
I'm currently working across two teams with long form journeys.
A quick prototyping scenario
What happens?
What's in this pull request
I've added the following config:
When set to
true
it swaps express-session with Mozilla client-sessions so retains compatibility withreq.session
and persists all session data in a cookie.