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
|
JWTClaims claims -> do
|
||||||
-- role claim defaults to anon if not specified in jwt
|
-- role claim defaults to anon if not specified in jwt
|
||||||
let setClaims = claimsToSQL (M.union claims (M.singleton "role" anon))
|
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
|
app req
|
||||||
where
|
where
|
||||||
anon = String . toS $ configAnonRole conf
|
anon = String . toS $ configAnonRole conf
|
||||||
customReqCheck = maybeToList $ (\f -> "select " <> toS f <> "();")
|
customReqCheck = (\f -> "select " <> toS f <> "();") <$> configReqCheck conf
|
||||||
<$> configReqCheck conf
|
|
||||||
unauthed message = responseLBS unauthorized401
|
unauthed message = responseLBS unauthorized401
|
||||||
[ ctToHeader CTApplicationJSON
|
[ ctToHeader CTApplicationJSON
|
||||||
, ( "WWW-Authenticate"
|
, ( "WWW-Authenticate"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
module Feature.AuthSpec where
|
module Feature.AuthSpec where
|
||||||
|
|
||||||
-- {{{ Imports
|
-- {{{ Imports
|
||||||
|
import Text.Heredoc
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
import Test.Hspec.Wai
|
import Test.Hspec.Wai
|
||||||
import Test.Hspec.Wai.JSON
|
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
|
it "should fail when jwt contains no claims" $ do
|
||||||
let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.lu-rG8aSCiw-aOlN0IxpRGz5r7Jwq7K9r3tuMPUpytI"
|
let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.lu-rG8aSCiw-aOlN0IxpRGz5r7Jwq7K9r3tuMPUpytI"
|
||||||
request methodGet "/authors_only" [auth] ""
|
request methodGet "/authors_only" [auth] ""
|
||||||
@@ -124,3 +120,35 @@ spec = describe "authorization" $ do
|
|||||||
_ <- request methodPost "/rpc/problem" [auth] ""
|
_ <- request methodPost "/rpc/problem" [auth] ""
|
||||||
request methodGet "/authors_only" [auth] ""
|
request methodGet "/authors_only" [auth] ""
|
||||||
`shouldRespondWith` 200
|
`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
|
||||||
testCfg =
|
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 :: AppConfig
|
||||||
testCfgNoJWT =
|
testCfgNoJWT =
|
||||||
|
|||||||
Vendored
+2
@@ -2,3 +2,5 @@ DROP DATABASE IF EXISTS postgrest_test;
|
|||||||
DROP ROLE IF EXISTS postgrest_test;
|
DROP ROLE IF EXISTS postgrest_test;
|
||||||
CREATE USER postgrest_test createdb createrole;
|
CREATE USER postgrest_test createdb createrole;
|
||||||
CREATE DATABASE postgrest_test OWNER postgrest_test;
|
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
|
, test
|
||||||
, jwt
|
, jwt
|
||||||
, "تست"
|
, "تست"
|
||||||
TO postgrest_test_anonymous, bad_role;
|
TO postgrest_test_anonymous;
|
||||||
|
|
||||||
-- Schema test objects
|
-- Schema test objects
|
||||||
SET search_path = test, "تست", pg_catalog;
|
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_authenticator WITH login noinherit;
|
||||||
CREATE ROLE postgrest_test_anonymous;
|
CREATE ROLE postgrest_test_anonymous;
|
||||||
CREATE ROLE postgrest_test_default_role;
|
CREATE ROLE postgrest_test_default_role;
|
||||||
CREATE ROLE postgrest_test_author;
|
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;
|
) 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
|
begin
|
||||||
if current_role = 'bad_role' then
|
user_id = current_setting('postgrest.claims.id')::text;
|
||||||
raise invalid_password using message = 'role is not allowed';
|
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 if;
|
||||||
end
|
end
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_current_user() RETURNS text
|
||||||
|
LANGUAGE sql
|
||||||
|
AS $$
|
||||||
|
SELECT current_user::text;
|
||||||
|
$$;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: reveal_big_jwt(); Type: FUNCTION; Schema: test; Owner: -
|
-- Name: reveal_big_jwt(); Type: FUNCTION; Schema: test; Owner: -
|
||||||
--
|
--
|
||||||
|
|||||||
Reference in New Issue
Block a user