move BasicAuthData from servant-client to servant
This commit is contained in:
parent
738b9a8e9f
commit
459e82a8e0
7 changed files with 23 additions and 23 deletions
|
@ -17,7 +17,6 @@
|
||||||
module Servant.Client
|
module Servant.Client
|
||||||
( AuthClientData
|
( AuthClientData
|
||||||
, AuthenticateReq(..)
|
, AuthenticateReq(..)
|
||||||
, BasicAuthData(..)
|
|
||||||
, client
|
, client
|
||||||
, HasClient(..)
|
, HasClient(..)
|
||||||
, mkAuthenticateReq
|
, mkAuthenticateReq
|
||||||
|
@ -40,6 +39,7 @@ import Network.HTTP.Media
|
||||||
import qualified Network.HTTP.Types as H
|
import qualified Network.HTTP.Types as H
|
||||||
import qualified Network.HTTP.Types.Header as HTTP
|
import qualified Network.HTTP.Types.Header as HTTP
|
||||||
import Servant.API
|
import Servant.API
|
||||||
|
import Servant.API.Auth (BasicAuthData)
|
||||||
import Servant.Common.Auth
|
import Servant.Common.Auth
|
||||||
import Servant.Common.BaseUrl
|
import Servant.Common.BaseUrl
|
||||||
import Servant.Common.Req
|
import Servant.Common.Req
|
||||||
|
|
|
@ -7,22 +7,15 @@
|
||||||
module Servant.Common.Auth (
|
module Servant.Common.Auth (
|
||||||
AuthenticateReq(AuthenticateReq, unAuthReq)
|
AuthenticateReq(AuthenticateReq, unAuthReq)
|
||||||
, AuthClientData
|
, AuthClientData
|
||||||
, BasicAuthData (BasicAuthData, username, password)
|
|
||||||
, basicAuthReq
|
, basicAuthReq
|
||||||
, mkAuthenticateReq
|
, mkAuthenticateReq
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.ByteString (ByteString)
|
|
||||||
import Data.ByteString.Base64 (encode)
|
import Data.ByteString.Base64 (encode)
|
||||||
import Data.Monoid ((<>))
|
import Data.Monoid ((<>))
|
||||||
import Data.Text.Encoding (decodeUtf8)
|
import Data.Text.Encoding (decodeUtf8)
|
||||||
import Servant.Common.Req (addHeader, Req)
|
import Servant.Common.Req (addHeader, Req)
|
||||||
|
import Servant.API.Auth (BasicAuthData(BasicAuthData))
|
||||||
|
|
||||||
-- | A simple datatype to hold data required to decorate a request
|
|
||||||
data BasicAuthData = BasicAuthData { username :: ByteString
|
|
||||||
, password :: ByteString
|
|
||||||
}
|
|
||||||
|
|
||||||
-- | Authenticate a request using Basic Authentication
|
-- | Authenticate a request using Basic Authentication
|
||||||
basicAuthReq :: BasicAuthData -> Req -> Req
|
basicAuthReq :: BasicAuthData -> Req -> Req
|
||||||
|
|
|
@ -51,6 +51,7 @@ import Test.HUnit
|
||||||
import Test.QuickCheck
|
import Test.QuickCheck
|
||||||
|
|
||||||
import Servant.API
|
import Servant.API
|
||||||
|
import Servant.API.Auth (BasicAuthData(BasicAuthData))
|
||||||
import Servant.API.Internal.Test.ComprehensiveAPI
|
import Servant.API.Internal.Test.ComprehensiveAPI
|
||||||
import Servant.Client
|
import Servant.Client
|
||||||
import Servant.Server
|
import Servant.Server
|
||||||
|
@ -167,7 +168,7 @@ type instance AuthClientData (AuthProtect "auth-tag") = ()
|
||||||
|
|
||||||
basicAuthHandler :: BasicAuthCheck ()
|
basicAuthHandler :: BasicAuthCheck ()
|
||||||
basicAuthHandler =
|
basicAuthHandler =
|
||||||
let check username password =
|
let check (BasicAuthData username password) =
|
||||||
if username == "servant" && password == "server"
|
if username == "servant" && password == "server"
|
||||||
then return (Authorized ())
|
then return (Authorized ())
|
||||||
else return Unauthorized
|
else return Unauthorized
|
||||||
|
|
|
@ -14,6 +14,7 @@ import GHC.Generics (Generic)
|
||||||
import Network.Wai.Handler.Warp (run)
|
import Network.Wai.Handler.Warp (run)
|
||||||
import Servant.API ((:<|>) ((:<|>)), (:>), BasicAuth,
|
import Servant.API ((:<|>) ((:<|>)), (:>), BasicAuth,
|
||||||
Get, JSON)
|
Get, JSON)
|
||||||
|
import Servant.API.Auth (BasicAuthData(BasicAuthData))
|
||||||
import Servant.Server (AuthReturnType, BasicAuthResult (Authorized, Unauthorized), Config ((:.), EmptyConfig),
|
import Servant.Server (AuthReturnType, BasicAuthResult (Authorized, Unauthorized), Config ((:.), EmptyConfig),
|
||||||
Server, serve, BasicAuthCheck(BasicAuthCheck))
|
Server, serve, BasicAuthCheck(BasicAuthCheck))
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ type instance AuthReturnType (BasicAuth "foo-realm") = User
|
||||||
-- | 'BasicAuthCheck' holds the handler we'll use to verify a username and password.
|
-- | 'BasicAuthCheck' holds the handler we'll use to verify a username and password.
|
||||||
authCheck :: BasicAuthCheck User
|
authCheck :: BasicAuthCheck User
|
||||||
authCheck =
|
authCheck =
|
||||||
let check username password =
|
let check (BasicAuthData username password) =
|
||||||
if username == "servant" && password == "server"
|
if username == "servant" && password == "server"
|
||||||
then return (Authorized (User "servant"))
|
then return (Authorized (User "servant"))
|
||||||
else return Unauthorized
|
else return Unauthorized
|
||||||
|
|
|
@ -17,6 +17,7 @@ import GHC.Generics
|
||||||
import Network.HTTP.Types (Header)
|
import Network.HTTP.Types (Header)
|
||||||
import Network.Wai (Request, requestHeaders)
|
import Network.Wai (Request, requestHeaders)
|
||||||
|
|
||||||
|
import Servant.API.Auth (BasicAuthData(BasicAuthData))
|
||||||
import Servant.Server.Internal.RoutingApplication
|
import Servant.Server.Internal.RoutingApplication
|
||||||
import Servant.Server.Internal.ServantErr
|
import Servant.Server.Internal.ServantErr
|
||||||
|
|
||||||
|
@ -34,6 +35,8 @@ newtype AuthHandler r usr = AuthHandler
|
||||||
mkAuthHandler :: (r -> ExceptT ServantErr IO usr) -> AuthHandler r usr
|
mkAuthHandler :: (r -> ExceptT ServantErr IO usr) -> AuthHandler r usr
|
||||||
mkAuthHandler = AuthHandler
|
mkAuthHandler = AuthHandler
|
||||||
|
|
||||||
|
-- * Basic Auth
|
||||||
|
|
||||||
-- | The result of authentication/authorization
|
-- | The result of authentication/authorization
|
||||||
data BasicAuthResult usr
|
data BasicAuthResult usr
|
||||||
= Unauthorized
|
= Unauthorized
|
||||||
|
@ -42,11 +45,9 @@ data BasicAuthResult usr
|
||||||
| Authorized usr
|
| Authorized usr
|
||||||
deriving (Eq, Show, Read, Generic, Typeable, Functor)
|
deriving (Eq, Show, Read, Generic, Typeable, Functor)
|
||||||
|
|
||||||
-- * Basic Auth
|
|
||||||
|
|
||||||
newtype BasicAuthCheck usr = BasicAuthCheck
|
newtype BasicAuthCheck usr = BasicAuthCheck
|
||||||
{ unBasicAuthCheck :: BS.ByteString -- Username
|
{ unBasicAuthCheck :: BasicAuthData
|
||||||
-> BS.ByteString -- Password
|
|
||||||
-> IO (BasicAuthResult usr)
|
-> IO (BasicAuthResult usr)
|
||||||
}
|
}
|
||||||
deriving (Generic, Typeable, Functor)
|
deriving (Generic, Typeable, Functor)
|
||||||
|
@ -55,7 +56,7 @@ mkBAChallengerHdr :: BS.ByteString -> Header
|
||||||
mkBAChallengerHdr realm = ("WWW-Authenticate", "Basic realm=\"" <> realm <> "\"")
|
mkBAChallengerHdr realm = ("WWW-Authenticate", "Basic realm=\"" <> realm <> "\"")
|
||||||
|
|
||||||
-- | Find and decode an 'Authorization' header from the request as Basic Auth
|
-- | Find and decode an 'Authorization' header from the request as Basic Auth
|
||||||
decodeBAHdr :: Request -> Maybe (BS.ByteString, BS.ByteString)
|
decodeBAHdr :: Request -> Maybe BasicAuthData
|
||||||
decodeBAHdr req = do
|
decodeBAHdr req = do
|
||||||
ah <- lookup "Authorization" $ requestHeaders req
|
ah <- lookup "Authorization" $ requestHeaders req
|
||||||
let (b, rest) = BS.break isSpace ah
|
let (b, rest) = BS.break isSpace ah
|
||||||
|
@ -63,13 +64,13 @@ decodeBAHdr req = do
|
||||||
let decoded = decodeLenient (BS.dropWhile isSpace rest)
|
let decoded = decodeLenient (BS.dropWhile isSpace rest)
|
||||||
let (username, passWithColonAtHead) = BS.break (== _colon) decoded
|
let (username, passWithColonAtHead) = BS.break (== _colon) decoded
|
||||||
(_, password) <- BS.uncons passWithColonAtHead
|
(_, password) <- BS.uncons passWithColonAtHead
|
||||||
return (username, password)
|
return (BasicAuthData username password)
|
||||||
|
|
||||||
runBasicAuth :: Request -> BS.ByteString -> BasicAuthCheck usr -> IO (RouteResult usr)
|
runBasicAuth :: Request -> BS.ByteString -> BasicAuthCheck usr -> IO (RouteResult usr)
|
||||||
runBasicAuth req realm (BasicAuthCheck ba) =
|
runBasicAuth req realm (BasicAuthCheck ba) =
|
||||||
case decodeBAHdr req of
|
case decodeBAHdr req of
|
||||||
Nothing -> plzAuthenticate
|
Nothing -> plzAuthenticate
|
||||||
Just e -> uncurry ba e >>= \res -> case res of
|
Just e -> ba e >>= \res -> case res of
|
||||||
BadPassword -> plzAuthenticate
|
BadPassword -> plzAuthenticate
|
||||||
NoSuchUser -> plzAuthenticate
|
NoSuchUser -> plzAuthenticate
|
||||||
Unauthorized -> return $ Fail err403
|
Unauthorized -> return $ Fail err403
|
||||||
|
|
|
@ -33,7 +33,7 @@ import Network.HTTP.Types (Status (..), hAccept, hContentType,
|
||||||
import Network.Wai (Application, Request, requestHeaders, pathInfo,
|
import Network.Wai (Application, Request, requestHeaders, pathInfo,
|
||||||
queryString, rawQueryString,
|
queryString, rawQueryString,
|
||||||
responseBuilder, responseLBS)
|
responseBuilder, responseLBS)
|
||||||
import Network.Wai.Internal (Response (ResponseBuilder), requestHeaders)
|
import Network.Wai.Internal (Response (ResponseBuilder))
|
||||||
import Network.Wai.Test (defaultRequest, request,
|
import Network.Wai.Test (defaultRequest, request,
|
||||||
runSession, simpleBody,
|
runSession, simpleBody,
|
||||||
simpleHeaders, simpleStatus)
|
simpleHeaders, simpleStatus)
|
||||||
|
@ -55,20 +55,18 @@ import qualified Test.Hspec.Wai as THW
|
||||||
import Test.Hspec.Wai (get, liftIO, matchHeaders,
|
import Test.Hspec.Wai (get, liftIO, matchHeaders,
|
||||||
matchStatus, request,
|
matchStatus, request,
|
||||||
shouldRespondWith, with, (<:>))
|
shouldRespondWith, with, (<:>))
|
||||||
import qualified Test.Hspec.Wai as THW
|
|
||||||
|
|
||||||
|
import Servant.API.Auth (BasicAuthData(BasicAuthData))
|
||||||
import Servant.Server.Internal.Auth
|
import Servant.Server.Internal.Auth
|
||||||
(AuthHandler, AuthReturnType, BasicAuthCheck (BasicAuthCheck),
|
(AuthHandler, AuthReturnType, BasicAuthCheck (BasicAuthCheck),
|
||||||
BasicAuthResult (Authorized, Unauthorized), mkAuthHandler)
|
BasicAuthResult (Authorized, Unauthorized), mkAuthHandler)
|
||||||
|
|
||||||
import Servant.Server.Internal.Auth
|
|
||||||
import Servant.Server.Internal.RoutingApplication
|
import Servant.Server.Internal.RoutingApplication
|
||||||
(toApplication, RouteResult(..))
|
(toApplication, RouteResult(..))
|
||||||
import Servant.Server.Internal.Router
|
import Servant.Server.Internal.Router
|
||||||
(tweakResponse, runRouter,
|
(tweakResponse, runRouter,
|
||||||
Router, Router'(LeafRouter))
|
Router, Router'(LeafRouter))
|
||||||
import Servant.Server.Internal.Config
|
import Servant.Server.Internal.Config
|
||||||
(Config(..), NamedConfig(..))
|
(NamedConfig(NamedConfig))
|
||||||
|
|
||||||
-- * comprehensive api test
|
-- * comprehensive api test
|
||||||
|
|
||||||
|
@ -554,7 +552,7 @@ authConfig :: Config '[ BasicAuthCheck ()
|
||||||
, AuthHandler Request ()
|
, AuthHandler Request ()
|
||||||
]
|
]
|
||||||
authConfig =
|
authConfig =
|
||||||
let basicHandler = BasicAuthCheck $ (\usr pass ->
|
let basicHandler = BasicAuthCheck $ (\(BasicAuthData usr pass) ->
|
||||||
if usr == "servant" && pass == "server"
|
if usr == "servant" && pass == "server"
|
||||||
then return (Authorized ())
|
then return (Authorized ())
|
||||||
else return Unauthorized
|
else return Unauthorized
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
{-# LANGUAGE PolyKinds #-}
|
{-# LANGUAGE PolyKinds #-}
|
||||||
module Servant.API.Auth where
|
module Servant.API.Auth where
|
||||||
|
|
||||||
|
import Data.ByteString (ByteString)
|
||||||
import Data.Typeable (Typeable)
|
import Data.Typeable (Typeable)
|
||||||
import GHC.TypeLits (Symbol)
|
import GHC.TypeLits (Symbol)
|
||||||
|
|
||||||
|
@ -20,6 +21,11 @@ import GHC.TypeLits (Symbol)
|
||||||
data BasicAuth (realm :: Symbol)
|
data BasicAuth (realm :: Symbol)
|
||||||
deriving (Typeable)
|
deriving (Typeable)
|
||||||
|
|
||||||
|
-- | A simple datatype to hold data required to decorate a request
|
||||||
|
data BasicAuthData = BasicAuthData { basicAuthUsername :: !ByteString
|
||||||
|
, basicAuthPassword :: !ByteString
|
||||||
|
}
|
||||||
|
|
||||||
-- | A generalized Authentication combinator.
|
-- | A generalized Authentication combinator.
|
||||||
data AuthProtect (tag :: k)
|
data AuthProtect (tag :: k)
|
||||||
deriving (Typeable)
|
deriving (Typeable)
|
||||||
|
|
Loading…
Reference in a new issue