Use the following instructions in a Supabase project to add user_role to jwt token generated at login.
Create a new role "app_role" in Supabase
CREATE TYPE app_role AS ENUM ('admin', 'editor', 'user');
The user_roles table is used to connect the logging in user to a user_role. The auth hook uses this table to extract the user_role.
create table public.user_roles (
id bigint generated by default as identity not null,
user_id uuid not null,
role public.app_role not null default 'user',
constraint user_roles_pkey primary key (id),
constraint user_roles_user_id_role_key unique (user_id, role),
constraint user_roles_user_id_fkey foreign KEY (user_id) references auth.users (id) on delete CASCADE
) TABLESPACE pg_default;
Create a new Stored Procedure in the public schema named "custom_access_token_hook".
CREATE OR REPLACE FUNCTION public.custom_access_token_hook(event jsonb)
RETURNS jsonb
LANGUAGE plpgsql
AS $$
declare
claims jsonb;
user_role public.app_role;
begin
-- Fetch the user role in the user_roles table
select role into user_role from public.user_roles where user_id = (event->>'user_id')::uuid;
claims := event->'claims';
if user_role is not null then
-- Set the claim
claims := jsonb_set(claims, '{user_role}', to_jsonb(user_role));
else
claims := jsonb_set(claims, '{user_role}', 'null');
end if;
-- Update the 'claims' object in the original event
event := jsonb_set(event, '{claims}', claims);
-- Return the modified or original event
return event;
end;
$$;
Access will have to be granted to the hook for it to function.
GRANT EXECUTE ON FUNCTION public.custom_access_token_hook TO supabase_auth_admin;
GRANT USAGE ON SCHEMA public TO supabase_auth_admin;
REVOKE EXECUTE ON FUNCTION public.custom_access_token_hook FROM authenticated, anon, public;
GRANT ALL ON TABLE public.user_roles TO supabase_auth_admin;
REVOKE ALL ON TABLE public.user_roles FROM authenticated, anon, public;
The following items need to be added to the docker-compose.yml file. Add to the bottom of the Auth->Environment section.
GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_ENABLED: "true"
GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_URI: "pg-functions://postgres/public/custom_access_token_hook"
Docker compose will have to be restart inorder for the hook to work with the user login process.
docker compose down
docker compose up -d