Fix custom pre-request handler

Uses Ruslan's technique
This commit is contained in:
Joe Nelson
2016-09-27 23:17:08 -07:00
parent 06363ccc77
commit 5a166e8e80
7 changed files with 63 additions and 17 deletions
+3 -3
View File
@@ -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"
+33 -5
View File
@@ -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
View File
@@ -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 =
+2
View File
@@ -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';
+1 -1
View File
@@ -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;
+2 -3
View File
@@ -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;
+21 -4
View File
@@ -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: -
--