module Jose.Jwt
( module Jose.Types
, decode
)
where
import Crypto.PubKey.RSA (PrivateKey(..))
import Data.ByteString (ByteString)
import Data.List (find)
import qualified Data.ByteString.Char8 as BC
import qualified Jose.Internal.Base64 as B64
import Jose.Types
import Jose.Jwk
import qualified Jose.Jws as Jws
import qualified Jose.Jwe as Jwe
decode :: JwkSet
-> ByteString
-> Either JwtError Jwt
decode keySet jwt = do
let components = BC.split '.' jwt
hdr <- (B64.decode $ head components) >>= parseHeader
ks <- findKeys hdr (keys keySet)
let decodeWith = case hdr of
JwsH _ -> decodeWithJws
_ -> decodeWithJwe
let decodings = map decodeWith ks
maybe (Left $ KeyError "None of the keys was able to decode the JWT") id $ find (isRight) decodings
where
decodeWithJws :: Jwk -> Either JwtError Jwt
decodeWithJws k = fmap Jws $ case k of
RsaPublicJwk kPub _ _ _ -> Jws.rsaDecode kPub jwt
RsaPrivateJwk kPr _ _ _ -> Jws.rsaDecode (private_pub kPr) jwt
SymmetricJwk kb _ _ _ -> Jws.hmacDecode kb jwt
decodeWithJwe :: Jwk -> Either JwtError Jwt
decodeWithJwe k = fmap Jwe $ case k of
RsaPrivateJwk kPr _ _ _ -> Jwe.rsaDecode kPr jwt
_ -> Left $ KeyError "Not a JWE key (shoudln't happen)"
isRight (Left _) = False
isRight (Right _) = True
findKeys :: JwtHeader -> [Jwk] -> Either JwtError [Jwk]
findKeys hdr jwks = checkKeys $ case hdr of
JweH h -> findMatchingJweKeys jwks h
JwsH h -> findMatchingJwsKeys jwks h
where
checkKeys [] = Left $ KeyError "No suitable key was found to decode the JWT"
checkKeys ks = return ks