|
| 1 | +-- Tests for the custom_access_token_hook that adds sso_not_satisfied claim. |
| 2 | +create function tests.test_sso_access_token_hook() |
| 3 | +returns setof text as $$ |
| 4 | +declare |
| 5 | + provider_acme uuid = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'; |
| 6 | + alice_id uuid = '11111111-1111-1111-1111-111111111111'; |
| 7 | + result jsonb; |
| 8 | +begin |
| 9 | + -- Setup: test user. |
| 10 | + insert into auth.users (id, email) values |
| 11 | + (alice_id, 'alice@example.com') |
| 12 | + on conflict do nothing; |
| 13 | + |
| 14 | + -- Setup: SSO provider for acmeCo. |
| 15 | + insert into auth.sso_providers (id) values (provider_acme) |
| 16 | + on conflict do nothing; |
| 17 | + |
| 18 | + -- Tenants: acmeCo has SSO configured, openCo does not. |
| 19 | + delete from tenants; |
| 20 | + insert into tenants (tenant, sso_provider_id) values |
| 21 | + ('acmeCo/', provider_acme), |
| 22 | + ('openCo/', null); |
| 23 | + |
| 24 | + -- Alice has grants on both tenants, no SSO identity yet. |
| 25 | + delete from user_grants; |
| 26 | + insert into user_grants (user_id, object_role, capability) values |
| 27 | + (alice_id, 'acmeCo/', 'admin'), |
| 28 | + (alice_id, 'openCo/', 'admin'); |
| 29 | + |
| 30 | + delete from auth.identities where user_id = alice_id; |
| 31 | + |
| 32 | + -- No SSO identity — should get sso_not_satisfied with acmeCo's provider. |
| 33 | + select public.custom_access_token_hook(jsonb_build_object( |
| 34 | + 'user_id', alice_id, |
| 35 | + 'claims', jsonb_build_object('sub', alice_id) |
| 36 | + )) into result; |
| 37 | + |
| 38 | + return next is( |
| 39 | + result->'claims'->'sso_not_satisfied', |
| 40 | + to_jsonb(provider_acme), |
| 41 | + 'Non-SSO user on SSO tenant gets sso_not_satisfied' |
| 42 | + ); |
| 43 | + |
| 44 | + -- Add SSO identity — sso_not_satisfied should disappear. |
| 45 | + insert into auth.identities (user_id, provider, provider_id, identity_data) values |
| 46 | + (alice_id, 'sso:' || provider_acme::text, provider_acme::text, '{}'::jsonb); |
| 47 | + |
| 48 | + select public.custom_access_token_hook(jsonb_build_object( |
| 49 | + 'user_id', alice_id, |
| 50 | + 'claims', jsonb_build_object('sub', alice_id) |
| 51 | + )) into result; |
| 52 | + |
| 53 | + return next ok( |
| 54 | + result->'claims'->'sso_not_satisfied' is null, |
| 55 | + 'SSO user on own tenant has no sso_not_satisfied claim' |
| 56 | + ); |
| 57 | + |
| 58 | + -- Only open-tenant grants: no sso_not_satisfied. |
| 59 | + delete from user_grants where user_id = alice_id; |
| 60 | + delete from auth.identities where user_id = alice_id; |
| 61 | + insert into user_grants (user_id, object_role, capability) values |
| 62 | + (alice_id, 'openCo/', 'admin'); |
| 63 | + |
| 64 | + select public.custom_access_token_hook(jsonb_build_object( |
| 65 | + 'user_id', alice_id, |
| 66 | + 'claims', jsonb_build_object('sub', alice_id) |
| 67 | + )) into result; |
| 68 | + |
| 69 | + return next ok( |
| 70 | + result->'claims'->'sso_not_satisfied' is null, |
| 71 | + 'User with only open-tenant grants has no sso_not_satisfied claim' |
| 72 | + ); |
| 73 | + |
| 74 | + -- Sub-prefix grant on acmeCo/reports/ should still trigger sso_not_satisfied. |
| 75 | + delete from user_grants where user_id = alice_id; |
| 76 | + insert into user_grants (user_id, object_role, capability) values |
| 77 | + (alice_id, 'acmeCo/reports/', 'read'); |
| 78 | + |
| 79 | + select public.custom_access_token_hook(jsonb_build_object( |
| 80 | + 'user_id', alice_id, |
| 81 | + 'claims', jsonb_build_object('sub', alice_id) |
| 82 | + )) into result; |
| 83 | + |
| 84 | + return next is( |
| 85 | + result->'claims'->'sso_not_satisfied', |
| 86 | + to_jsonb(provider_acme), |
| 87 | + 'Sub-prefix grant on acmeCo/reports/ triggers sso_not_satisfied' |
| 88 | + ); |
| 89 | + |
| 90 | + return; |
| 91 | +end |
| 92 | +$$ language plpgsql; |
0 commit comments