| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Wai.CryptoCookie
Contents
Description
This module exports tools for safely storing encrypted data on client-side cookies through Network.Wai.
This module is designed to be imported as follows:
import qualified Wai.CryptoCookie
One example of how to obtain a new Network.Wai.Middleware,
do (middleware, lookup) <- do
key <- Wai.CryptoCookie.autoKeyFileBase16 "/run/my-cookie-encryption-key"
Wai.CryptoCookie.middleware (Wai.CryptoCookie.defaultConfig key)
The obtained middleware shall be applied to your
Network.Wai.Application.
The obtained lookup function can be used to obtain the CryptoCookie
associated with each Request. It returns Nothing if this particular
middleware was not used on the given Request.
Finally, interact with the CryptoCookie data using get or set.
Do I store session data on the client or on the server?
It's not so much about where to store the session data, but about how to store it and how to expire it. Here are some ideas. But please, do your own research.
- Data on server, identifier on both: In this approach, all the data is
stored on the server. On the
CryptoCookie, simplyseta unique session identifier and latergetit back and use it to find the associated session data on your server-side database. In order to expire the session, all the server have to do is remove this session identifier from its database. Choose this option unless you know what you are doing, it doesn't require you to plan ahead too much. - Data on the client, identifier on both: In this approach, all the
data and session identifier is stored on the
CryptoCookie. On your server-side database, store the session identifier and a timestamp representing its creation time or last session activity time. Before accepting the session data from theCryptoCookieas valid, check that the session identifier exists in your database, and that the time since the timestamp is acceptable. This approach is simpler on your server-side database, but it can lead to more network traffic, and schema migrations for session data will be complex if you care about backwards compatibility with currently active sessions. - Everything on the client: You can store everything in the
CryptoCookie. However, you will be more suceptible to replay attacks because you won't have control over session expiration beyond comparing the current time against the session creation timestamp or last activity timestamp previously set in the session data. You can force all the existing sessions to “expire” by rotating your encryptionKey. Also, this approach can lead to more network traffic, and schema migrations for session data will be complex if you care about backwards compatibility with currently active sessions.
Synopsis
- data CryptoCookie a
- get :: CryptoCookie a -> Maybe a
- set :: CryptoCookie a -> Maybe a -> STM ()
- middleware :: forall a m. MonadIO m => Config a -> m (Middleware, Request -> Maybe (CryptoCookie a))
- defaultConfig :: (FromJSON a, ToJSON a) => Key "AEAD_AES_256_GCM_SIV" -> Config a
- data Config a = Encryption e => Config {}
- autoKeyFileBase16 :: forall {k} (e :: k) m. (Encryption e, MonadIO m) => FilePath -> m (Key e)
- readKeyFileBase16 :: forall {k} (e :: k) m. (Encryption e, MonadIO m) => FilePath -> m (Key e)
Cookie data
data CryptoCookie a Source #
Read-write access to the Wai.CryptoCookie data.
Middleware
Arguments
| :: forall a m. MonadIO m | |
| => Config a | Consider using |
| -> m (Middleware, Request -> Maybe (CryptoCookie a)) |
Construct a new Middleware, and function that can be used to look-up the
CryptoCookie on each incoming Request. Said function returns
Nothing if the Middleware was not used on the Request.
Arguments
| :: (FromJSON a, ToJSON a) | |
| => Key "AEAD_AES_256_GCM_SIV" | Consider using |
| -> Config a |
Default Config:
Encodingisaeson.Encryptionscheme is the nonce-misuse resistantAEAD_AES_256_GCM_SIVas defined in in RFC 8452.As an AEAD encryption scheme, you can be confident that a successfully decrypted cookie could only have been encrypted by the same
Key. This makes this encryption scheme suitable for storing user session authentication identifiers generated by the server.Cookie name is
SESSION.HttpOnly: yesMax-Age: 16 hoursPath:/SameSite:LaxSecure: yesDomain: not set
Configuration for middleware.
Consider using defaultConfig and
updating desired fields only.
autoKeyFileBase16 :: forall {k} (e :: k) m. (Encryption e, MonadIO m) => FilePath -> m (Key e) Source #
readKeyFileBase16 :: forall {k} (e :: k) m. (Encryption e, MonadIO m) => FilePath -> m (Key e) Source #
Read a base-16 encoded Key from a file. Ignores trailing newlines.