Search code examples
haskellservant

Using Authentication With a Custom Reader Monad With Servant


An API protected with Basic Authentication

type SubApi = API1 :<|> API2 :<|> API3
type API = BasicAuth "foo-realm" AuthData :> SubApi

supports handlers of type AuthData -> Handler a.

I have a set of handlers:

handler1 :: Request1 -> AuthMonad Response
handler2 :: Request2 -> AuthMonad Response

That run in an AuthMonad, which is a ReaderT whose context is constructed in part from AuthData. Using enter and AuthMonad :~> Handler, I can get a Server API supporting handlers of type AuthData -> AuthMonad, but what I'd really like to do is use the AuthData argument as the environment to runReaderT.

I don't quite grok enough of the type wizardry going on with enter to understand how to do this. Any ideas?


Solution

  • Just realized I left this one hanging.

    Mostly, was just over-thinking this one -- the answer is pretty obvious. In the above case I made a function that would create the natural transformation:

    enterAuth :: AuthData -> AuthMonad :~> Handler
    

    Which I then used when constructing the ServerT:

    protectedServer :: AuthData -> ServerT ProtectedAPI Handler
    protectedServer ad = enter (enterAuth ad) protectedServer'
    

    where

    genAuthServerContext :: Context (AuthHandler Request AuthData ': '[])