supabase icon indicating copy to clipboard operation
supabase copied to clipboard

serverSupabaseUser not working on server route when app is deployed to Netlify.

Open ninjaaaaah opened this issue 2 years ago • 8 comments

Version

@nuxtjs/supabase: "^0.1.25" nuxt: "^3.0.0-rc.11"

Issue

I'm trying to deploy my Nuxt 3 app which renders client side to Netlify and locally, Supabase Auth works as intended.

However, upon deploying the app to Netlify, when I call server routes that needs user validation, suddenly the serverSupabaseUser returns undefined even though the user is logged in since a session was obtained from Supabase.

I'm wondering whether I did something wrong on my end or if I'm missing something.

nuxt.config.js

import { defineNuxtConfig } from 'nuxt/config';

export default defineNuxtConfig({
  ssr: false,
  target: 'static',
  modules: [
    '@nuxtjs/supabase',
    ...
  ],
  ...
});

server/api/profile.get.js

import { serverSupabaseUser } from '#supabase/server';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export default defineEventHandler(async (event) => {
  const user = await serverSupabaseUser(event);
  if (!user) {
    throw new Error('Not authorized');
  }

  const profile = await prisma.profiles.findUnique({
    where: {
      id: user.id,
    },
  });
  return profile;
});

pages/login.vue

async function login() {
  const { error } = await client.auth.signIn({
    email: email.value,
    password: password.value,
    initialCache: false,
  });
  if (error) $toast(error.message, 'error');

  $toast('Successfully logged in!', 'success');
  const { data: profile } = await useFetch('/api/profile');
  store.setProfile(profile.value);
}

Fetch result: image

Any help provided will be appreciated. Thanks!

ninjaaaaah avatar Sep 22 '22 15:09 ninjaaaaah

Could you check if the correct headers are sent to the API endpoint when deployed?

atinux avatar Sep 22 '22 17:09 atinux

On running netlify dev locally, I see the sb-access-token included in the request header.

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Cookie: sb-access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNjYzODcwMjQ2LCJzdWIiOiI2MGM3YjI0ZC0wOTE5LTQwYTctOWQwYy1jYTI4ZWU5ZGJlOTEiLCJlbWFpbCI6Imx1emFkYWphcnJlZEBnbWFpbC5jb20iLCJwaG9uZSI6IiIsImFwcF9tZXRhZGF0YSI6eyJwcm92aWRlciI6ImVtYWlsIiwicHJvdmlkZXJzIjpbImVtYWlsIl19LCJ1c2VyX21ldGFkYXRhIjp7fSwicm9sZSI6ImF1dGhlbnRpY2F0ZWQiLCJzZXNzaW9uX2lkIjoiNGE4MWVmNDAtNWU4MS00N2NkLThiNjItMDU4ODZkMGVlMWFhIn0.Gs9EtBQV5JKNgeJ249HmdTIjB4ZyYKNvA-mPFb6qSxs
Host: localhost:8888
If-None-Match: W/"2f8-ja+LhF5HQLhq4kdO7AmNYEEC5Vc"
Referer: http://localhost:8888/transactions
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="104", "Opera GX";v="90"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36 OPR/90.0.4480.100

However, it isn't there on the deployed app.

:authority: thryft.netlify.app
:method: GET
:path: /api/users
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
referer: https://thryft.netlify.app/transactions
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="104", "Opera GX";v="90"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-origin
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36 OPR/90.0.4480.100

I've also noticed that even my auth middleware doesn't work as intended as after reloading the page, the user will be redirected back to the login page.

middleware/auth.js

export default defineNuxtRouteMiddleware(async (to) => {
  const user = useSupabaseUser();

  if (to.path === '/login' || to.path === '/signup') {
    if (!user.value) {
      return;
    }
    return '/';
  }
  if (!user.value) {
    return '/login';
  }
});

ninjaaaaah avatar Sep 22 '22 17:09 ninjaaaaah

I think I figured out the problem. It really is on the sb-access-token cookie that's missing from the request header. I tried copying the access token I got in my local development to the deployment site and the route guard and request guard works as intended!

However, is there any way to configure this so that Supabase will pass the appropriate cookies back to the Deployed app at Netlify?

ninjaaaaah avatar Sep 22 '22 18:09 ninjaaaaah

This might be the solution: https://v3.nuxtjs.org/getting-started/data-fetching#example-pass-client-headers-to-the-api

Edit: not sure since it is for SSR…

atinux avatar Sep 22 '22 20:09 atinux

I'm getting the same issue. It works on localhost but not when I deploy to Netlify. The sb-access-token field is not set in my cookies but I can see the access token in my localstorage. So I agree with @ninjaaaaah that the sb-access-token doesnt appear to be set. But again, works on localhost, just not when I deploy it to Netlify

EDIT: I got it to work as expected if I set the "sb-access-token" after a user logs in manually using useCookie() in Nuxt and pulling the access token from the session when the page is loaded but this feels super hacky.

Another dev and I were collaborating and he had a great point - the sb-access-token is being set with attributes HttpOnly and Secure, but there’s no SameSite attribute so it’s defaulting to “Lax”. Because of this plus the cookie coming from a different domain (supabase), the cookie is not being set at all. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#lax

Is there anyway to set the cookie on the library side using the onAuthStateChange function? Just a thought but yall probably know better than me

zkschmitz avatar Sep 23 '22 02:09 zkschmitz

You can use the supabase.client option in the nuxt.config: https://supabase.nuxtjs.org/get-started#client

See the available options: https://github.com/supabase/supabase-js/blob/master/src/lib/types.ts

You have cookieOptions or maybe try localStorage?

atinux avatar Sep 23 '22 07:09 atinux

Indeed, I've reproduced it here: https://github.com/larbish/nuxt3-supabase-with-server-routes. Don't know what's going on with Netlify, need to dig into it. However, as a temporary fix you can deploy on Vercel as it is working as expected, you can check it here: https://nuxt3-supabase-with-server-routes-6ki7.vercel.app

larbish avatar Sep 23 '22 12:09 larbish

Weird; thanks for the workaround. I've got it working by manually setting the cookie when a user logs in using the onAuthStateChange function in a plugin for now, and it seems to work.

zkschmitz avatar Sep 23 '22 16:09 zkschmitz

Closing in favor of #101 (merging all Netlify issues)

larbish avatar Oct 27 '22 08:10 larbish