oidc-client-0.3.0.0: test/Spec/Client.hs
{-# LANGUAGE OverloadedStrings #-}
module Spec.Client where
import Data.ByteString (ByteString)
import Data.Text (unpack)
import Data.Text.Encoding (decodeUtf8)
import Network.HTTP.Client (newManager)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import Network.HTTP.Types (urlEncode)
import Test.Hspec (Spec, describe, it, shouldContain, shouldNotContain, shouldThrow)
import Web.OIDC.Client
clientId, clientSecret, redirectUri, nonce :: ByteString
clientId = "dummy client id"
clientSecret = "dummy client secret"
redirectUri = "http://localhost"
nonce = "dummy nonce"
tests :: Spec
tests = do
describe "CodeFlow.getAuthenticationRequestUrl" $ do
it "should return a url that has required parameters" $ do
manager <- newManager tlsManagerSettings
provider <- discover google manager
let oidc = setCredentials clientId clientSecret redirectUri $ newOIDC provider
url <- getAuthenticationRequestUrl oidc [] Nothing []
show url `shouldContain` "response_type=code"
show url `shouldContain` "scope=openid"
show url `shouldContain` (toES "client_id" ++ "=" ++ toES clientId)
show url `shouldContain` (toES "redirect_uri" ++ "=" ++ toES redirectUri)
show url `shouldNotContain` toES clientSecret
it "should return a url that has other parameters" $ do
manager <- newManager tlsManagerSettings
provider <- discover google manager
let oidc = setCredentials clientId clientSecret redirectUri $ newOIDC provider
state = "dummy state"
url <- getAuthenticationRequestUrl oidc [email] (Just state) [("nonce", Just nonce)]
show url `shouldContain` (toES "scope" ++ "=" ++ toES "openid email")
show url `shouldContain` (toES "state" ++ "=" ++ toES state)
show url `shouldContain` (toES "nonce" ++ "=" ++ toES nonce)
describe "CodeFlow.validateClaims" $ do
it "should succeed at a validation of correct claims" $ do
let issuer' = "http://localhost"
clientId' = decodeUtf8 clientId
now <- getCurrentIntDate
let claims' = defClaims { jwtIss = Just issuer'
, jwtAud = Just [clientId']
, jwtExp = Just (add 10 now)
}
validateClaims issuer' clientId' now claims'
validateClaims issuer' clientId' now (claims' { jwtAud = Just ["other id", clientId'] })
it "should throw ValidationException if 'iss' field is invalid" $ do
let issuer' = "http://localhost"
clientId' = decodeUtf8 clientId
now <- getCurrentIntDate
let claims' = defClaims { jwtIss = Just "http://localhost/hoge"
, jwtAud = Just [clientId']
, jwtExp = Just (add 10 now)
}
validateClaims issuer' clientId' now claims'
`shouldThrow` isValidationException
it "should throw ValidationException if 'aud' field does not contain Client ID" $ do
let issuer' = "http://localhost"
clientId' = decodeUtf8 clientId
now <- getCurrentIntDate
let claims' = defClaims { jwtIss = Just issuer'
, jwtAud = Just ["other id"]
, jwtExp = Just (add 10 now)
}
validateClaims issuer' clientId' now claims'
`shouldThrow` isValidationException
it "should throw ValidationException if 'exp' field expired" $ do
let issuer' = "http://localhost"
clientId' = decodeUtf8 clientId
now <- getCurrentIntDate
let claims' = defClaims { jwtIss = Just issuer'
, jwtAud = Just [clientId']
, jwtExp = Just (add (-1) now)
}
validateClaims issuer' clientId' now claims'
`shouldThrow` isValidationException
where
toES = unpack . decodeUtf8 . urlEncode True
defClaims = JwtClaims { jwtIss = Nothing
, jwtSub = Nothing
, jwtAud = Nothing
, jwtExp = Nothing
, jwtNbf = Nothing
, jwtIat = Nothing
, jwtJti = Nothing
}
add sec (IntDate t) = IntDate $ t + sec
isValidationException e = case e of
(ValidationException _) -> True
_ -> False