Skip to content

Commit 371f88d

Browse files
committed
refactor: group jwt errors
1 parent c9a625c commit 371f88d

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

src/PostgREST/Auth.hs

+7-7
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import PostgREST.Auth.JwtCache (lookupJwtCache)
4848
import PostgREST.Auth.Types (AuthResult (..))
4949
import PostgREST.Config (AppConfig (..), FilterExp (..),
5050
JSPath, JSPathExp (..))
51-
import PostgREST.Error (Error (..))
51+
import PostgREST.Error (Error (..), JwtError (..))
5252

5353
import Protolude
5454

@@ -57,20 +57,20 @@ import Protolude
5757
parseToken :: AppConfig -> ByteString -> UTCTime -> ExceptT Error IO JSON.Value
5858
parseToken _ "" _ = return JSON.emptyObject
5959
parseToken AppConfig{..} token time = do
60-
secret <- liftEither . maybeToRight JwtTokenMissing $ configJWKS
60+
secret <- liftEither . maybeToRight (JwtErr JwtTokenMissing) $ configJWKS
6161
eitherContent <- liftIO $ JWT.decode (JWT.keys secret) Nothing token
62-
content <- liftEither . mapLeft jwtDecodeError $ eitherContent
63-
liftEither $ verifyClaims content
62+
content <- liftEither . mapLeft (JwtErr . jwtDecodeError) $ eitherContent
63+
liftEither $ mapLeft JwtErr $ verifyClaims content
6464
where
6565
-- TODO: Improve errors, those were just taken as-is from hs-jose to avoid
6666
-- breaking changes.
67-
jwtDecodeError :: JWT.JwtError -> Error
67+
jwtDecodeError :: JWT.JwtError -> JwtError
6868
jwtDecodeError (JWT.KeyError _) = JwtTokenInvalid "JWSError JWSInvalidSignature"
6969
jwtDecodeError JWT.BadCrypto = JwtTokenInvalid "JWSError (CompactDecodeError Invalid number of parts: Expected 3 parts; got 2)"
7070
jwtDecodeError (JWT.BadAlgorithm _) = JwtTokenInvalid "JWSError JWSNoSignatures"
7171
jwtDecodeError e = JwtTokenInvalid $ show e
7272

73-
verifyClaims :: JWT.JwtContent -> Either Error JSON.Value
73+
verifyClaims :: JWT.JwtContent -> Either JwtError JSON.Value
7474
verifyClaims (JWT.Jws (_, claims)) = case JSON.decodeStrict claims of
7575
Nothing -> Left $ JwtTokenInvalid "Parsing claims failed"
7676
Just (JSON.Object mclaims)
@@ -110,7 +110,7 @@ parseClaims :: Monad m =>
110110
AppConfig -> JSON.Value -> ExceptT Error m AuthResult
111111
parseClaims AppConfig{..} jclaims@(JSON.Object mclaims) = do
112112
-- role defaults to anon if not specified in jwt
113-
role <- liftEither . maybeToRight JwtTokenRequired $
113+
role <- liftEither . maybeToRight (JwtErr JwtTokenRequired) $
114114
unquoted <$> walkJSPath (Just jclaims) configJwtRoleClaimKey <|> configDbAnonRole
115115
return AuthResult
116116
{ authClaims = mclaims & KM.insert "role" (JSON.toJSON $ decodeUtf8 role)

src/PostgREST/Error.hs

+25-11
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module PostgREST.Error
1212
, RangeError(..)
1313
, PgError(..)
1414
, Error(..)
15+
, JwtError (..)
1516
, errorPayload
1617
, status
1718
) where
@@ -567,32 +568,47 @@ pgErrorStatus authed (SQL.SessionUsageError (SQL.QueryError _ _ (SQL.ResultError
567568
_ -> HTTP.status500
568569

569570

571+
-- TODO: separate "SchemaCacheError" from ApiRequestError similar to how we
572+
-- them in docs
570573
data Error
571574
= ApiRequestError ApiRequestError
572-
| JwtTokenInvalid Text
573-
| JwtTokenMissing
574-
| JwtTokenRequired
575+
| JwtErr JwtError
575576
| NoSchemaCacheError
576577
| PgErr PgError
577578

579+
data JwtError
580+
= JwtTokenInvalid Text
581+
| JwtTokenMissing
582+
| JwtTokenRequired
583+
578584
instance PgrstError Error where
579585
status (ApiRequestError err) = status err
580-
status JwtTokenInvalid{} = HTTP.unauthorized401
581-
status JwtTokenMissing = HTTP.status500
582-
status JwtTokenRequired = HTTP.unauthorized401
586+
status (JwtErr err) = status err
583587
status NoSchemaCacheError = HTTP.status503
584588
status (PgErr err) = status err
585589

586590
headers (ApiRequestError err) = headers err
587-
headers (JwtTokenInvalid m) = [invalidTokenHeader m]
588-
headers JwtTokenRequired = [requiredTokenHeader]
591+
headers (JwtErr err) = headers err
589592
headers (PgErr err) = headers err
590593
headers _ = mempty
591594

595+
instance PgrstError JwtError where
596+
status JwtTokenInvalid{} = HTTP.unauthorized401
597+
status JwtTokenMissing = HTTP.status500
598+
status JwtTokenRequired = HTTP.unauthorized401
599+
600+
headers (JwtTokenInvalid m) = [invalidTokenHeader m]
601+
headers JwtTokenRequired = [requiredTokenHeader]
602+
headers _ = mempty
603+
592604
instance JSON.ToJSON Error where
593-
toJSON NoSchemaCacheError = toJsonPgrstError
605+
toJSON (ApiRequestError err) = JSON.toJSON err
606+
toJSON (JwtErr err) = JSON.toJSON err
607+
toJSON (PgErr err) = JSON.toJSON err
608+
toJSON NoSchemaCacheError = toJsonPgrstError
594609
ConnectionErrorCode02 "Could not query the database for the schema cache. Retrying." Nothing Nothing
595610

611+
instance JSON.ToJSON JwtError where
596612
toJSON JwtTokenMissing = toJsonPgrstError
597613
JWTErrorCode00 "Server lacks JWT secret" Nothing Nothing
598614

@@ -602,8 +618,6 @@ instance JSON.ToJSON Error where
602618
toJSON JwtTokenRequired = toJsonPgrstError
603619
JWTErrorCode02 "Anonymous access is disabled" Nothing Nothing
604620

605-
toJSON (PgErr err) = JSON.toJSON err
606-
toJSON (ApiRequestError err) = JSON.toJSON err
607621

608622
invalidTokenHeader :: Text -> Header
609623
invalidTokenHeader m =

0 commit comments

Comments
 (0)