Fix custom pre-request handler
Uses Ruslan's technique
This commit is contained in:
@@ -33,12 +33,12 @@ runWithClaims conf eClaims app req =
|
||||
JWTClaims claims -> do
|
||||
-- role claim defaults to anon if not specified in jwt
|
||||
let setClaims = claimsToSQL (M.union claims (M.singleton "role" anon))
|
||||
H.sql (mconcat $ setClaims ++ customReqCheck)
|
||||
H.sql $ mconcat setClaims
|
||||
mapM_ H.sql customReqCheck
|
||||
app req
|
||||
where
|
||||
anon = String . toS $ configAnonRole conf
|
||||
customReqCheck = maybeToList $ (\f -> "select " <> toS f <> "();")
|
||||
<$> configReqCheck conf
|
||||
customReqCheck = (\f -> "select " <> toS f <> "();") <$> configReqCheck conf
|
||||
unauthed message = responseLBS unauthorized401
|
||||
[ ctToHeader CTApplicationJSON
|
||||
, ( "WWW-Authenticate"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
module Feature.AuthSpec where
|
||||
|
||||
-- {{{ Imports
|
||||
import Text.Heredoc
|
||||
import Test.Hspec
|
||||
import Test.Hspec.Wai
|
||||
import Test.Hspec.Wai.JSON
|
||||
@@ -103,11 +104,6 @@ spec = describe "authorization" $ do
|
||||
]
|
||||
}
|
||||
|
||||
it "runs a custom request validation proc" $ do
|
||||
let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYmFkX3JvbGUifQ.ENAiheEOlskpfoT5byj-gKJkOhHKTvETQu1Zso3c4Ts"
|
||||
request methodGet "/items" [auth] ""
|
||||
`shouldRespondWith` 400
|
||||
|
||||
it "should fail when jwt contains no claims" $ do
|
||||
let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.lu-rG8aSCiw-aOlN0IxpRGz5r7Jwq7K9r3tuMPUpytI"
|
||||
request methodGet "/authors_only" [auth] ""
|
||||
@@ -124,3 +120,35 @@ spec = describe "authorization" $ do
|
||||
_ <- request methodPost "/rpc/problem" [auth] ""
|
||||
request methodGet "/authors_only" [auth] ""
|
||||
`shouldRespondWith` 200
|
||||
|
||||
describe "custom pre-request proc acting on id claim" $ do
|
||||
|
||||
it "able to switch to postgrest_test_author role (id=1)" $
|
||||
let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MX0.mI2HNoOum6xM3sc4oHLxU4yLv-_WV5W1kqBfY_wEvLw" in
|
||||
request methodPost "/rpc/get_current_user" [auth]
|
||||
[json| {} |]
|
||||
`shouldRespondWith` ResponseMatcher {
|
||||
matchBody = Just [str|"postgrest_test_author"|]
|
||||
, matchStatus = 200
|
||||
, matchHeaders = []
|
||||
}
|
||||
|
||||
it "able to switch to postgrest_test_default_role (id=2)" $
|
||||
let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Mn0.W7jLsG-zswM91AJkCvZeIMHrnz7_6ceY2jnscVl3Yhk" in
|
||||
request methodPost "/rpc/get_current_user" [auth]
|
||||
[json| {} |]
|
||||
`shouldRespondWith` ResponseMatcher {
|
||||
matchBody = Just [str|"postgrest_test_default_role"|]
|
||||
, matchStatus = 200
|
||||
, matchHeaders = []
|
||||
}
|
||||
|
||||
it "raises error (id=3)" $
|
||||
let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6M30.15Gy8PezQhJIaHYDJVLa-Gmz9T3sJnW66EKAYIsXc7c" in
|
||||
request methodPost "/rpc/get_current_user" [auth]
|
||||
[json| {} |]
|
||||
`shouldRespondWith` ResponseMatcher {
|
||||
matchBody = Just [str|{"hint":"Please contact administrator","details":null,"code":"P0001","message":"Disabled ID --> 3"}|]
|
||||
, matchStatus = 400
|
||||
, matchHeaders = []
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ testDbConn = "postgres://postgrest_test_authenticator@localhost:5432/postgrest_t
|
||||
|
||||
testCfg :: AppConfig
|
||||
testCfg =
|
||||
AppConfig testDbConn "postgrest_test_anonymous" Nothing "test" "localhost" 3000 (Just "safe") 10 Nothing (Just "test.block_bad_role") True
|
||||
AppConfig testDbConn "postgrest_test_anonymous" Nothing "test" "localhost" 3000 (Just "safe") 10 Nothing (Just "test.switch_role") True
|
||||
|
||||
testCfgNoJWT :: AppConfig
|
||||
testCfgNoJWT =
|
||||
|
||||
Vendored
+2
@@ -2,3 +2,5 @@ DROP DATABASE IF EXISTS postgrest_test;
|
||||
DROP ROLE IF EXISTS postgrest_test;
|
||||
CREATE USER postgrest_test createdb createrole;
|
||||
CREATE DATABASE postgrest_test OWNER postgrest_test;
|
||||
|
||||
ALTER DATABASE postgrest_test SET postgrest.claims.id = '-1';
|
||||
|
||||
Vendored
+1
-1
@@ -4,7 +4,7 @@ GRANT USAGE ON SCHEMA
|
||||
, test
|
||||
, jwt
|
||||
, "تست"
|
||||
TO postgrest_test_anonymous, bad_role;
|
||||
TO postgrest_test_anonymous;
|
||||
|
||||
-- Schema test objects
|
||||
SET search_path = test, "تست", pg_catalog;
|
||||
|
||||
Vendored
+2
-3
@@ -1,8 +1,7 @@
|
||||
DROP ROLE IF EXISTS postgrest_test_authenticator, postgrest_test_anonymous, postgrest_test_default_role, postgrest_test_author, bad_role;
|
||||
DROP ROLE IF EXISTS postgrest_test_authenticator, postgrest_test_anonymous, postgrest_test_default_role, postgrest_test_author;
|
||||
CREATE ROLE postgrest_test_authenticator WITH login noinherit;
|
||||
CREATE ROLE postgrest_test_anonymous;
|
||||
CREATE ROLE postgrest_test_default_role;
|
||||
CREATE ROLE postgrest_test_author;
|
||||
CREATE ROLE bad_role;
|
||||
|
||||
GRANT postgrest_test_anonymous, postgrest_test_default_role, postgrest_test_author, bad_role TO postgrest_test_authenticator;
|
||||
GRANT postgrest_test_anonymous, postgrest_test_default_role, postgrest_test_author TO postgrest_test_authenticator;
|
||||
|
||||
Vendored
+21
-4
@@ -237,15 +237,32 @@ SELECT jwt.sign(
|
||||
) r;
|
||||
$$;
|
||||
|
||||
create function block_bad_role() returns void
|
||||
language plpgsql as $$
|
||||
|
||||
CREATE OR REPLACE FUNCTION switch_role() RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
declare
|
||||
user_id text;
|
||||
begin
|
||||
if current_role = 'bad_role' then
|
||||
raise invalid_password using message = 'role is not allowed';
|
||||
user_id = current_setting('postgrest.claims.id')::text;
|
||||
if user_id = '1'::text then
|
||||
execute 'set local role postgrest_test_author';
|
||||
elseif user_id = '2'::text then
|
||||
execute 'set local role postgrest_test_default_role';
|
||||
elseif user_id = '3'::text then
|
||||
RAISE EXCEPTION 'Disabled ID --> %', user_id USING HINT = 'Please contact administrator';
|
||||
/* else */
|
||||
/* execute 'set local role postgrest_test_anonymous'; */
|
||||
end if;
|
||||
end
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION get_current_user() RETURNS text
|
||||
LANGUAGE sql
|
||||
AS $$
|
||||
SELECT current_user::text;
|
||||
$$;
|
||||
|
||||
--
|
||||
-- Name: reveal_big_jwt(); Type: FUNCTION; Schema: test; Owner: -
|
||||
--
|
||||
|
||||
Reference in New Issue
Block a user