Open forficate opened 8 years ago
Let's say: It depends :-)
If you use the Spock-core
package you have full control over that, the framework will not inject any cookies. But you also don't have CSRF
protection built in, no global "state" and no database pooling. The latter two are easy to implement in your own monad stack on top of SpockT
.
If you use the Spock
package, you currently can not prevent Spock from creating a spockcookie
. But I'd be happy to explore how we could integrate a fully client side session management, as I know of several other Spock users that have a similar setup. Are you interested in contributing?
Thanks.
I did switch to Spock-core using a ReaderT
with my own Connection Pool
and cookie Key
from the clientsession
package. Firefox was still reporting the spockcookie
in the inspector after repeatedly deleting it.
Checking again it must of been a Firefox issue, the cookie is no longer appearing. Verifying with curl
the Set-Cookie
header is not set as expected.
I am new to Haskell / Spock, happy to contribute where I can if you have any implementation suggestions.
Not knowing to much it might be possible using the existing SessionManager
type? sm_clearAllSessions
and sm_closeSessionManager
would be a noop for client side. sm_middleware
could have a middleware which automatically increments/validates expiry based on some config value. Not sure about the need for a sessionId clientside but can stay for compatibility. m
is the Spock monad so there is access to read / write a cookie?
data SessionManager m conn sess st
= SessionManager
{ sm_getSessionId :: m SessionId
, sm_getCsrfToken :: m T.Text
, sm_regenerateSessionId :: m ()
, sm_readSession :: m sess
, sm_writeSession :: sess -> m ()
, sm_modifySession :: forall a. (sess -> (sess, a)) -> m a
, sm_mapSessions :: (forall n. Monad n => sess -> n sess) -> m ()
, sm_clearAllSessions :: MonadIO m => m ()
, sm_middleware :: Middleware
, sm_closeSessionManager :: IO ()
}
Actually, the current SessionManager
implements a session manager for all m
in MonadIO
(see https://github.com/agrafix/Spock/blob/138198fa5e50d7238bfecc64678403aadc80fc37/Spock/src/Web/Spock/Internal/SessionManager.hs#L43-L50 ). We should probably split the SessionManager
into two (or three) types otherwise the type will not represent the semantics (i.E. sm_mapSessions
can not be implemented for client side sessions.) We will also need to track if we use client or server side sessions in the sess
parameter somehow we carry around to call/expose the functions to the end user. So to start we'd need to split the type for example like so:
data BaseSessionManager m conn sess st
= BaseSessionManager
{ bsm_getSessionId :: m SessionId
, bsm_getCsrfToken :: m T.Text
, bsm_regenerateSessionId :: m ()
, bsm_readSession :: m sess
, bsm_writeSession :: sess -> m ()
, bsm_modifySession :: forall a. (sess -> (sess, a)) -> m a
, bsm_middleware :: Middleware
}
data ServerSessionManager m conn sess st
= ServerSessionManager
{ ssm_base :: m (BaseSessionManager m conn sess st)
, ssm_mapSessions :: (forall n. Monad n => sess -> n sess) -> m ()
, ssm_clearAllSessions :: MonadIO m => m ()
, ssm_closeSessionManager :: IO ()
}
data ClientSessionManager m conn sess st
= ClientSessionManager
{ csm_base :: m (BaseSessionManager m conn sess st)
, -- what do we need apart from that?
}
All session values would then be wrapped with either newtype ServerSession sess = ServerSession sess
and newtype ClientSession sess = ClientSession sess
The functions in https://github.com/agrafix/Spock/blob/138198fa5e50d7238bfecc64678403aadc80fc37/Spock/src/Web/Spock/SessionActions.hs would then move to type classes IsAnySession
, IsServerSession
and IsClientSession
and be dependent on the session wrapper, as of how the session manager is initialized and chosen.
What do you think?
Two questions.
1) Is it possible to disable Spock from creating the
spockcookie
session cookie? I can see it's created with Wai middleware but can't an easy way to disable it.2) This leads on from I want to use a encrypted cookie to store sessions and not use a remote session store.
I currently create a encrypted session cookie on a callback from Auth0 with a expiry field in the cookie, user id, name and roles. The expiry is low, each request returns a new session cookie with expiry incremented creating a sliding session.
I can see the backend session storage is plugable but no way to disable backend storage and use a client side implementation? Is anything on the roadmap to allow this?