Question

Claude Code used supabase.auth.getUserById in the browser, TypeError

Solved · 281 viewsasked by jasper_t

On the profile page Claude wrote:

const { data } = await supabase.auth.getUserById(params.id)

Browser console:

When I told it, it changed it to supabase.auth.admin.getUserById which now gives a 403 / "User not allowed". I just want to show another user's name and avatar.

What I’ve tried

Asked Claude to check the docs, it said the method exists (it kind of does?). Tried both versions.

Comment
What do you actually need, the email too or only name/avatar? Changes the answer. jb_supa
Only name and avatar, it's a public profile card. jasper_t

3 answers

Marked as helpful by the asker
jb_supa

auth.admin.* exists, but only works with the service role key, on a server. In the browser you (correctly) have the anon key, hence "User not allowed". Please don't fix that by putting the service key in the client.

You don't need the auth API for this at all. Public profile data belongs in your own table:

create table public.profiles (
  id uuid primary key references auth.users on delete cascade,
  display_name text,
  avatar_url text
);
alter table public.profiles enable row level security;
create policy "profiles are public" on public.profiles for select using (true);
const { data } = await supabase.from('profiles').select('display_name, avatar_url').eq('id', params.id).single()

Fill it with a trigger on auth.users insert, the Supabase docs have the standard one.

Comment
Makes total sense now, the auth table isn't meant to be read by other users. Profiles table + trigger done. jasper_t
Bookmarking. Claude suggested the exact same admin call to me last week. kenji_w
sofia_gr

Tip for next time: when it claims a method exists, ask it to show the type from node_modules/@supabase/auth-js/dist/.... If it can't point at the definition, it's guessing.

Comment
Asked it that. It pointed at a file, the method was in the admin class. So yes. jasper_t
amir_h

Confirming the important part: the service role key bypasses RLS completely. If Claude ever suggests NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY, stop right there. Anything with NEXT_PUBLIC_ ends up in the browser bundle.

Comment