goetzrobin / spartan

Cutting-edge tools powering Angular full-stack development.
https://spartan.ng
MIT License
1.35k stars 143 forks source link

Easy access to Supabase current user inside tRPC #383

Closed mparpaillon closed 1 week ago

mparpaillon commented 1 week ago

Which scope/s are relevant/related to the feature request?

trpc

Information

I've started working with the Spartan stack at work and it's been great so far. One important aspect seems to be missing though. What would be the best way to access the current Supabase user inside tRPC in order to have some kind of auth middleware to properly query the DB.

Describe any alternatives/workarounds you're currently using

None so far

I would be willing to submit a PR to fix this issue

goetzrobin commented 1 week ago

I believe you would use Context for this in tRPC: https://trpc.io/docs/server/context

Let me know if that makes sense. Also, Nitro also supports middleware, so this would not be part of tRPC, but e.g. if you want global auth you can do it there: https://nitro.unjs.io/guide/routing#middleware

Let me know if this helps!

ismaelguerrib commented 1 week ago

Hey there !

I recently implemented this exact feature in a project using the Spartan stack.

Here’s how I accessed the current Supabase user inside tRPC and added auth middleware:

Supabase Auth Integration

Use supabase.auth to handle authentication and token management. After login, you can retrieve the access_token and store it in local storage or send it via headers. I choose to made a function to get the user token use it in trpc-client to add token in request header (last step).

Create Context

In tRPC, I created a context function that verifies the token from the request headers and retrieve the authenticated user with Supabase.

export const createContext = async ({ req }: { req: IncomingMessage }) => {
  const token = req.headers.authorization?.split(" ")[1];
  if (!token) return { user: null };
  const {
    data: { user },
    error,
  } = await supabaseClient.auth.getUser(token);
  if (error) {
    console.error("Supabase token verification failed:", error.message);
    return { user: null };
  }
  return { user };
};

Add Auth Middleware in tRPC route procedure.

I added a middleware in trpc.router to handle protected routes, where the user must be authenticated.

export const privateProcedure = t.procedure.use(({ ctx, next }) => {
  if (!ctx.user) {
    throw new Error("Error during token verification");
  }
  return next();});

Attach Token to Request Header

Include the token inside the tRPC Client in the Request Headers using Supabase. (see first step)

const trpcClient = createTRPCProxyClient<AppRouter>({
  links: [
    httpBatchLink({
      url: "/api/trpc",
      async headers() {
        return {
          authorization: `Bearer ${await SupabaseService.getToken()}`,
        };},}),],});
mparpaillon commented 1 week ago

Great thanks 🙏

goetzrobin commented 1 week ago

@ismaelguerrib would you be cool if we added this to the docs? Or even better do you want to add it to the docs?

ismaelguerrib commented 6 days ago

I can do it with pleasure !