@@ -31,14 +31,15 @@ import Network.HTTP.Types (Status (..), hAccept, hContentType,
31 methodHead, methodPatch,
31 methodHead, methodPatch,
32 methodPost, methodPut, ok200,
32 methodPost, methodPut, ok200,
33 parseQuery)
33 parseQuery)
34−import Network.Wai (Application, Request, pathInfo,
34+import Network.Wai (Application, Request, requestHeaders, pathInfo,
35 queryString, rawQueryString,
35 queryString, rawQueryString,
36 responseBuilder, responseLBS)
36 responseBuilder, responseLBS)
37import Network.Wai.Internal (Response (ResponseBuilder))
37import Network.Wai.Internal (Response (ResponseBuilder))
38import Network.Wai.Test (defaultRequest, request,
38import Network.Wai.Test (defaultRequest, request,
39 runSession, simpleBody,
39 runSession, simpleBody,
40 simpleHeaders, simpleStatus)
40 simpleHeaders, simpleStatus)
41+import Servant.API ((:<|>) (..), (:>), AuthProtect,
41−import Servant.API ((:<|>) (..), (:>), BasicAuth, BasicAuthData(BasicAuthData),
42+ BasicAuth, BasicAuthData(BasicAuthData),
42 Capture, Delete, Get, Header (..),
43 Capture, Delete, Get, Header (..),
43 Headers, HttpVersion,
44 Headers, HttpVersion,
44 IsSecure (..), JSON,
45 IsSecure (..), JSON,
@@ -48,7 +49,7 @@ import Servant.API ((:<|>) (..), (:>), BasicAuth, Basic
48 Raw, RemoteHost, ReqBody,
49 Raw, RemoteHost, ReqBody,
49 StdMethod (..), Verb, addHeader)
50 StdMethod (..), Verb, addHeader)
50import Servant.API.Internal.Test.ComprehensiveAPI
51import Servant.API.Internal.Test.ComprehensiveAPI
51−import Servant.Server (ServantErr (..), Server, err404,
52+import Servant.Server (ServantErr (..), Server, err401, err404,
52 serve, serveWithContext, Context((:.), EmptyContext))
53 serve, serveWithContext, Context((:.), EmptyContext))
53import Test.Hspec (Spec, context, describe, it,
54import Test.Hspec (Spec, context, describe, it,
54 shouldBe, shouldContain)
55 shouldBe, shouldContain)
@@ -59,6 +60,9 @@ import Test.Hspec.Wai (get, liftIO, matchHeaders,
60import Servant.Server.Internal.BasicAuth (BasicAuthCheck(BasicAuthCheck),
61import Servant.Server.Internal.BasicAuth (BasicAuthCheck(BasicAuthCheck),
61 BasicAuthResult(Authorized,Unauthorized))
62 BasicAuthResult(Authorized,Unauthorized))
63+import Servant.Server.Experimental.Auth
64+ (AuthHandler, AuthServerData,
62import Servant.Server.Internal.RoutingApplication
66import Servant.Server.Internal.RoutingApplication
63 (toApplication, RouteResult(..))
67 (toApplication, RouteResult(..))
64import Servant.Server.Internal.Router
68import Servant.Server.Internal.Router
@@ -90,6 +94,7 @@ spec = do
90 routerSpec
94 routerSpec
91 miscCombinatorSpec
95 miscCombinatorSpec
92 basicAuthSpec
96 basicAuthSpec
94------------------------------------------------------------------------------
99------------------------------------------------------------------------------
95-- * verbSpec {{{
100-- * verbSpec {{{
@@ -534,7 +539,7 @@ miscCombinatorSpec = with (return $ serve miscApi miscServ) $
536------------------------------------------------------------------------------
541------------------------------------------------------------------------------
537−-- * Authentication {{{
542+-- * Basic Authentication {{{
538------------------------------------------------------------------------------
543------------------------------------------------------------------------------
540type BasicAuthAPI = BasicAuth "foo" () :> "basic" :> Get '[JSON] Animal
545type BasicAuthAPI = BasicAuth "foo" () :> "basic" :> Get '[JSON] Animal
@@ -564,6 +569,39 @@ basicAuthSpec = do
564 it "returns 200 with the right password" $ do
569 it "returns 200 with the right password" $ do
565 THW.request methodGet "/basic" [("Authorization","Basic c2VydmFudDpzZXJ2ZXI=")] "" `shouldRespondWith` 200
570 THW.request methodGet "/basic" [("Authorization","Basic c2VydmFudDpzZXJ2ZXI=")] "" `shouldRespondWith` 200
573+------------------------------------------------------------------------------
574+-- * General Authentication {{{
575+------------------------------------------------------------------------------
577+type GenAuthAPI = AuthProtect "auth" :> "auth" :> Get '[JSON] Animal
578+authApi :: Proxy GenAuthAPI
580+authServer :: Server GenAuthAPI
581+authServer = const (return tweety)
583+type instance AuthServerData (AuthProtect "auth") = ()
585+genAuthContext :: Context '[ AuthHandler Request () ]
587+ let authHandler = (\req ->
588+ if elem ("Auth", "secret") (requestHeaders req)
592+ in mkAuthHandler authHandler :. EmptyContext
596+ describe "Servant.API.Auth" $ do
597+ with (return (serveWithContext authApi genAuthContext authServer)) $ do
599+ context "Custom Auth Protection" $ do
600+ it "returns 401 when missing headers" $ do
601+ get "/auth" `shouldRespondWith` 401
602+ it "returns 200 with the right header" $ do
603+ THW.request methodGet "/auth" [("Auth","secret")] "" `shouldRespondWith` 200
568------------------------------------------------------------------------------
606------------------------------------------------------------------------------
569-- * Test data types {{{
607-- * Test data types {{{