Insert into users.profiles right after signUp() (email confirmation flow) — request goes as anon, 40
Context
* Nuxt 3 + Nuxt Supabase client
* Email confirmation enabled
* Table:
users.profiles
with FK to auth.users(id,email)
and RLS
* Policies exist for SELECT/UPDATE/INSERT
; INSERT has WITH CHECK (id = auth.uid())
* Grants: schema USAGE
+ INSERT/SELECT/UPDATE
to authenticated
Schema (short)
Client code (where I try to insert names right after signUp):
3 Replies
Observed behavior
* The POST to
/rest/v1/profiles
is 401.
* My gateway logs decode the JWT as role: "anon"
, session_id: null
, subject: null
.
* Makes sense because with email confirmation enabled, signUp()
returns no session I guess, so the client has no access token to attach.
* RLS & grants are fine (SELECT/UPDATE work once the user is logged in); this particular INSERT goes out as anon
→ rejected.
What I’d like to do
* Insert the initial profile row immediately after signUp, before the user verifies their email (so we can store first_name/last_name
captured during registration).
Questions
1. Is there a supported way to “insert as the user” right after signUp()
when email confirmation is enabled)?
2. If not, is the recommended pattern one of the following?
* DB trigger on auth.users
(server-side, SECURITY DEFINER
) that inserts into users.profiles
and pulls names from raw_user_meta_data
(i.e., pass data: { first_name, last_name }
in signUp.options
).
* Server-side upsert using a Supabase service client (Edge Function / server route) protected by Turnstile/CSRF. (But then we must carefully guard it, since it bypasses RLS. I try to only use the Service Role when it is really really necessary).
* Defer the insert until after email verification (first authenticated page load), then upsert as the user.
* Use auth.admin.createUser
(server-side) with email_confirm
to create and seed the profile in one go (but we do want standard email confirmation UX).
3. Any caveats with the trigger approach (e.g., search_path
, SECURITY DEFINER
, RLS interaction, defaulting id
to auth.uid()
vs explicit NEW.id
) that I should be aware of?
Notes
* Sequences: none in users
schema.
* Schema USAGE
: authenticated = true
, anon = false
.
* Policies confirm INSERT WITH CHECK (id = auth.uid())
.
Goal
* Keep strict RLS (no anon
inserts), but still capture and persist first/last names at registration time without waiting for the user to verify/sign in.
Thanks for any guidance or best-practice pointers!SignUp if you are doing email confirm does not return a user session. It will redirect to your code after they access the email. There is user data but no session.
You could use the data option on signup to send in data to user_metadata and then in a trigger function on auth.users insert to your profile table. Note though if you ever plan to use OAuth this is not possible so you would have to solve getting the data after they are confirmed anyway.
Thanks a lot, that clears it up! Appreciate the guidance!