With Go 1.7's request.Context()
requiring a (non-trivial!) breaking API change, I figured it would be a good time to discuss what a "v2" of this package would look like. Further, with golang/dep on the horizon, vendoring/pinning dependencies is more common-place, allowing us to 'safely' leave v1 API users as-is whilst improving the library for others.
What I see as key changes:
Save(w, r)
rather than (r, w)
Save
(forgetting to save sucks, and is common enough!)There is no schedule for this yet. Open to feedback.
I agree with pretty much all of this.
Great. I'd also likely simplify gorilla/securecookie as part of this: the internals have grown over time, and moving from the current AES-CTR + MAC approach to either HMAC-SHA-512/256 or ChaCha20+Poly1305 (https://godoc.org/golang.org/x/crypto/chacha20poly1305) and thus simplifying the crypto.
securecookie is otherwise a small lib; I think it was a mistake growing the error interface the way we did, but alas.
+1 for pretty much all of these.
You've probably already considered this, but one thing I learnt from building SCS was that although using JSON for the default encoding is sensible from a performance view it has the potential to make things more complicated for users (assuming a map[interface{}]interface{}
is still used behind the scenes).
For example, retrieving a previously stored time.Time
object. With gob encoding, the user can just retrieve the interface{}
value and assert it to a time.Time
. It's fairly simple and straightforward. With underlying JSON encoding, the user needs to know to type assert the interface{}
value to a string and then call time.Parse(time.RFC3339, ...)
to get it back to a time.Time
object.
Similarly, dealing with integers and floats and json.Number
is a bit of a pain.
You could implement helpers (like I did in SCS), or there's probably something clever that can be done with a custom JSON unmarshaller. Either way, it would be good to keep usage no more difficult than it is with gob encoding.
A couple of further suggestions.
It would be nice if both absolute and idle timeouts could be supported (in line with the OWASP recommendations).
For the non-cookie stores, there would ideally be an clear and baked-in way to renew session IDs after login/logouts etc to help prevent session fixation attacks (possibly as part of the interface along with New, Save etc). At the moment this isn't possible (at least as far as I can see) without a clunky workaround of creating a new session with a different name and copying the data over.
Thanks for the input @alexedwards -
It would be nice if both absolute and idle timeouts could be supported (in line with the OWASP recommendations).
Yes, agreed. Some opts.MaxAge
and opts.IdleTimeout
would be useful. I'd need to think about how to employ that without also performing a Set-Cookie
on every response too.
For the non-cookie stores, there would ideally be an clear and baked-in way to renew session IDs after login/logouts etc to help prevent session fixation attacks (possibly as part of the interface along with New, Save etc).
Agree - a Refresh
method would be useful here, or an argument to Save
that achieves the same effect (issues a new ID).
https://github.com/gorilla/securecookie/issues/43 tracks a "v2" of securecookie that will underpin some of this work
This looks great. One question: have you considered/what are the tradeoffs of putting included stores with non stdlib imports (cookie, boltdb) into separate packages?
Thank you for all your work!
@ccahoon The stores would each be in separate packages ("sub-packages") so that if you don't use BoltDB, it's not imported.
Redis, MySQL & Postgres backends already exist, and the Redis store is
rather polished. All of the third party stores are linked in the README.
On Thu, Mar 23, 2017 at 4:47 PM Kyle Terry notifications@github.com wrote:
Redis and database (sql) support would be cool too. If you are running n
instances of the application using gorilla/sessions you need to be able to
centralize your sessions for round robin.—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
https://github.com/gorilla/sessions/issues/105#issuecomment-288893992,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABIcDfaPALfkjOw5FzdDoM_MHs9RbCYks5rowSIgaJpZM4LwM5f
.
I think especially supporting the golang context package would be a big step forward. It's even backwards compatible, since all interfaces already accept a request to get the value.
Any timeline on this?
@Niondir No timeline. I want to wait until golang/dep hits 1.0 so I existing users have a clear way to pin to pre-2.0. As it is, those pulling from master will see a ton of breakage immediately, which is going to be painful as gorilla/sessions sees use from a wide range of developers (newbie Gophers to experienced).
A way to disable the in memory cache would be great. This package is unusable in applications that run multiple instances.
Can you share more details here? The cache should only live for one
request; sessions are otherwise not stored in memory across requests.
On Mon, Dec 18, 2017 at 5:16 AM Romain Menke notifications@github.com
wrote:
A way to disable the in memory cache would be great. This package is
unusable in applications that run multiple instances.—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
https://github.com/gorilla/sessions/issues/105#issuecomment-352422398,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABIcETDijyILlKONBJDuBlr6REcQgK6ks5tBmWTgaJpZM4LwM5f
.
@elithrar My bad, have been looking at too many packages that utilise an in memory cache that is shared across requests. Looking through the source code it was not immediately clear that the Registry was isolated to a single request. Thx for pointing this out!
Is dep 1.0 still a blocker? According to the status in the readme, dep is safe for production usage: https://github.com/golang/dep#current-status
Namely, the manifest and lock files are stable. See: https://github.com/golang/dep/wiki/Roadmap#timeline
My understanding is that if gorilla/sessions starts using dep, downstream packages shouldn't be affected. See: https://github.com/golang/dep/blob/master/docs/FAQ.md#my-dependers-dont-use-dep-yet-what-should-i-do
Any downstream package that's using the master branch should be aware that they've signed up for backwards incompatible changes. The other option would be to create a new repo/package if preserving backwards compatibility is paramount.
Any downstream package that's using the master branch should be aware
that they've signed up
That hasn’t been the status quo, and the lack of an option in the toolchain
is the pain point for regular users.
dep being in the Go toolchain is strongly preferred before we use it to
break the API here.
We may do it earlier than that, but not without careful consideration.
The other option would be to create a new repo/package if preserving
backwards compatibility is paramount.
That ends up islanding old users & causing a lot of confusion. I’ve not
seen that work well to date.
On Wed, Jan 10, 2018 at 11:19 PM Dale Hui notifications@github.com wrote:
Is dep 1.0 still a blocker? According to the status in the readme, dep is
safe for production usage: https://github.com/golang/dep#current-status
Namely, the manifest and lock files are stable. See:
https://github.com/golang/dep/wiki/Roadmap#timelineMy understanding is that if gorilla/sessions starts using dep, downstream
packages shouldn't be affected. See:
https://github.com/golang/dep/blob/master/docs/FAQ.md#my-dependers-dont-use-dep-yet-what-should-i-doAny downstream package that's using the master branch should be aware that
they've signed up for backwards incompatible changes. The other option
would be to create a new repo/package if preserving backwards compatibility
is paramount.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/gorilla/sessions/issues/105#issuecomment-356847518,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABIcO-Q_kwTZCommIiIm02ce7dd2afRks5tJbYWgaJpZM4LwM5f
.
dep ensure -add github.com/gorilla/sessions@^1.0.0
should properly pin the package.
But yeah, anyone who's used (or using) go get
will have a problem and I guess it's too early to force all of the downstream packages to start using dep
.
What do you think about creating a v2 branch to start all of the v2 work, tagging new releases off of the v2 branch, and requiring v2 users to use dep
? The v2 branch could be merged back into master when dep
is part of the toolchain.
Yes, that's an option I've considered.
I'd also need to start the work on securecookie first, as sessions relies
on securecookie, and I'd like to update that library.
On Thu, Jan 11, 2018 at 11:45 AM Dale Hui notifications@github.com wrote:
dep ensure -add github.com/gorilla/sessions@^1.0.0 should properly pin
the package.
But yeah, anyone who's used (or using) go get will have a problem and I
guess it's too early to force all of the downstream packages to start using
dep.What do you think about creating a v2 branch to start all of the v2 work,
tagging new releases off of the v2 branch, and requiring v2 users to use
dep? The v2 branch could be merged back into master when dep is part of
the toolchain.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/gorilla/sessions/issues/105#issuecomment-357039763,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABIcFVJM02Np6zhOehopNPu2dmzUwPkks5tJmTEgaJpZM4LwM5f
.
Cool, lemme know where I can help out by tagging me on any issue in sessions
or securecookie
If you have any opinions on:
There's been a handful of issues tagged as "v2" that provide some
background / user feedback, but I want to make sure we solve either new
problems, or solve old problems better, by breaking the API. Breaking for
the sake of breaking makes less sense ;)
On Thu, Jan 11, 2018 at 4:20 PM Dale Hui notifications@github.com wrote:
Cool, lemme know where I can help out by tagging me on any issue in
sessions or securecookie—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/gorilla/sessions/issues/105#issuecomment-357104851,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABIcOppAU5Mj8YyU6US-lRBQ14wgb8oks5tJqVJgaJpZM4LwM5f
.
I think most of the improvements listed in the issue description are good to have.
The changes I find the most useful (in-order) are:
sessions
package, not by the store.Store
receiver methods to not use http.Request
and http.ResponseWriter
would be a breaking change.request.Context
was used?Save
(forgetting to save sucks, and is common enough!)"Regarding "Make sessions.Values better (setters, getters, rather than a map)", I'd like to keep the sessions.Values
map but also expose type-casting getters and setters. The developer may have their own way of handling type-casting failures.
Thanks for the feedback @dhui
The store API needs to be revamped and re-designed. An implementer of a session store shouldn't be responsible for setting the HTTP cookie in the response. Cookie management and the session lifecycle should be handled by the sessions package, not by the store.
Session stores should only have one concern which is the persistence of the session data. Pushing core functionality (even parts of it) to the stores will result in inconsistent behaviors between 3rd party stores and make it harder to change core functionality in the future.
Agree. Stores need the session ID (to allow lookup), TTL (to allow expiry) and the session payload itself. There are a few approaches here - I'll omit context.Context
from the signatures for now as that warrants further discussion.
type Store interface {
Get(id string) (*Session, error)
Save(session *Session) error
Expire(id string) (bool, error)
}
Stores would need to care about marshalling *Session
to the correct format: we could alternatively send id string, exp time.Time, data []byte
where data
is already marshalled, but I feel marshalling is within the purvey of a Store.
Supporting request.Context (only)
Would the registry/cache still be necessary if request.Context was used?
No, but that goes back to the larger, breaking change. We would only support context.Context
in v2 as gorilla/context
does not cooperate when used alongside request.WithContext
due to the way it shallow clones a request.
Out of the box middleware that makes a session available
How would it make it available? In the request context? If so, fetching it from there is the same amount of code—except, with type assertions as context.Value is an interface{}
—as calling sessions.Get(ctx, name)
.
Saving, on the other hand, can be done (mostly) automatically, although if a user writes to the response body before the middleware runs, we'll run into issues. The middleware would need to hijack the http.ResponseWriter
and defer writes so that it can Save
. There's also the fact that you may not wish to Save
on every request.
Improved crypto interface
I'm a fan of having safe defaults but allowing the developer to customize security for their usecase. A good way of doing this is by exposing a separate "unsafe" or "hazmat" package. Inspired by https://golang.org/pkg/unsafe/ and https://cryptography.io/en/latest/
I'd need to see an extremely convincing argument for this. I don't see any sensible use-case for why a developer needs to customize the cryptographic primitives of a sessions library. You should not need to replace the CSPRNG, and you shouldn't need to change the AEAD. We'll use HMAC-SHA-512 for auth-only mode & XSalsa20-Poly1305 for encrypted mode (AEAD).
JSON as the default encoder
Yes!
Regarding "Make sessions.Values better (setters, getters, rather than a map)", I'd like to keep the sessions.Values map but also expose type-casting getters and setters. The developer may have their own way of handling type-casting failures.
Agree!
You're welcome! Thanks for being open and receptive to different ideas!
Stores would need to care about marshalling *Session to the correct format: we could alternatively send id string, exp time.Time, data []byte where data is already marshalled, but I feel marshalling is within the purvey of a Store.
Agreed. I think the Store should be responsible for storing the data since there may be more efficient storage mechanisms for the store besides []byte
. The Session
will need all relevant fields exported for stores to support marshalling and unmarshalling.
How would it make it available? In the request context?
Yeah, I'm a fan of the middleware setting the Session
using an unexported context key type in request.Context()
. That way, there's a bit less boiler plate code for the consuming developer.
Something like sessions.SessionFromRequest(http.Request) (*Session, error)
. We could also drop the error
and create a new Session
if it's used w/o the middleware, but that could lead to subtle bugs if there are multiple calls using the same request.
The middleware would need to hijack the http.ResponseWriter and defer writes so that it can Save.
I'm not familiar w/ the Hijacker
interface, but it seems like we'd want compatibility with HTTP/2 connections. I'm not sure if wrapping the ResponseWriter
to set the cookie after WriteHeader()
called is the best route.
There's also the fact that you may not wish to Save on every request.
Good point regarding the middleware. We could have 2 middlewares:
I'd need to see an extremely convincing argument for this.
Haha, I don't think I have one but I'll try... My best argument is that there's no one size fits all for security. Security is about making trade-offs between usability, performance, and protection against expected attack vectors. The best person to make that decision is the the app developer. Providing a clean crypto interface (sane defaults and allowing customization with ample warnings) would allow developers to customize security for their usecase. e.g. They could use HSMs and/or TRNGs if they wanted to although it's probably overkill for sessions...
One other thing regarding the crypto interface: make sure there's a way to change/upgrade the algorithm, key size, and work factor. These things are always change, so a system that can auto upgrade the algo, key size, and work factor will save a lot of future headaches.
This issue has been automatically marked as stale because it hasn't seen a recent update. It'll be automatically closed in a few days.
This issue has been automatically marked as stale because it hasn't seen a recent update. It'll be automatically closed in a few days.
Should this be reopened?
Most helpful comment
I think especially supporting the golang context package would be a big step forward. It's even backwards compatible, since all interfaces already accept a request to get the value.
Any timeline on this?