postgres-websockets 0.11.2.5 → 0.12.0.0
raw patch · 3 files changed
+50/−9 lines, 3 filesdep ~jose
Dependency ranges changed: jose
Files
- postgres-websockets.cabal +2/−2
- src/PostgresWebsockets/Claims.hs +9/−7
- test/ClaimsSpec.hs +39/−0
postgres-websockets.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: postgres-websockets-version: 0.11.2.5+version: 0.12.0.0 synopsis: Middleware to map LISTEN/NOTIFY messages to Websockets description: WAI middleware that adds websockets capabilites on top of PostgreSQL's asynchronous notifications using LISTEN and NOTIFY commands. Fully functioning server included. homepage: https://github.com/diogob/postgres-websockets#readme@@ -48,7 +48,7 @@ , hasql-notifications >= 0.2.4.0 && < 0.3 , hasql-pool ^>= 1.3 , http-types >= 0.12.3 && < 0.13- , jose >= 0.11 && < 0.12+ , jose >= 0.11 && < 0.13 , lens >= 5.2.3 && < 5.4 , mtl >=2.3.1 && <2.4 , async >=2.2.5 && <2.3
src/PostgresWebsockets/Claims.hs view
@@ -35,7 +35,7 @@ UTCTime -> IO (Either Text ConnectionInfo) validateClaims requestChannel secret jwtToken time = runExceptT $ do- cl <- liftIO $ jwtClaims time (parseJWK secret) jwtToken+ cl <- liftIO $ jwtClaims time (parseSecret secret) jwtToken cl' <- case cl of JWTClaims c -> pure c JWTInvalid JWTExpired -> throwError "Token expired"@@ -82,13 +82,13 @@ -- | -- Receives the JWT secret (from config) and a JWT and returns a map -- of JWT claims.-jwtClaims :: UTCTime -> JWK -> LByteString -> IO JWTAttempt+jwtClaims :: UTCTime -> JWKSet -> LByteString -> IO JWTAttempt jwtClaims _ _ "" = return $ JWTClaims JSON.empty-jwtClaims time jwk' payload = do+jwtClaims time jwks payload = do let config = defaultJWTValidationSettings (const True) eJwt <- runExceptT $ do jwt <- decodeCompact payload- verifyClaimsAt config jwk' time jwt+ verifyClaimsAt config jwks time (jwt :: SignedJWT) return $ case eJwt of Left e -> JWTInvalid e Right jwt -> JWTClaims . claims2map $ jwt@@ -114,6 +114,8 @@ where km = OctKeyMaterial (OctKeyParameters (JOSE.Types.Base64Octets key)) -parseJWK :: ByteString -> JWK-parseJWK str =- fromMaybe (hs256jwk str) (JSON.decode (fromStrict str) :: Maybe JWK)+parseSecret :: ByteString -> JWKSet+parseSecret str =+ case JSON.decode (fromStrict str) :: Maybe JWKSet of+ Just jwks -> jwks+ Nothing -> JWKSet [fromMaybe (hs256jwk str) (JSON.decode (fromStrict str) :: Maybe JWK)]
test/ClaimsSpec.hs view
@@ -11,6 +11,14 @@ secret :: ByteString secret = "reallyreallyreallyreallyverysafe" +-- Same secret as a single JWK object+jwkSecret :: ByteString+jwkSecret = "{\"kty\":\"oct\",\"k\":\"cmVhbGx5cmVhbGx5cmVhbGx5cmVhbGx5dmVyeXNhZmU\",\"alg\":\"HS256\"}"++-- Same secret wrapped in a JWKS envelope+jwksSecret :: ByteString+jwksSecret = "{\"keys\":[{\"kty\":\"oct\",\"k\":\"cmVhbGx5cmVhbGx5cmVhbGx5cmVhbGx5dmVyeXNhZmU\",\"alg\":\"HS256\"}]}"+ spec :: Spec spec = describe "validate claims" $ do@@ -73,3 +81,34 @@ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjaGFubmVscyI6WyJ0ZXN0IiwidGVzdDIiXX0.akC1PEYk2DEZtLP2XjC6qXOGZJejmPx49qv-VeEtQYQ" time `shouldReturn` Left "Missing mode"++ it "should validate a token using a JWK secret" $ do+ time <- getCurrentTime+ validateClaims+ (Just "test")+ jwkSecret+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtb2RlIjoiciIsImNoYW5uZWwiOiJ0ZXN0In0.1d4s-at2kWj8OSabHZHTbNh1dENF7NWy_r0ED3Rwf58"+ time+ `shouldReturn` Right (["test"], "r", JSON.fromList [("mode", String "r"), ("channel", String "test")])++ it "should validate a token using a JWKS secret" $ do+ time <- getCurrentTime+ validateClaims+ (Just "test")+ jwksSecret+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtb2RlIjoiciIsImNoYW5uZWwiOiJ0ZXN0In0.1d4s-at2kWj8OSabHZHTbNh1dENF7NWy_r0ED3Rwf58"+ time+ `shouldReturn` Right (["test"], "r", JSON.fromList [("mode", String "r"), ("channel", String "test")])++ it "should reject a token with wrong key in JWKS" $ do+ time <- getCurrentTime+ result <-+ validateClaims+ (Just "test")+ "{\"keys\":[{\"kty\":\"oct\",\"k\":\"d3JvbmdrZXl3cm9uZ2tleXdyb25na2V5d3Jvbmdr\",\"alg\":\"HS256\"}]}"+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtb2RlIjoiciIsImNoYW5uZWwiOiJ0ZXN0In0.1d4s-at2kWj8OSabHZHTbNh1dENF7NWy_r0ED3Rwf58"+ time+ result `shouldSatisfy` isLeft+ where+ isLeft (Left _) = True+ isLeft _ = False