{-# LANGUAGE DataKinds #-}
{-# LANGUAGE EmptyDataDeriving #-}
module Auth.Biscuit
(
newSecret
, toPublic
, SecretKey
, PublicKey
, serializeSecretKeyHex
, serializePublicKeyHex
, parseSecretKeyHex
, parsePublicKeyHex
, serializeSecretKey
, serializePublicKey
, parseSecretKey
, parsePublicKey
, mkBiscuit
, mkBiscuitWith
, block
, blockContext
, Biscuit
, OpenOrSealed
, Open
, Sealed
, Verified
, Unverified
, BiscuitProof
, Block
, parseB64
, parse
, parseWith
, parseBiscuitUnverified
, checkBiscuitSignatures
, BiscuitEncoding (..)
, ParserConfig (..)
, fromRevocationList
, serializeB64
, serialize
, fromHex
, addBlock
, addSignedBlock
, mkThirdPartyBlockReq
, mkThirdPartyBlockReqB64
, mkThirdPartyBlock
, mkThirdPartyBlockB64
, applyThirdPartyBlock
, applyThirdPartyBlockB64
, seal
, fromOpen
, fromSealed
, asOpen
, asSealed
, authorizer
, Authorizer
, authorizeBiscuit
, authorizeBiscuitWithLimits
, Limits (..)
, defaultLimits
, ParseError (..)
, ExecutionError (..)
, AuthorizedBiscuit (..)
, AuthorizationSuccess (..)
, MatchedQuery (..)
, getBindings
, ToTerm (..)
, FromValue (..)
, Term
, Term' (..)
, queryAuthorizerFacts
, queryRawBiscuitFacts
, getVariableValues
, getSingleVariableValue
, query
, getRevocationIds
, getVerifiedBiscuitPublicKey
) where
import Control.Monad ((<=<))
import Control.Monad.Identity (runIdentity)
import Data.Bifunctor (first)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Base16 as Hex
import qualified Data.ByteString.Base64.URL as B64
import Data.Foldable (toList)
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Text (Text, unpack)
import Auth.Biscuit.Crypto (PublicKey, SecretKey,
generateSecretKey,
pkBytes,
readEd25519PublicKey,
readEd25519SecretKey,
skBytes, toPublic)
import Auth.Biscuit.Datalog.AST (Authorizer, Block,
FromValue (..), Term,
Term' (..), ToTerm (..),
bContext)
import Auth.Biscuit.Datalog.Executor (ExecutionError (..),
Limits (..),
MatchedQuery (..),
defaultLimits)
import Auth.Biscuit.Datalog.Parser (authorizer, block, query)
import Auth.Biscuit.Datalog.ScopedExecutor (AuthorizationSuccess (..),
getBindings,
getSingleVariableValue,
getVariableValues)
import Auth.Biscuit.Token (AuthorizedBiscuit (..),
Biscuit,
BiscuitEncoding (..),
BiscuitProof (..), Open,
OpenOrSealed,
ParseError (..),
ParserConfig (..), Sealed,
Unverified, Verified,
addBlock, addSignedBlock,
applyThirdPartyBlock,
asOpen, asSealed,
authorizeBiscuit,
authorizeBiscuitWithLimits,
checkBiscuitSignatures,
fromOpen, fromSealed,
getRevocationIds,
getVerifiedBiscuitPublicKey,
mkBiscuit, mkBiscuitWith,
mkThirdPartyBlock,
mkThirdPartyBlockReq,
parseBiscuitUnverified,
parseBiscuitWith,
queryAuthorizerFacts,
queryRawBiscuitFacts,
seal, serializeBiscuit)
import qualified Data.Text as Text
blockContext :: Text -> Block
blockContext :: Text -> Block' 'Repr 'Representation
blockContext Text
c = forall a. Monoid a => a
mempty { bContext :: Maybe Text
bContext = forall a. a -> Maybe a
Just Text
c }
fromHex :: MonadFail m => ByteString -> m ByteString
fromHex :: forall (m :: * -> *). MonadFail m => ByteString -> m ByteString
fromHex = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
Text.unpack) forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either Text ByteString
Hex.decodeBase16
newSecret :: IO SecretKey
newSecret :: IO SecretKey
newSecret = IO SecretKey
generateSecretKey
serializeSecretKey :: SecretKey -> ByteString
serializeSecretKey :: SecretKey -> ByteString
serializeSecretKey = SecretKey -> ByteString
skBytes
serializePublicKey :: PublicKey -> ByteString
serializePublicKey :: PublicKey -> ByteString
serializePublicKey = PublicKey -> ByteString
pkBytes
serializeSecretKeyHex :: SecretKey -> ByteString
serializeSecretKeyHex :: SecretKey -> ByteString
serializeSecretKeyHex = ByteString -> ByteString
Hex.encodeBase16' forall b c a. (b -> c) -> (a -> b) -> a -> c
. SecretKey -> ByteString
skBytes
serializePublicKeyHex :: PublicKey -> ByteString
serializePublicKeyHex :: PublicKey -> ByteString
serializePublicKeyHex = ByteString -> ByteString
Hex.encodeBase16' forall b c a. (b -> c) -> (a -> b) -> a -> c
. PublicKey -> ByteString
pkBytes
parseSecretKey :: ByteString -> Maybe SecretKey
parseSecretKey :: ByteString -> Maybe SecretKey
parseSecretKey = ByteString -> Maybe SecretKey
readEd25519SecretKey
parseSecretKeyHex :: ByteString -> Maybe SecretKey
parseSecretKeyHex :: ByteString -> Maybe SecretKey
parseSecretKeyHex = ByteString -> Maybe SecretKey
parseSecretKey forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< forall (m :: * -> *). MonadFail m => ByteString -> m ByteString
fromHex
parsePublicKey :: ByteString -> Maybe PublicKey
parsePublicKey :: ByteString -> Maybe PublicKey
parsePublicKey = ByteString -> Maybe PublicKey
readEd25519PublicKey
parsePublicKeyHex :: ByteString -> Maybe PublicKey
parsePublicKeyHex :: ByteString -> Maybe PublicKey
parsePublicKeyHex = ByteString -> Maybe PublicKey
parsePublicKey forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< forall (m :: * -> *). MonadFail m => ByteString -> m ByteString
fromHex
parse :: PublicKey -> ByteString -> Either ParseError (Biscuit OpenOrSealed Verified)
parse :: PublicKey
-> ByteString -> Either ParseError (Biscuit OpenOrSealed Verified)
parse PublicKey
pk = forall a. Identity a -> a
runIdentity forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
Applicative m =>
ParserConfig m
-> ByteString
-> m (Either ParseError (Biscuit OpenOrSealed Verified))
parseBiscuitWith ParserConfig
{ encoding :: BiscuitEncoding
encoding = BiscuitEncoding
RawBytes
, isRevoked :: Set ByteString -> Identity Bool
isRevoked = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
, getPublicKey :: Maybe Int -> PublicKey
getPublicKey = forall (f :: * -> *) a. Applicative f => a -> f a
pure PublicKey
pk
}
parseB64 :: PublicKey -> ByteString -> Either ParseError (Biscuit OpenOrSealed Verified)
parseB64 :: PublicKey
-> ByteString -> Either ParseError (Biscuit OpenOrSealed Verified)
parseB64 PublicKey
pk = forall a. Identity a -> a
runIdentity forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
Applicative m =>
ParserConfig m
-> ByteString
-> m (Either ParseError (Biscuit OpenOrSealed Verified))
parseBiscuitWith ParserConfig
{ encoding :: BiscuitEncoding
encoding = BiscuitEncoding
UrlBase64
, isRevoked :: Set ByteString -> Identity Bool
isRevoked = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
, getPublicKey :: Maybe Int -> PublicKey
getPublicKey = forall (f :: * -> *) a. Applicative f => a -> f a
pure PublicKey
pk
}
parseWith :: Applicative m
=> ParserConfig m
-> ByteString
-> m (Either ParseError (Biscuit OpenOrSealed Verified))
parseWith :: forall (m :: * -> *).
Applicative m =>
ParserConfig m
-> ByteString
-> m (Either ParseError (Biscuit OpenOrSealed Verified))
parseWith = forall (m :: * -> *).
Applicative m =>
ParserConfig m
-> ByteString
-> m (Either ParseError (Biscuit OpenOrSealed Verified))
parseBiscuitWith
fromRevocationList :: (Applicative m, Foldable t)
=> t ByteString
-> Set ByteString
-> m Bool
fromRevocationList :: forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t ByteString -> Set ByteString -> m Bool
fromRevocationList t ByteString
revokedIds Set ByteString
tokenIds =
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall a b. (a -> b) -> a -> b
$ forall a. Ord a => Set a -> Set a -> Set a
Set.intersection (forall a. Ord a => [a] -> Set a
Set.fromList forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> [a]
toList t ByteString
revokedIds) Set ByteString
tokenIds
serialize :: BiscuitProof p => Biscuit p Verified -> ByteString
serialize :: forall p. BiscuitProof p => Biscuit p Verified -> ByteString
serialize = forall p. BiscuitProof p => Biscuit p Verified -> ByteString
serializeBiscuit
serializeB64 :: BiscuitProof p => Biscuit p Verified -> ByteString
serializeB64 :: forall p. BiscuitProof p => Biscuit p Verified -> ByteString
serializeB64 = ByteString -> ByteString
B64.encodeBase64' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall p. BiscuitProof p => Biscuit p Verified -> ByteString
serialize
mkThirdPartyBlockReqB64 :: Biscuit Open c -> ByteString
mkThirdPartyBlockReqB64 :: forall c. Biscuit Open c -> ByteString
mkThirdPartyBlockReqB64 = ByteString -> ByteString
B64.encodeBase64' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall proof check. Biscuit proof check -> ByteString
mkThirdPartyBlockReq
mkThirdPartyBlockB64 :: SecretKey -> ByteString -> Block -> Either String ByteString
mkThirdPartyBlockB64 :: SecretKey
-> ByteString
-> Block' 'Repr 'Representation
-> Either String ByteString
mkThirdPartyBlockB64 SecretKey
sk ByteString
reqB64 Block' 'Repr 'Representation
b = do
ByteString
req <- forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Text -> String
unpack forall a b. (a -> b) -> a -> b
$ ByteString -> Either Text ByteString
B64.decodeBase64 ByteString
reqB64
ByteString
contents <- SecretKey
-> ByteString
-> Block' 'Repr 'Representation
-> Either String ByteString
mkThirdPartyBlock SecretKey
sk ByteString
req Block' 'Repr 'Representation
b
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
B64.encodeBase64' ByteString
contents
applyThirdPartyBlockB64 :: Biscuit Open check -> ByteString -> Either String (IO (Biscuit Open check))
applyThirdPartyBlockB64 :: forall check.
Biscuit Open check
-> ByteString -> Either String (IO (Biscuit Open check))
applyThirdPartyBlockB64 Biscuit Open check
b ByteString
contentsB64 = do
ByteString
contents <- forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Text -> String
unpack forall a b. (a -> b) -> a -> b
$ ByteString -> Either Text ByteString
B64.decodeBase64 ByteString
contentsB64
forall check.
Biscuit Open check
-> ByteString -> Either String (IO (Biscuit Open check))
applyThirdPartyBlock Biscuit Open check
b ByteString
contents