module Network.Hawk.Middleware
( hawkAuth
, bewitAuth
, VerifyPayload(..)
) where
import Data.Text (Text)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Lazy.Char8 as L8
import Network.Wai
import Network.HTTP.Types (badRequest400, unauthorized401)
import Network.HTTP.Types.Header (Header, hContentType, hWWWAuthenticate)
import qualified Data.Vault.Lazy as V
import qualified Network.Hawk.Server as Hawk
import qualified Network.Hawk.Types as Hawk
data VerifyPayload = DontVerifyPayload
| VerifyPayload
deriving (Show, Eq)
hawkAuth :: Hawk.AuthReqOpts -> VerifyPayload -> Hawk.CredentialsFunc IO t -> Middleware
hawkAuth opts vp c = genHawkAuth $ \req -> do
payload <- case vp of
DontVerifyPayload -> pure Nothing
VerifyPayload -> Just <$> lazyRequestBody req
Hawk.authenticateRequest opts c req payload
bewitAuth :: Hawk.AuthReqOpts -> Hawk.CredentialsFunc IO t -> Middleware
bewitAuth opts creds = genHawkAuth $ Hawk.authenticateBewitRequest opts creds
genHawkAuth :: (Request -> IO (Hawk.AuthResult t)) -> Application -> Application
genHawkAuth auth app req respond = do
k <- V.newKey
res <- auth req
case res of
Right s -> do
let vault' = V.insert k s (vault req)
req' = req { vault = vault' }
app req' respond
Left f -> respond $ failResponse f
failResponse :: Hawk.AuthFail -> Response
failResponse f = responseLBS status [(hContentType, plain), hdr] msg
where
(status, hdr) = Hawk.header (Left f) (Just payload)
msg = L8.pack (Hawk.authFailMessage f)
plain = "text/plain"
payload = Hawk.PayloadInfo plain msg