-- Copyright (C) 2016, 2017  Fraser Tweedale
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.

{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}

{-|

Types and functions for working with JOSE header parameters.

-}
module Crypto.JOSE.Header
  (
  -- * Defining header data types
    HeaderParam(..)
  , ProtectionIndicator(..)
  , Protection(..)
  , protection
  , isProtected
  , param

  -- * Defining header parsers
  -- $parsing
  , HasParams(..)
  , headerRequired
  , headerRequiredProtected
  , headerOptional
  , headerOptional'
  , headerOptionalProtected

  -- * Parsing headers
  , parseParams
  , parseCrit

  -- * Encoding headers
  , protectedParamsEncoded
  , unprotectedParams


  -- * Header fields shared by JWS and JWE
  , HasAlg(..)
  , HasJku(..)
  , HasJwk(..)
  , HasKid(..)
  , HasX5u(..)
  , HasX5c(..)
  , HasX5t(..)
  , HasX5tS256(..)
  , HasTyp(..)
  , HasCty(..)
  , HasCrit(..)
  ) where


import qualified Control.Monad.Fail as Fail
import Data.Kind (Type)
import Data.List.NonEmpty (NonEmpty)
import Data.Monoid ((<>))
import Data.Proxy (Proxy(..))

import Control.Lens (Lens', Getter, review, to)
import Data.Aeson (FromJSON(..), Object, Value, encode, object)
import Data.Aeson.Types (Pair, Parser)
import qualified Data.Aeson.Key as Key
import qualified Data.Aeson.KeyMap as M
import qualified Data.ByteString.Lazy as L
import qualified Data.Text as T

import qualified Crypto.JOSE.JWA.JWS as JWA.JWS
import Crypto.JOSE.JWK (JWK)
import Crypto.JOSE.Types.Internal (base64url)
import qualified Crypto.JOSE.Types as Types


-- | A thing with parameters.
--
class HasParams (a :: Type -> Type) where
  -- | Return a list of parameters,
  -- each paired with whether it is protected or not.
  params :: ProtectionIndicator p => a p -> [(Bool, Pair)]

  -- | List of "known extensions", i.e. keys that may appear in the
  -- "crit" header parameter.
  extensions :: Proxy a -> [T.Text]
  extensions = forall a b. a -> b -> a
const []

  parseParamsFor
    :: (HasParams b, ProtectionIndicator p)
    => Proxy b -> Maybe Object -> Maybe Object -> Parser (a p)

-- | Parse a pair of objects (protected and unprotected header)
--
-- This internally invokes 'parseParamsFor' applied to a proxy for
-- the target type.  (This allows the parsing of the "crit" parameter
-- to access "known extensions" understood by the target type.)
--
parseParams
  :: forall a p. (HasParams a, ProtectionIndicator p)
  => Maybe Object -- ^ protected header
  -> Maybe Object -- ^ unprotected header
  -> Parser (a p)
parseParams :: forall (a :: * -> *) p.
(HasParams a, ProtectionIndicator p) =>
Maybe Object -> Maybe Object -> Parser (a p)
parseParams = forall (a :: * -> *) (b :: * -> *) p.
(HasParams a, HasParams b, ProtectionIndicator p) =>
Proxy b -> Maybe Object -> Maybe Object -> Parser (a p)
parseParamsFor (forall {k} (t :: k). Proxy t
Proxy :: Proxy a)

protectedParams
  :: (HasParams a, ProtectionIndicator p)
  => a p -> Maybe Value {- ^ Object -}
protectedParams :: forall (a :: * -> *) p.
(HasParams a, ProtectionIndicator p) =>
a p -> Maybe Value
protectedParams a p
h =
  case (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (a :: * -> *) p.
(HasParams a, ProtectionIndicator p) =>
a p -> [(Bool, Pair)]
params) a p
h of
    [] -> forall a. Maybe a
Nothing
    [Pair]
xs -> forall a. a -> Maybe a
Just ([Pair] -> Value
object [Pair]
xs)

-- | Return the base64url-encoded protected parameters
--
protectedParamsEncoded
  :: (HasParams a, ProtectionIndicator p)
  => a p -> L.ByteString
protectedParamsEncoded :: forall (a :: * -> *) p.
(HasParams a, ProtectionIndicator p) =>
a p -> ByteString
protectedParamsEncoded =
  forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. Monoid a => a
mempty (forall b (m :: * -> *) t. MonadReader b m => AReview t b -> m t
review forall s1 s2.
(AsEmpty s1, AsEmpty s2, Cons s1 s1 Word8 Word8,
 Cons s2 s2 Word8 Word8) =>
Prism' s1 s2
base64url forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToJSON a => a -> ByteString
encode) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (a :: * -> *) p.
(HasParams a, ProtectionIndicator p) =>
a p -> Maybe Value
protectedParams

-- | Return unprotected params as a JSON 'Value' (always an object)
--
unprotectedParams
  :: (HasParams a, ProtectionIndicator p)
  => a p -> Maybe Value {- ^ Object -}
unprotectedParams :: forall (a :: * -> *) p.
(HasParams a, ProtectionIndicator p) =>
a p -> Maybe Value
unprotectedParams a p
h =
  case (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (a :: * -> *) p.
(HasParams a, ProtectionIndicator p) =>
a p -> [(Bool, Pair)]
params) a p
h of
    [] -> forall a. Maybe a
Nothing
    [Pair]
xs -> forall a. a -> Maybe a
Just ([Pair] -> Value
object [Pair]
xs)

-- | Whether a header is protected or unprotected
--
data Protection = Protected | Unprotected
  deriving (Protection -> Protection -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Protection -> Protection -> Bool
$c/= :: Protection -> Protection -> Bool
== :: Protection -> Protection -> Bool
$c== :: Protection -> Protection -> Bool
Eq, Int -> Protection -> ShowS
[Protection] -> ShowS
Protection -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Protection] -> ShowS
$cshowList :: [Protection] -> ShowS
show :: Protection -> String
$cshow :: Protection -> String
showsPrec :: Int -> Protection -> ShowS
$cshowsPrec :: Int -> Protection -> ShowS
Show)

