diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-import Distribution.Simple
-main = defaultMain
diff --git a/Snap/Snaplet/CustomAuth.hs b/Snap/Snaplet/CustomAuth.hs
--- a/Snap/Snaplet/CustomAuth.hs
+++ b/Snap/Snaplet/CustomAuth.hs
@@ -10,7 +10,7 @@
   , UserData(..)
   , defAuthSettings
   , authName
-  , authSetCookie
+  , authCookieLifetime
   , createAccount
   , loginUser
   , logoutUser
diff --git a/Snap/Snaplet/CustomAuth/AuthManager.hs b/Snap/Snaplet/CustomAuth/AuthManager.hs
--- a/Snap/Snaplet/CustomAuth/AuthManager.hs
+++ b/Snap/Snaplet/CustomAuth/AuthManager.hs
@@ -17,6 +17,7 @@
 import Data.ByteString (ByteString)
 import Data.HashMap.Lazy (HashMap)
 import Data.Text (Text)
+import Data.Time.Clock (NominalDiffTime)
 import Network.HTTP.Client (Manager)
 
 import Snap.Core
@@ -43,7 +44,7 @@
 
 data AuthManager u e b = forall i. IAuthBackend u i e b => AuthManager
   { activeUser :: UserData u => Maybe u
-  , setCookie :: ByteString -> Cookie
+  , cookieLifetime :: Maybe NominalDiffTime
   , sessionCookieName :: ByteString
   , userField :: ByteString
   , passwordField :: ByteString
diff --git a/Snap/Snaplet/CustomAuth/Handlers.hs b/Snap/Snaplet/CustomAuth/Handlers.hs
--- a/Snap/Snaplet/CustomAuth/Handlers.hs
+++ b/Snap/Snaplet/CustomAuth/Handlers.hs
@@ -131,7 +131,7 @@
   ps <- maybe (return M.empty) oauth2Init oa
   return $ AuthManager
     { activeUser = Nothing
-    , setCookie = s ^. authSetCookie
+    , cookieLifetime = s ^. authCookieLifetime
     , sessionCookieName = scn
     , userField = un
     , passwordField = pn
diff --git a/Snap/Snaplet/CustomAuth/OAuth2/Internal.hs b/Snap/Snaplet/CustomAuth/OAuth2/Internal.hs
--- a/Snap/Snaplet/CustomAuth/OAuth2/Internal.hs
+++ b/Snap/Snaplet/CustomAuth/OAuth2/Internal.hs
@@ -19,9 +19,9 @@
 import Data.Aeson
 import qualified Data.Binary
 import Data.Binary (Binary)
-import Data.Binary.Orphans ()
+import Data.Binary.Instances ()
 import qualified Data.ByteString.Base64
-import Data.ByteString.Lazy (toStrict, fromStrict)
+import Data.ByteString.Lazy (ByteString, toStrict, fromStrict)
 import Data.Char (chr)
 import qualified Data.Configurator as C
 import Data.HashMap.Lazy (HashMap)
@@ -53,7 +53,7 @@
   cfg <- getSnapletUserConfig
   root <- getSnapletRootURL
   hostname <- liftIO $ C.require cfg "hostname"
-  scheme <- liftIO $ C.lookupDefault "http" cfg "protocol"
+  scheme <- liftIO $ C.lookupDefault "https" cfg "protocol"
   names <- liftIO $ C.lookupDefault [] cfg "oauth2.providers"
   -- TODO: use discovery
   let makeProvider name = let
@@ -73,7 +73,7 @@
            <*> lk ".identityField"
            <*> (OAuth2
                 <$> lk ".clientId"
-                <*> lk ".clientSecret"
+                <*> (lift $ runMaybeT $ lk ".clientSecret")
                 <*> lku ".endpoint.auth"
                 <*> lku ".endpoint.access"
                 <*> (pure $ Just callback))
@@ -132,24 +132,20 @@
   redirect' redirUrl 303
 
 getUserInfo
-  :: OAuth2Settings u i e b
+  :: MonadIO m
+  => Manager
   -> Provider
   -> AccessToken
-  -> Handler b (AuthManager u e b) (Maybe Text)
-getUserInfo s provider token = do
+  -> ExceptT (Maybe ByteString) m Text
+getUserInfo mgr provider token = do
   let endpoint = identityEndpoint provider
-  let mgr = httpManager s
-  liftIO $ runMaybeT $ do
-    dat <- MaybeT $ hush <$> authGetJSON' mgr token endpoint
-    MaybeT . return $ lookupProviderInfo dat
+  (withExceptT Just $ ExceptT $ liftIO $ authGetJSON mgr token endpoint) >>=
+    (maybe (throwE Nothing) pure . lookupProviderInfo)
   where
-    authGetJSON' :: Manager -> AccessToken -> URI
-                 -> IO (OAuth2Result (HashMap Text Value) (HashMap Text Value))
-    authGetJSON' = authGetJSON
     lookup' a b = maybeText =<< M.lookup a b
     maybeText (String x) = Just x
     maybeText _ = Nothing
-    lookupProviderInfo dat = lookup' (identityField provider) dat
+    lookupProviderInfo = lookup' (identityField provider)
 
 oauth2Callback
   :: IAuthBackend u i e b
@@ -184,14 +180,15 @@
       err <- MaybeT $ lift $ getParam "error"
       lift $ throwE $ ProviderError $ hush $ decodeUtf8' err
     -- Get the user id from provider
-    (maybe (throwE IdExtractionFailed) return =<<) $ runMaybeT $ do
-      code <- MaybeT $ (fmap ExchangeToken) <$> (lift $ getParamText "code")
-      -- TODO: catch?
-      token <- either (const $ lift $ throwE AccessTokenFetchError) return =<< liftIO
-        (fetchAccessToken mgr param code)
+    (maybe (throwE (IdExtractionFailed Nothing)) pure =<<
+      (fmap ExchangeToken) <$> (lift $ getParamText "code")) >>=
+    -- TODO: catch?
+      (liftIO . fetchAccessToken mgr param >=>
+       either (const $ throwE AccessTokenFetchError) pure >=>
       -- TODO: get user id (sub) from idToken in token, if
       -- available. Requires JWT handling.
-      MaybeT $ lift $ getUserInfo s provider (accessToken token)
+       withExceptT (IdExtractionFailed . ((hush . decodeUtf8' . toStrict) =<<)) .
+        getUserInfo (httpManager s) provider . accessToken)
   either (setFailure ((oauth2Failure s) SCallback) (Just $ providerName provider) .
           Right . Create . OAuth2Failure)
     (oauth2Success s provider) res
diff --git a/Snap/Snaplet/CustomAuth/Types.hs b/Snap/Snaplet/CustomAuth/Types.hs
--- a/Snap/Snaplet/CustomAuth/Types.hs
+++ b/Snap/Snaplet/CustomAuth/Types.hs
@@ -6,10 +6,10 @@
 
 import Control.Lens.TH
 import Data.Binary
-import Data.Binary.Orphans ()
+import Data.Binary.Instances ()
 import Data.ByteString
 import Data.Text (Text)
-import Data.Time.Clock (UTCTime)
+import Data.Time.Clock (UTCTime, NominalDiffTime)
 import GHC.Generics (Generic)
 import Network.OAuth.OAuth2 (OAuth2)
 import URI.ByteString (URI)
@@ -36,7 +36,7 @@
 
 data OAuth2Failure =
     StateNotStored | StateNotReceived | ExpiredState | BadState
-  | ConfigurationError | IdExtractionFailed | NoStoredToken
+  | ConfigurationError | IdExtractionFailed (Maybe Text) | NoStoredToken
   | AlreadyUser | AlreadyLoggedIn
   | IdentityInUse
   | ProviderError (Maybe Text)
@@ -68,8 +68,8 @@
   { actionProvider :: Text
   , actionStamp :: UTCTime
   , actionUser :: Maybe ByteString
-  -- Is the action expected to match with an ID attached to the user.
-  -- Use False if using the action to attach a new ID.
+  -- | Is the action expected to match with an ID attached to the
+  -- user.  Use False if using the action to attach a new ID.
   , requireUser :: Bool
   , savedAction :: ByteString
   } deriving (Generic)
@@ -84,11 +84,10 @@
 
 data AuthSettings = AuthSettings
   { _authName :: Text
-  , _authSetCookie :: ByteString -> Cookie
+  , _authCookieLifetime :: Maybe NominalDiffTime
   }
 
 makeLenses ''AuthSettings
 
 defAuthSettings :: AuthSettings
-defAuthSettings = AuthSettings "auth" $ \x ->
-  Cookie "_session" x Nothing Nothing (Just "/") False True
+defAuthSettings = AuthSettings "auth" Nothing
diff --git a/Snap/Snaplet/CustomAuth/User.hs b/Snap/Snaplet/CustomAuth/User.hs
--- a/Snap/Snaplet/CustomAuth/User.hs
+++ b/Snap/Snaplet/CustomAuth/User.hs
@@ -1,13 +1,19 @@
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeApplications #-}
 
 module Snap.Snaplet.CustomAuth.User where
 
 import Control.Error.Util
 import Control.Monad.State
 import Control.Monad.Trans.Maybe
+import Data.ByteString (ByteString)
+import Data.ByteString.Lazy (toStrict)
+import qualified Data.Configurator as C
 import Data.Maybe
 import Data.Text.Encoding
+import Data.Time.Clock (addUTCTime, getCurrentTime)
 import Snap
+import qualified Text.Show.ByteString
 
 import Snap.Snaplet.CustomAuth.Types (AuthUser(..))
 import Snap.Snaplet.CustomAuth.AuthManager
@@ -17,11 +23,17 @@
   => u
   -> Handler b (AuthManager u e b) ()
 setUser usr = do
-  setter <- gets setCookie
+  cfg <- getSnapletUserConfig
+  secure <- fmap (== "https") $ liftIO $ C.lookupDefault ("https" :: ByteString) cfg "protocol"
   let udata = extractUser usr
-  -- TODO
-  let wafer = setter $ session udata
-  modifyResponse $ addResponseCookie wafer
+  (name, lifetime) <- gets ((,) <$> sessionCookieName <*> cookieLifetime)
+  modifyResponse $ addHeader "Set-Cookie" $
+    name <> "=" <> session udata <>
+    (maybe "" (("; Max-Age=" <>) . toStrict . Text.Show.ByteString.show @Int . floor) lifetime) <>
+    "; Path=/" <>
+    (if secure then "; Secure" else "") <>
+    "; HttpOnly" <>
+    "; SameSite=Lax"
   modify $ \mgr -> mgr { activeUser = Just usr }
 
 currentUser :: UserData u => Handler b (AuthManager u e b) (Maybe u)
diff --git a/snaplet-customauth.cabal b/snaplet-customauth.cabal
--- a/snaplet-customauth.cabal
+++ b/snaplet-customauth.cabal
@@ -1,5 +1,5 @@
 Name:                snaplet-customauth
-Version:             0.1.2
+Version:             0.2
 Synopsis:            Alternate authentication snaplet
 Description:         More customizable authentication snaplet with OAuth2 support
 License:             BSD3
@@ -9,13 +9,14 @@
 Stability:           Experimental
 Category:            Web
 Build-type:          Simple
-Cabal-version:       >=1.6
+Cabal-version:       >=1.10
 
 source-repository head
   type: git
   location: https://github.com/kaol/snaplet-customauth
 
 library
+  default-language:    Haskell2010
   exposed-modules:
     Snap.Snaplet.CustomAuth,
     Snap.Snaplet.CustomAuth.OAuth2
@@ -32,9 +33,10 @@
 
   Build-depends:
     base                      >= 4.4     && < 5,
-    lens                      >= 3.7.6   && < 4.17,
+    lens                      >= 3.7.6   && < 4.20,
     bytestring                >= 0.9.1   && < 0.11,
     base64-bytestring         >= 1.0.0.1 && < 1.1,
+    bytestring-show           >= 0.3.5.6 && < 0.4,
     heist                     >= 1.0.1   && < 1.2,
     mtl                       >= 2       && < 3,
     transformers              >= 0.4     && < 0.6,
@@ -43,16 +45,16 @@
     snap-core                 >= 1.0     && < 1.1,
     configurator              >= 0.3     && < 0.4,
     text                      >= 0.11    && < 1.3,
-    time                      >= 1.1     && < 1.7,
+    time                      >= 1.1     && < 1.12,
     xmlhtml                   >= 0.1     && < 0.3,
     binary                    >= 0.8.5   && < 0.9,
-    binary-orphans            >= 0.1.7   && < 0.2,
-    hoauth2                   >= 1.7.0   && < 1.8.0,
-    http-client               >= 0.5.7   && < 0.6,
+    binary-instances          >= 1       && < 2,
+    hoauth2                   >= 1.11.0  && < 1.17.0,
+    http-client               >= 0.5.7   && < 0.7,
     http-client-tls           >= 0.3.5   && < 0.4,
     containers                >= 0.5.6   && < 0.6,
     unordered-containers      >= 0.2.7.1 && < 0.3,
-    aeson                     >= 1.2     && < 1.4,
+    aeson                     >= 1.2     && < 1.6,
     uri-bytestring            >= 0.2.3   && < 0.4,
     map-syntax                >= 0.2     && < 0.4,
     random                    >= 1.1     && < 1.2
