From 484eb0862def172ba405c78f5617e430aaaa1821 Mon Sep 17 00:00:00 2001 From: Andrey Prokopenko Date: Tue, 5 Nov 2019 20:41:46 +0300 Subject: [PATCH 1/2] Bump upper boundaries, replace ServantErr with ServerError --- servant-auth-cookie.cabal | 17 +-- .../Server/Experimental/Auth/Cookie.hs | 131 +++++++++--------- stack.yaml | 2 +- 3 files changed, 76 insertions(+), 74 deletions(-) diff --git a/servant-auth-cookie.cabal b/servant-auth-cookie.cabal index 8fbf0d4..5682b12 100644 --- a/servant-auth-cookie.cabal +++ b/servant-auth-cookie.cabal @@ -47,19 +47,20 @@ library build-depends: base >= 4.7 && < 5.0 , base64-bytestring - , blaze-builder >= 0.4 && < 0.4.1 + , blaze-builder >= 0.4 && < 0.6 , bytestring , cereal >= 0.5 && < 0.6 , cereal-time >= 0.1 && < 0.2 , cookie >= 0.4.1 && < 0.5 - , cryptonite >= 0.14 && < 0.25 + , cryptonite >= 0.14 && < 0.26 , data-default - , exceptions >= 0.8 && < 0.9 - , http-types >= 0.9 && < 0.12 + , http-api-data >=0.3.0 && < 0.5 + , exceptions >= 0.8 && < 0.11 + , http-types >= 0.9 && < 0.13 , memory >= 0.11 && < 0.15 , mtl >= 2.0 && < 3.0 - , servant >= 0.5 && < 0.13 - , servant-server >= 0.5 && < 0.13 + , servant >= 0.5 && < 0.17 + , servant-server >= 0.5 && < 0.17 , tagged == 0.8.* , text , time >= 1.6 && < 1.8.1 @@ -76,12 +77,12 @@ library if flag(servant9) build-depends: servant >= 0.9, - http-api-data == 0.3.* + http-api-data < 0.5 else if flag(servant91) build-depends: servant >= 0.9, - http-api-data == 0.3.* + http-api-data < 0.5 else build-depends: servant < 0.9, diff --git a/src/Servant/Server/Experimental/Auth/Cookie.hs b/src/Servant/Server/Experimental/Auth/Cookie.hs index e66104c..4a0153e 100644 --- a/src/Servant/Server/Experimental/Auth/Cookie.hs +++ b/src/Servant/Server/Experimental/Auth/Cookie.hs @@ -12,21 +12,21 @@ paper \"A Secure Cookie Protocol\" by Alex Liu et al. -} -{-# LANGUAGE CPP #-} -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE DeriveDataTypeable #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE KindSignatures #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TupleSections #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TupleSections #-} +{-# LANGUAGE TypeFamilies #-} module Servant.Server.Experimental.Auth.Cookie @@ -108,67 +108,68 @@ module Servant.Server.Experimental.Auth.Cookie , applyCipherAlgorithm ) where -import Blaze.ByteString.Builder (toByteString) -import Control.Arrow ((&&&), first) -import Control.Monad -import Control.Monad.Catch (MonadThrow (..), Exception) -import Control.Monad.Except -import Crypto.Cipher.AES (AES256) -import Crypto.Cipher.Types -import Crypto.Error -import Crypto.Hash (HashAlgorithm(..)) -import Crypto.Hash.Algorithms (SHA256) -import Crypto.MAC.HMAC (HMAC) -import Crypto.Random (DRG(..), drgNew) -import Data.ByteString (ByteString) -import Data.Default -import Data.IORef -import Data.List (partition) -import Data.Maybe (listToMaybe) -import Data.Monoid ((<>)) -import Data.Proxy -import Data.Serialize (Serialize(..)) -import Data.Tagged (Tagged (..), retag) -import Data.Time -import Data.Time.Clock.Serialize () -import Data.Typeable -import GHC.Generics (Generic) -import GHC.TypeLits (Symbol) -import Network.HTTP.Types (hCookie, HeaderName, RequestHeaders, ResponseHeaders) -import Network.Wai (Request, requestHeaders) -import Servant (addHeader, ServantErr (..)) -import Servant.API.Experimental.Auth (AuthProtect) -import Servant.API.ResponseHeaders (AddHeader) -import Servant.Server (err403) -import Servant.Server.Experimental.Auth -import Web.Cookie -import qualified Crypto.MAC.HMAC as H -import qualified Data.ByteArray as BA -import qualified Data.ByteString as BS -import qualified Data.ByteString.Base64 as Base64 -import qualified Data.ByteString.Char8 as BSC8 -import qualified Data.Serialize as Serialize (encode, decode) -import qualified Network.HTTP.Types as N(Header) +import Blaze.ByteString.Builder (toByteString) +import Control.Arrow (first, (&&&)) +import Control.Monad +import Control.Monad.Catch (Exception, MonadThrow (..)) +import Control.Monad.Except +import Crypto.Cipher.AES (AES256) +import Crypto.Cipher.Types +import Crypto.Error +import Crypto.Hash (HashAlgorithm (..)) +import Crypto.Hash.Algorithms (SHA256) +import Crypto.MAC.HMAC (HMAC) +import qualified Crypto.MAC.HMAC as H +import Crypto.Random (DRG (..), drgNew) +import qualified Data.ByteArray as BA +import Data.ByteString (ByteString) +import qualified Data.ByteString as BS +import qualified Data.ByteString.Base64 as Base64 +import qualified Data.ByteString.Char8 as BSC8 +import Data.Default +import Data.IORef +import Data.List (partition) +import Data.Maybe (listToMaybe) +import Data.Monoid ((<>)) +import Data.Proxy +import Data.Serialize (Serialize (..)) +import qualified Data.Serialize as Serialize (decode, encode) +import Data.Tagged (Tagged (..), retag) +import Data.Time +import Data.Time.Clock.Serialize () +import Data.Typeable +import GHC.Generics (Generic) +import GHC.TypeLits (Symbol) +import Network.HTTP.Types (HeaderName, RequestHeaders, + ResponseHeaders, hCookie) +import qualified Network.HTTP.Types as N (Header) +import Network.Wai (Request, requestHeaders) +import Servant (addHeader) +import Servant.API.Experimental.Auth (AuthProtect) +import Servant.API.ResponseHeaders (AddHeader) +import Servant.Server (ServerError (..), err403) +import Servant.Server.Experimental.Auth +import Web.Cookie #if !MIN_VERSION_base(4,8,0) -import Control.Applicative +import Control.Applicative #endif #if MIN_VERSION_servant(0,9,0) -import Servant (ToHttpApiData (..)) -import Data.Text (Text) +import Data.Text (Text) +import Servant (ToHttpApiData (..)) #else -import Data.ByteString.Conversion (ToByteString (..)) +import Data.ByteString.Conversion (ToByteString (..)) #endif #if MIN_VERSION_servant(0,9,1) -import Servant (noHeader) -import Servant.API.ResponseHeaders (Headers) -import qualified Servant.API.Header as S(Header) +import Servant (noHeader) +import qualified Servant.API.Header as S (Header) +import Servant.API.ResponseHeaders (Headers) #endif #if MIN_VERSION_http_types(0,10,0) -import Network.HTTP.Types.Header (hSetCookie) +import Network.HTTP.Types.Header (hSetCookie) #endif #if MIN_VERSION_http_types(0,10,0) @@ -622,14 +623,14 @@ removeSession acs response = -- | Add cookie session to error allowing to set cookie even if response is -- not 200. -addSessionToErr :: AddSession ServantErr ServantErr +addSessionToErr :: AddSession ServerError ServerError addSessionToErr acs rs sk pwSettings pwSession err = do header <- renderSession acs rs sk pwSettings pwSession () return err { errHeaders = (hSetCookie, header) : errHeaders err } -- | "Remove" a session by invalidating the cookie. -- Cookie expiry date is set at 0 and content is wiped -removeSessionFromErr :: RemoveSession ServantErr ServantErr +removeSessionFromErr :: RemoveSession ServerError ServerError removeSessionFromErr acs err = return $ err { errHeaders = (hSetCookie, renderExpiredSession acs) : errHeaders err } diff --git a/stack.yaml b/stack.yaml index 35adf15..0f42f53 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: lts-8.9 +resolver: lts-14.2 packages: - '.' extra-deps: From 712033df0384c08df59defbc8af60d1f0a28ce04 Mon Sep 17 00:00:00 2001 From: Andrey Prokopenko Date: Wed, 6 Nov 2019 00:28:42 +0300 Subject: [PATCH 2/2] Add FromHttpApiData instance for EncryptedSession --- src/Servant/Server/Experimental/Auth/Cookie.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Servant/Server/Experimental/Auth/Cookie.hs b/src/Servant/Server/Experimental/Auth/Cookie.hs index 4a0153e..8ab3029 100644 --- a/src/Servant/Server/Experimental/Auth/Cookie.hs +++ b/src/Servant/Server/Experimental/Auth/Cookie.hs @@ -126,6 +126,7 @@ import Data.ByteString (ByteString) import qualified Data.ByteString as BS import qualified Data.ByteString.Base64 as Base64 import qualified Data.ByteString.Char8 as BSC8 +import Data.Coerce (coerce) import Data.Default import Data.IORef import Data.List (partition) @@ -150,6 +151,7 @@ import Servant.API.ResponseHeaders (AddHeader) import Servant.Server (ServerError (..), err403) import Servant.Server.Experimental.Auth import Web.Cookie +import Web.HttpApiData #if !MIN_VERSION_base(4,8,0) import Control.Applicative @@ -157,6 +159,7 @@ import Control.Applicative #if MIN_VERSION_servant(0,9,0) import Data.Text (Text) +import Data.Text.Encoding (encodeUtf8) import Servant (ToHttpApiData (..)) #else import Data.ByteString.Conversion (ToByteString (..)) @@ -252,6 +255,9 @@ instance Serialize Cookie where newtype EncryptedSession = EncryptedSession ByteString deriving (Eq, Show, Typeable) +instance FromHttpApiData EncryptedSession where + parseUrlPiece = pure . coerce . encodeUtf8 + -- | An empty 'EncryptedSession' emptyEncryptedSession :: EncryptedSession emptyEncryptedSession = EncryptedSession ""