class Eq a => ProtectionIndicator a where
  -- | Get a value for indicating protection.
  getProtected :: a

  -- | Get a 'Just' a value for indicating no protection, or 'Nothing'
  -- if the type does not support unprotected headers.
  getUnprotected :: Maybe a

instance ProtectionIndicator Protection where
  getProtected :: Protection
getProtected = Protection
Protected
  getUnprotected :: Maybe Protection
getUnprotected = forall a. a -> Maybe a
Just Protection
Unprotected

instance ProtectionIndicator () where
  getProtected :: ()
getProtected = ()
  getUnprotected :: Maybe ()
getUnprotected = forall a. Maybe a
Nothing


-- | A header value, along with a protection indicator.
--
data HeaderParam p a = HeaderParam p a
  deriving (HeaderParam p a -> HeaderParam p a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall p a.
(Eq p, Eq a) =>
HeaderParam p a -> HeaderParam p a -> Bool
/= :: HeaderParam p a -> HeaderParam p a -> Bool
$c/= :: forall p a.
(Eq p, Eq a) =>
HeaderParam p a -> HeaderParam p a -> Bool
== :: HeaderParam p a -> HeaderParam p a -> Bool
$c== :: forall p a.
(Eq p, Eq a) =>
HeaderParam p a -> HeaderParam p a -> Bool
Eq, Int -> HeaderParam p a -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall p a. (Show p, Show a) => Int -> HeaderParam p a -> ShowS
forall p a. (Show p, Show a) => [HeaderParam p a] -> ShowS
forall p a. (Show p, Show a) => HeaderParam p a -> String
showList :: [HeaderParam p a] -> ShowS
$cshowList :: forall p a. (Show p, Show a) => [HeaderParam p a] -> ShowS
show :: HeaderParam p a -> String
$cshow :: forall p a. (Show p, Show a) => HeaderParam p a -> String
showsPrec :: Int -> HeaderParam p a -> ShowS
$cshowsPrec :: forall p a. (Show p, Show a) => Int -> HeaderParam p a -> ShowS
Show)

instance Functor (HeaderParam p) where
  fmap :: forall a b. (a -> b) -> HeaderParam p a -> HeaderParam p b
