correct: fail on invalid types of registered JWT claims (exp, nbf, iat, aud)
This commit is contained in:
@@ -137,6 +137,66 @@ spec = describe "authorization" $ do
|
||||
request methodGet "/authors_only" [auth] ""
|
||||
`shouldRespondWith` 200
|
||||
|
||||
it "fails when the exp claim is not a number" $ do
|
||||
let jwtPayload = [json|
|
||||
{
|
||||
"exp": "invalid",
|
||||
"role": "postgrest_test_author"
|
||||
}|]
|
||||
auth = authHeaderJWT $ generateJWT jwtPayload
|
||||
request methodGet "/authors_only" [auth] ""
|
||||
`shouldRespondWith`
|
||||
[json|{"code":"PGRST303","details":null,"hint":null,"message":"The JWT 'exp' claim must be a number"}|]
|
||||
{ matchStatus = 401 }
|
||||
|
||||
it "fails when the nbf claim is not a number" $ do
|
||||
let jwtPayload = [json|
|
||||
{
|
||||
"nbf": "invalid",
|
||||
"role": "postgrest_test_author"
|
||||
}|]
|
||||
auth = authHeaderJWT $ generateJWT jwtPayload
|
||||
request methodGet "/authors_only" [auth] ""
|
||||
`shouldRespondWith`
|
||||
[json|{"code":"PGRST303","details":null,"hint":null,"message":"The JWT 'nbf' claim must be a number"}|]
|
||||
{ matchStatus = 401 }
|
||||
|
||||
it "fails when the iat claim is not a number" $ do
|
||||
let jwtPayload = [json|
|
||||
{
|
||||
"iat": "invalid",
|
||||
"role": "postgrest_test_author"
|
||||
}|]
|
||||
auth = authHeaderJWT $ generateJWT jwtPayload
|
||||
request methodGet "/authors_only" [auth] ""
|
||||
`shouldRespondWith`
|
||||
[json|{"code":"PGRST303","details":null,"hint":null,"message":"The JWT 'iat' claim must be a number"}|]
|
||||
{ matchStatus = 401 }
|
||||
|
||||
it "fails when the aud claim has a single value and it's not a string" $ do
|
||||
let jwtPayload = [json|
|
||||
{
|
||||
"aud": {"invalid": "value"},
|
||||
"role": "postgrest_test_author"
|
||||
}|]
|
||||
auth = authHeaderJWT $ generateJWT jwtPayload
|
||||
request methodGet "/authors_only" [auth] ""
|
||||
`shouldRespondWith`
|
||||
[json|{"code":"PGRST303","details":null,"hint":null,"message":"The JWT 'aud' claim must be a string or an array of strings"}|]
|
||||
{ matchStatus = 401 }
|
||||
|
||||
it "fails when the aud claim is an array but it has non-string elements" $ do
|
||||
let jwtPayload = [json|
|
||||
{
|
||||
"aud": [{"invalid": "value"}, "test"],
|
||||
"role": "postgrest_test_author"
|
||||
}|]
|
||||
auth = authHeaderJWT $ generateJWT jwtPayload
|
||||
request methodGet "/authors_only" [auth] ""
|
||||
`shouldRespondWith`
|
||||
[json|{"code":"PGRST303","details":null,"hint":null,"message":"The JWT 'aud' claim must be a string or an array of strings"}|]
|
||||
{ matchStatus = 401 }
|
||||
|
||||
describe "custom pre-request proc acting on id claim" $ do
|
||||
|
||||
it "able to switch to postgrest_test_author role (id=1)" $
|
||||
|
||||
+14
-6
@@ -10,6 +10,9 @@ import qualified Data.ByteString.Lazy as BL
|
||||
import qualified Data.Map.Strict as M
|
||||
import Data.Scientific (toRealFloat)
|
||||
import qualified Data.Set as S
|
||||
import qualified Jose.Jwa as JWT
|
||||
import qualified Jose.Jws as JWT
|
||||
import qualified Jose.Jwt as JWT
|
||||
|
||||
import Data.Aeson ((.=))
|
||||
import Data.CaseInsensitive (CI (..), mk, original)
|
||||
@@ -197,19 +200,17 @@ testPlanEnabledCfg = baseCfg { configDbPlanEnabled = True }
|
||||
|
||||
testCfgBinaryJWT :: AppConfig
|
||||
testCfgBinaryJWT =
|
||||
let secret = B64.decodeLenient "cmVhbGx5cmVhbGx5cmVhbGx5cmVhbGx5dmVyeXNhZmU=" in
|
||||
baseCfg {
|
||||
configJwtSecret = Just secret
|
||||
, configJWKS = rightToMaybe $ parseSecret secret
|
||||
configJwtSecret = Just generateSecret
|
||||
, configJWKS = rightToMaybe $ parseSecret generateSecret
|
||||
}
|
||||
|
||||
testCfgAudienceJWT :: AppConfig
|
||||
testCfgAudienceJWT =
|
||||
let secret = B64.decodeLenient "cmVhbGx5cmVhbGx5cmVhbGx5cmVhbGx5dmVyeXNhZmU=" in
|
||||
baseCfg {
|
||||
configJwtSecret = Just secret
|
||||
configJwtSecret = Just generateSecret
|
||||
, configJwtAudience = Just "youraudience"
|
||||
, configJWKS = rightToMaybe $ parseSecret secret
|
||||
, configJWKS = rightToMaybe $ parseSecret generateSecret
|
||||
}
|
||||
|
||||
testCfgAsymJWK :: AppConfig
|
||||
@@ -291,6 +292,13 @@ authHeader typ creds =
|
||||
authHeaderJWT :: BS.ByteString -> Header
|
||||
authHeaderJWT = authHeader "Bearer"
|
||||
|
||||
generateSecret :: ByteString
|
||||
generateSecret = B64.decodeLenient "cmVhbGx5cmVhbGx5cmVhbGx5cmVhbGx5dmVyeXNhZmU="
|
||||
|
||||
generateJWT :: BL.ByteString -> ByteString
|
||||
generateJWT claims =
|
||||
either mempty JWT.unJwt $ JWT.hmacEncode JWT.HS256 generateSecret (BL.toStrict claims)
|
||||
|
||||
-- | Tests whether the text can be parsed as a json object containing
|
||||
-- the key "message", and optional keys "details", "hint", "code",
|
||||
-- and no extraneous keys
|
||||
|
||||
Reference in New Issue
Block a user