diff --git a/src/PostgREST/App.hs b/src/PostgREST/App.hs index bac5a4960..cd72a0d66 100644 --- a/src/PostgREST/App.hs +++ b/src/PostgREST/App.hs @@ -184,7 +184,7 @@ app dbStructure conf reqBody req = hasPrefer val = any (\(h,v) -> h == "Prefer" && v == val) hdrs accept = lookupHeader hAccept schema = cs $ configSchema conf - jwtSecret = (cs $ configJwtSecret conf) :: Text + jwtSecret = configJwtSecret conf range = rangeRequested hdrs allOrigins = ("Access-Control-Allow-Origin", "*") :: Header contentType = fromMaybe "application/json" $ contentTypeForAccept accept diff --git a/src/PostgREST/Auth.hs b/src/PostgREST/Auth.hs index 22d7de82a..f46da3c71 100644 --- a/src/PostgREST/Auth.hs +++ b/src/PostgREST/Auth.hs @@ -51,7 +51,7 @@ claimsToSQL = map setVar . toList returns a map of JWT claims In case there is any problem decoding the JWT it returns Nothing. -} -jwtClaims :: Text -> Text -> NominalDiffTime -> Maybe JWT.ClaimsMap +jwtClaims :: JWT.Secret -> Text -> NominalDiffTime -> Maybe JWT.ClaimsMap jwtClaims secret input time = case join $ claim JWT.exp of Just expires -> @@ -60,7 +60,7 @@ jwtClaims secret input time = else Nothing _ -> customClaims where - decoded = JWT.decodeAndVerifySignature (JWT.secret secret) input + decoded = JWT.decodeAndVerifySignature secret input claim :: (JWT.JWTClaimsSet -> a) -> Maybe a claim prop = prop . JWT.claims <$> decoded customClaims = claim JWT.unregisteredClaims @@ -74,8 +74,8 @@ setRole role = "set local role " <> cs (pgFmtLit role) <> ";" Receives the JWT secret (from config) and a JWT and a JSON value and returns a signed JWT. -} -tokenJWT :: Text -> Value -> Text -tokenJWT secret (Array a) = JWT.encodeSigned JWT.HS256 (JWT.secret secret) +tokenJWT :: JWT.Secret -> Value -> Text +tokenJWT secret (Array a) = JWT.encodeSigned JWT.HS256 secret JWT.def { JWT.unregisteredClaims = fromHashMap o } where Object o = if V.null a then emptyObject else V.head a diff --git a/src/PostgREST/Config.hs b/src/PostgREST/Config.hs index 17a94ff07..e7a9cc110 100644 --- a/src/PostgREST/Config.hs +++ b/src/PostgREST/Config.hs @@ -30,6 +30,7 @@ import Network.Wai import Network.Wai.Middleware.Cors (CorsResourcePolicy (..)) import Options.Applicative import Paths_postgrest (version) +import Web.JWT (Secret, secret) import Prelude -- | Data type to store all command line options @@ -38,7 +39,7 @@ data AppConfig = AppConfig { , configPort :: Int , configAnonRole :: String , configSchema :: String - , configJwtSecret :: String + , configJwtSecret :: Secret , configPool :: Int } @@ -49,7 +50,8 @@ argParser = AppConfig <*> option auto (long "port" <> short 'p' <> help "port number on which to run HTTP server" <> metavar "PORT" <> value 3000 <> showDefault) <*> strOption (long "anonymous" <> short 'a' <> help "postgres role to use for non-authenticated requests" <> metavar "ROLE") <*> strOption (long "schema" <> short 's' <> help "schema to use for API routes" <> metavar "NAME" <> value "1" <> showDefault) - <*> strOption (long "jwt-secret" <> short 'j' <> help "secret used to encrypt and decrypt JWT tokens" <> metavar "SECRET" <> value "secret" <> showDefault) + <*> (secret . cs <$> + strOption (long "jwt-secret" <> short 'j' <> help "secret used to encrypt and decrypt JWT tokens" <> metavar "SECRET" <> value "secret" <> showDefault)) <*> option auto (long "pool" <> short 'o' <> help "max connections in database pool" <> metavar "COUNT" <> value 10 <> showDefault) defaultCorsPolicy :: CorsResourcePolicy diff --git a/src/PostgREST/Main.hs b/src/PostgREST/Main.hs index 02640cdd5..fed0c41df 100644 --- a/src/PostgREST/Main.hs +++ b/src/PostgREST/Main.hs @@ -25,6 +25,7 @@ import Network.Wai.Middleware.RequestLogger (logStdout) import System.IO (BufferMode (..), hSetBuffering, stderr, stdin, stdout) +import Web.JWT (secret) isServerVersionSupported :: H.Session P.Postgres IO Bool isServerVersionSupported = do @@ -43,7 +44,7 @@ main = do conf <- readOptions let port = configPort conf - unless ("secret" /= configJwtSecret conf) $ + unless (secret "secret" /= configJwtSecret conf) $ putStrLn "WARNING, running in insecure mode, JWT secret is the default value" Prelude.putStrLn $ "Listening on port " ++ (show $ configPort conf :: String) diff --git a/src/PostgREST/Middleware.hs b/src/PostgREST/Middleware.hs index 6a60f20d0..a8e800768 100644 --- a/src/PostgREST/Middleware.hs +++ b/src/PostgREST/Middleware.hs @@ -51,7 +51,7 @@ runWithClaims conf app req = do where stmt c = B.Stmt c V.empty True hdrs = requestHeaders req - jwtSecret = (cs $ configJwtSecret conf) :: Text + jwtSecret = configJwtSecret conf auth = fromMaybe "" $ lookup hAuthorization hdrs anon = cs $ configAnonRole conf setAnon = setRole anon