fmap a -> b
f (HeaderParam p
p a
a) = forall p a. p -> a -> HeaderParam p a
HeaderParam p
p (a -> b
f a
a)

-- | Lens for the 'Protection' of a 'HeaderParam'
protection :: Lens' (HeaderParam p a) p
protection :: forall p a. Lens' (HeaderParam p a) p
protection p -> f p
f (HeaderParam p
p a
v) = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\p
p' -> forall p a. p -> a -> HeaderParam p a
HeaderParam p
p' a
v) (p -> f p
f p
p)
{-# ANN protection "HLint: ignore Avoid lambda using `infix`" #-}

-- | Lens for a 'HeaderParam' value
param :: Lens' (HeaderParam p a) a
param :: forall p a. Lens' (HeaderParam p a) a
param a -> f a
f (HeaderParam p
p a
v) = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\a
v' -> forall p a. p -> a -> HeaderParam p a
HeaderParam p
p a
v') (a -> f a
f a
v)
{-# ANN param "HLint: ignore Avoid lambda" #-}

-- | Getter for whether a parameter is protected
isProtected :: (ProtectionIndicator p) => Getter (HeaderParam p a) Bool
isProtected :: forall p a. ProtectionIndicator p => Getter (HeaderParam p a) Bool
isProtected = forall p a. Lens' (HeaderParam p a) p
protection forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to (forall a. Eq a => a -> a -> Bool
== forall a. ProtectionIndicator a => a
getProtected)


{- $parsing

The 'parseParamsFor' function defines the parser for a header type.

@
'parseParamsFor'
  :: ('HasParams' a, HasParams b)
  => Proxy b -> Maybe Object -> Maybe Object -> 'Parser' a
@

It is defined over two objects: the /protected header/ and the
/unprotected header/.  The following functions are provided for
parsing header parameters:

['headerOptional']
  An optional parameter that may be protected or unprotected.
['headerRequired']
  A required parameter that may be protected or unprotected.
['headerOptionalProtected']
  An optional parameter that, if present, MUST be carried in the protected header.
['headerRequiredProtected']
  A required parameter that, if present, MUST be carried in the protected header.

Duplicate headers are forbidden.  The above functions all perform
duplicate header detection.  If you do not use them, be sure to
perform this detection yourself!

An example parser:

@
instance HasParams ACMEHeader where
  'parseParamsFor' proxy hp hu = ACMEHeader
    \<$> 'parseParamsFor' proxy hp hu
    \<*> 'headerRequiredProtected' "nonce" hp hu
@

-}

-- | Parse an optional parameter that may be carried in either
-- the protected or the unprotected header.
--
headerOptional
  :: (FromJSON a, ProtectionIndicator p)
  => T.Text
  -> Maybe Object
  -> Maybe Object
  -> Parser (Maybe (HeaderParam p a))
headerOptional :: forall a p.
(FromJSON a, ProtectionIndicator p) =>
Text
-> Maybe Object -> Maybe Object -> Parser (Maybe (HeaderParam p a))
headerOptional = forall p a.
ProtectionIndicator p =>
(Value -> Parser a)
-> Text
-> Maybe Object
-> Maybe Object
-> Parser (Maybe (HeaderParam p a))
headerOptional' forall a. FromJSON a => Value -> Parser a
parseJSON

-- | Parse an optional parameter that may be carried in either
-- the protected or the unprotected header.  Like 'headerOptional',
-- but with an explicit argument for the parser.
--
headerOptional'
  :: (ProtectionIndicator p)
  => (Value -> Parser a)
  -> T.Text
  -> Maybe Object
  -> Maybe Object
  -> Parser (Maybe (HeaderParam p a))
headerOptional' :: forall p a.
ProtectionIndicator p =>
(Value -> Parser a)
-> Text
-> Maybe Object
-> Maybe Object
-> Parser (Maybe (HeaderParam p a))
headerOptional' Value -> Parser a
parser Text
kText Maybe Object
hp Maybe Object
hu = case (Maybe Object
hp forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall v. Key -> KeyMap v -> Maybe v
M.lookup Key
k, Maybe Object
hu forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall v. Key -> KeyMap v -> Maybe v
M.lookup Key
k) of
  (Just Value
_, Just Value
_)    -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"duplicate header " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
kText
  (Just Value
v, Maybe Value
Nothing)   -> forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall p a. p -> a -> HeaderParam p a
HeaderParam forall a. ProtectionIndicator a => a
getProtected forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser a
parser Value
v
  (Maybe Value
Nothing, Just Value
v)   -> forall b a. b -> (a -> b) -> Maybe a -> b
maybe
    (forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"unprotected header not supported")
    (\p
p -> forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall p a. p -> a -> HeaderParam p a
HeaderParam p
p forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser a
parser Value
v)
    forall a. ProtectionIndicator a => Maybe a
getUnprotected
  (Maybe Value
Nothing, Maybe Value
Nothing)  -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing
  where
    k :: Key
k = Text -> Key
Key.fromText Text
kText

-- | Parse an optional parameter that, if present, MUST be carried
-- in the protected header.
--
headerOptionalProtected
  :: FromJSON a
  => T.Text
  -> Maybe Object
  -> Maybe Object
  -> Parser (Maybe a)
headerOptionalProtected :: forall a.
FromJSON a =>
Text -> Maybe Object -> Maybe Object -> Parser (Maybe a)
headerOptionalProtected Text
kText Maybe Object
hp Maybe Object
hu = case (Maybe Object
hp forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall v. Key -> KeyMap v -> Maybe v
M.lookup Key
k, Maybe Object
hu forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall v. Key -> KeyMap v -> Maybe v
M.lookup Key
k) of
  (Just Value
_, Just Value
_)    -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"duplicate header " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
kText
  (Maybe Value
_, Just Value
_) -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"header must be protected: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
kText
  (Just Value
v, Maybe Value
_) -> forall a. a -> Maybe a
Just forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON Value
v
  (Maybe Value, Maybe Value)
_           -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing
  where
    k :: Key
k = Text -> Key
Key.fromText Text
kText

-- | Parse a required parameter that may be carried in either
-- the protected or the unprotected header.
--
headerRequired
  :: (FromJSON a, ProtectionIndicator p)
  => T.Text
  -> Maybe Object
  -> Maybe Object
  -> Parser (HeaderParam p a)
headerRequired :: forall a p.
(FromJSON a, ProtectionIndicator p) =>
Text -> Maybe Object -> Maybe Object -> Parser (HeaderParam p a)
headerRequired Text
kText Maybe Object
hp Maybe Object
hu = case (Maybe Object
hp forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall v. Key -> KeyMap v -> Maybe v
M.lookup Key
k, Maybe Object
hu forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall v. Key -> KeyMap v -> Maybe v
M.lookup Key
k) of
  (Just Value
_, Just Value
_)    -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"duplicate header " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
kText
  (Just Value
v, Maybe Value
Nothing)   -> forall p a. p -> a -> HeaderParam p a
HeaderParam forall a. ProtectionIndicator a => a
getProtected forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON Value
v
  (Maybe Value
Nothing, Just Value
v)   -> forall b a. b -> (a -> b) -> Maybe a -> b
maybe
    (forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"unprotected header not supported")
    (\p
p -> forall p a. p -> a -> HeaderParam p a
HeaderParam p
p forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON Value
v)
    forall a. ProtectionIndicator a => Maybe a
getUnprotected
  (Maybe Value
Nothing, Maybe Value
Nothing)  -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"missing required header " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Key
k
  where
    k :: Key
k = Text -> Key
Key.fromText Text
kText

-- | Parse a required parameter that MUST be carried
-- in the protected header.
--
headerRequiredProtected
  :: FromJSON a
  => T.Text
  -> Maybe Object
  -> Maybe Object
  -> Parser a
headerRequiredProtected :: forall a.
FromJSON a =>
Text -> Maybe Object -> Maybe Object -> Parser a
headerRequiredProtected Text
kText Maybe Object
hp Maybe Object
hu = case (Maybe Object
hp forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall v. Key -> KeyMap v -> Maybe v
M.lookup Key
k, Maybe Object
hu forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall v. Key -> KeyMap v -> Maybe v
M.lookup Key
k) of
  (Just Value
_, Just Value
_)    -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"duplicate header " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
kText
  (Maybe Value
_, Just Value
_) -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"header must be protected: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Text
kText
  (Just Value
v, Maybe Value
_) -> forall a. FromJSON a => Value -> Parser a
parseJSON Value
v
  (Maybe Value, Maybe Value)
_           -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"missing required protected header: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Text
kText
  where
    k :: Key
k = Text -> Key
Key.fromText Text
kText


critObjectParser
  :: (Foldable t0, Foldable t1, Fail.MonadFail m)
  => t0 T.Text -> t1 T.Text -> Object -> T.Text -> m T.Text
critObjectParser :: forall (t0 :: * -> *) (t1 :: * -> *) (m :: * -> *).
(Foldable t0, Foldable t1, MonadFail m) =>
t0 Text -> t1 Text -> Object -> Text -> m Text
critObjectParser t0 Text
reserved t1 Text
exts Object
o Text
s
  | Text
s forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` t0 Text
reserved         = forall (m :: * -> *) a. MonadFail m => String -> m a
Fail.fail String
"crit key is reserved"
  | Text
s forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` t1 Text
exts          = forall (m :: * -> *) a. MonadFail m => String -> m a
Fail.fail String
"crit key is not understood"
  | Bool -> Bool
not (Text -> Key
Key.fromText Text
s forall a. Key -> KeyMap a -> Bool
`M.member` Object
o) = forall (m :: * -> *) a. MonadFail m => String -> m a
Fail.fail String
"crit key is not present in headers"
  | Bool
otherwise                 = forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
s

-- | Parse a "crit" header param
--
-- Fails if:
--
-- * any reserved header appears in "crit" header
-- * any value in "crit" is not a recognised extension
-- * any value in "crit" does not have a corresponding key in the object
--
parseCrit
  :: (Foldable t0, Foldable t1, Traversable t2, Traversable t3, Fail.MonadFail m)
  => t0 T.Text -- ^ reserved header parameters
  -> t1 T.Text -- ^ recognised extensions
  -> Object    -- ^ full header (union of protected and unprotected headers)
  -> t2 (t3 T.Text) -- ^ crit header
  -> m (t2 (t3 T.Text))
parseCrit :: forall (t0 :: * -> *) (t1 :: * -> *) (t2 :: * -> *) (t3 :: * -> *)
       (m :: * -> *).
(Foldable t0, Foldable t1, Traversable t2, Traversable t3,
 MonadFail m) =>
t0 Text -> t1 Text -> Object -> t2 (t3 Text) -> m (t2 (t3 Text))
parseCrit t0 Text
reserved t1 Text
exts Object
o = forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (t0 :: * -> *) (t1 :: * -> *) (m :: * -> *).
(Foldable t0, Foldable t1, MonadFail m) =>
t0 Text -> t1 Text -> Object -> Text -> m Text
critObjectParser t0 Text
reserved t1 Text
exts Object
o))
  -- TODO fail on duplicate strings


class HasAlg a where
  alg :: Lens' (a p) (HeaderParam p JWA.JWS.Alg)

class HasJku a where
  jku :: Lens' (a p) (Maybe (HeaderParam p Types.URI))

class HasJwk a where
  jwk :: Lens' (a p) (Maybe (HeaderParam p JWK))

class HasKid a where
  kid :: Lens' (a p) (Maybe (HeaderParam p T.Text))

class HasX5u a where
  x5u :: Lens' (a p) (Maybe (HeaderParam p Types.URI))

class HasX5c a where
  x5c :: Lens' (a p) (Maybe (HeaderParam p (NonEmpty Types.SignedCertificate)))

class HasX5t a where
  x5t :: Lens' (a p) (Maybe (HeaderParam p Types.Base64SHA1))

class HasX5tS256 a where
  x5tS256 :: Lens' (a p) (Maybe (HeaderParam p Types.Base64SHA256))

class HasTyp a where
  typ :: Lens' (a p) (Maybe (HeaderParam p T.Text))

class HasCty a where
  cty :: Lens' (a p) (Maybe (HeaderParam p T.Text))

class HasCrit a where
  crit :: Lens' (a p) (Maybe (NonEmpty T.Text))