1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE RankNTypes #-}
4 Module : Crypto.Macaroon.Verifier
5 Copyright : (c) 2015 Julien Tanguy
8 Maintainer : julien.tanguy@jhome.fr
9 Stability : experimental
10 Portability : portable
15 module Crypto.Macaroon.Verifier (
21 , module Data.Attoparsec.ByteString.Char8
27 import Data.Attoparsec.ByteString
28 import Data.Attoparsec.ByteString.Char8
31 import qualified Data.ByteString as BS
33 import Data.Either.Validation
37 import Data.Traversable
39 import Crypto.Macaroon.Internal
41 type Verifier = Caveat -> Maybe (Either String Caveat)
43 verifySig :: Key -> Macaroon -> Either String Macaroon
44 verifySig k m = bool (Left "Signatures do not match") (Right m) $
45 signature m == foldl' hash (toBytes (hmac derivedKey (identifier m) :: HMAC SHA256)) (caveats m)
47 hash s c = toBytes (hmac s (vid c `BS.append` cid c) :: HMAC SHA256)
48 derivedKey = toBytes (hmac "macaroons-key-generator" k :: HMAC SHA256)
50 verifyMacaroon :: Key -> [Verifier] -> Macaroon -> Either String Macaroon
51 verifyMacaroon secret verifiers m = verifySig secret m >>= verifyCavs verifiers
53 verifyCavs :: [Verifier] -> Macaroon -> Either String Macaroon
54 verifyCavs verifiers m = case partitionEithers verifiedCaveats of
56 (errs,_) -> Left (mconcat errs)
58 verifiedCaveats = map (\c -> defaultFail c $ foldMap (fmap eitherToValidation . ($c)) verifiers) $ caveats m
59 defaultFail c = maybe (Left ("No validation for this caveat: " ++ show c)) validationToEither