module Authorize.Macaroon
(
MacaroonId (..)
, Macaroon
, SealedMacaroon (..)
, Key (..)
, Location
, createMacaroon
, addFirstPartyCaveat
, addThirdPartyCaveat
, extractThirdPartyCaveats
, sealMacaroon
, createDischargeMacaroon
, verify
, VerificationFailure (..)
) where
import Data.ByteString (ByteString)
import Data.List (foldl')
import Data.Maybe (isJust)
import Authorize.Macaroon.Crypto
import Authorize.Macaroon.Types
import Authorize.Macaroon.Verify
createMacaroon
:: Key
-> MacaroonId
-> Location
-> [ByteString]
-> Macaroon
createMacaroon k mid loc = foldl' addFirstPartyCaveat m0
where
m0 = Macaroon loc mid [] $ createSignature (deriveKey k) mid
addFirstPartyCaveat :: Macaroon -> ByteString -> Macaroon
addFirstPartyCaveat m = addCaveat m . Caveat mempty Nothing
addThirdPartyCaveat
:: Macaroon
-> Key
-> Location
-> ByteString
-> IO Macaroon
addThirdPartyCaveat m ck loc c
= addC <$> encryptKey (macaroonSignature m) (deriveKey ck)
where
addC k = addCaveat m $ Caveat loc (Just k) c
addCaveat :: Macaroon -> Caveat -> Macaroon
addCaveat m c@Caveat{ caveatKeyId = k, caveatContent = cc }
= m { caveats = caveats m <> [c]
, macaroonSignature = updateSignature (macaroonSignature m) k cc
}
extractThirdPartyCaveats :: Macaroon -> [ByteString]
extractThirdPartyCaveats = fmap caveatContent . filter isThirdParty . caveats
isThirdParty :: Caveat -> Bool
isThirdParty = isJust . caveatKeyId
createDischargeMacaroon
:: Key
-> Location
-> ByteString
-> [ByteString]
-> Macaroon
createDischargeMacaroon k l c = createMacaroon k (MacaroonId c) l
sealMacaroon
:: Macaroon
-> [Macaroon]
-> SealedMacaroon
sealMacaroon m@Macaroon{ macaroonSignature = s } ms
= SealedMacaroon m $ bindMacaroon <$> ms
where
bindMacaroon m'@Macaroon{ macaroonSignature = s' }
= m' { macaroonSignature = bindForRequest s s' }