Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Receiving warning when I'm not calling auth.getSession anywhere: Using is potentially insecure as it loads data directly from the storage medium (typically cookies) which may not be authentic. Prefer using supabase.auth.getUser() instead. To suppress this warning call supabase.auth.getUser() before you call supabase.auth.getSession() #755

Open
1 task
williamlmao opened this issue Mar 29, 2024 · 34 comments
Labels
bug Something isn't working

Comments

@williamlmao
Copy link

Bug report

  • [x ] I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

Despite not calling supabase.auth.getSession() anywhere in my code (as seen in screenshot), I get this warning nonstop in my server side terminal logs Using is potentially insecure as it loads data directly from the storage medium (typically cookies) which may not be authentic. Prefer using supabase.auth.getUser() instead. To suppress this warning call supabase.auth.getUser() before you call supabase.auth.getSession()

image

To Reproduce

import './globals.css'
import { Metadata } from 'next/types'
import { cookies } from 'next/headers'
import { createServerClient } from '@supabase/ssr'

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  const cookieStore = cookies()

  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        get(name: string) {
          return cookieStore.get(name)?.value
        },
      },
    }
  )

  const user = await supabase.auth.getUser()

  return (
    <html
      lang="en"
    >
      <div className="">text</div>
    </html>
  )
}

Expected behavior

I expect it to not give me the error since I'm using the function anywhere. It would be nice if it told me where in my code it detected the issue.

System information

  • OS: macOs
    "@supabase/ssr": "^0.1.0",
    "@supabase/supabase-js": "2.39.1",
@williamlmao williamlmao added the bug Something isn't working label Mar 29, 2024
@sahmed007
Copy link

Was just about to make an issue about this as well. Getting the same warnings despite not using it.

@beelzick
Copy link

I have the same issue

@przemyslaw-paziewski
Copy link

Same here

@AlanKeown
Copy link

I'm getting the warning but I am using it according to the docs for SSR in Sveltekit.

@caanyp24
Copy link

I'm getting the same warning and i am not using supabase.auth.getSession()

@Cheveniko
Copy link

Same issue here, happened just after I updated the Nextjs and eslint-config-next version from 14.0.4 to 14.1.4.
Before that I wasn't getting the warning.

@jdgamble555
Copy link

This is a huge problem and a pain. I don't want to contact the Supabase server to see if a user is logged in. This will slow down my app!

This is a supabase core problem it seems, as I can't find the error message in this package.

J

@Pluriscient
Copy link

+1 to the problem, only call getSession in the hooks.server.ts with the code from the tutorial (adapted to prevent setting cookies after request has been returned)

  let called = false;
  /**
   * A convenience helper so we can just call await getSession() instead const { data: { session } } = await supabase.auth.getSession()
   */

  event.locals.getSession = async () => {
    called = true;
    const {
      data: { user },
    } = await event.locals.supabase.auth.getUser();
    let {
      data: { session },
    } = await event.locals.supabase.auth.getSession();

    // solving the case if the user was deleted from the database but the browser still has a cookie/loggedin user
    // +layout.server.js will delete the cookie if the session is null
    if (user == null) {
      session = null;
    }

    return session;
  };
  if (!called) {
    await event.locals.getSession();
  }

@jdgamble555
Copy link

https://github.com/supabase/auth-js/blob/92fefbd49f25e20793ca74d5b83142a1bb805a18/src/GoTrueClient.ts#L936 - Here is the culprit. I just created a new issue and linked it.

@Pluriscient - I'm not sure why you're doing that, but it doesn't work. You're just calling getSession() an extra time? What is the goal here?

J

@Pluriscient
Copy link

https://github.com/supabase/auth-js/blob/92fefbd49f25e20793ca74d5b83142a1bb805a18/src/GoTrueClient.ts#L936 - Here is the culprit. I just created a new issue and linked it.

@Pluriscient - I'm not sure why you're doing that, but it doesn't work. You're just calling getSession() an extra time? What is the goal here?

J

The console log actually asked to call getUser before getSession to suppress the warning. The if (!called) escape was included due to this issue

@jdgamble555
Copy link

Looks like that fix doesn't work

@Pluriscient
Copy link

Pluriscient commented Mar 31, 2024

Looks like that fix doesn't work

YMMV, but I haven't seen a crash due to setCookies since. This error popped up the day after when we ran a fresh npm install, though I don't see the ssr package being updated there.

@jdgamble555
Copy link

For my purposes this hack solves it. However, I am only using session to detect if there is a session, not get session data.

event.locals.getSession = async () => {

  const { data: { user } } = await event.locals.supabase.auth.getUser();

  if (user === null) {
    return null;
  }

  const session = { user };

  return session as Session;
};

My problem with this approach is that I need to check for a user session on my non logged in page. So I can give different results whether or not a user is logged in (likes, votes, etc on a post). This means even for non-logged-in users, I have to send an extra fetch request to Supabase in order to display my data. Perhaps it should only call getUser() if there is a session, and then verify it on the Supabase server.

This is problematic for sure.

J

@cowboycodr
Copy link

I have the same issue as well. Makes debugging in the console an absolute nightmare.

@hmnd
Copy link

hmnd commented Apr 9, 2024

Just chiming in with my vote in support of fixing this issue... here's what I said in another thread:

I understand the intention with this warning, but it's impossible to silence when I know I'm properly verifying with getUser. In my case, I need to use it with createSupabaseLoadClient from auth-helpers, and because it serializes the session as JSON, I get a warning every time I call that function or eg. spread the session into a new object, etc.

At the very least, could the warning only be displayed once per session or could we please have an option to disable it? I see that now it's gated behind a non-existent __suppressUserWarning key on session.

For reference the warning I'm getting is below. It's a different one from the one this discussion originally addresses:

Using the user object as returned from supabase.auth.getSession() or from some supabase.auth.onAuthStateChange() events could be insecure! This value comes directly from the storage medium (usually cookies on the server) and many not be authentic. Use supabase.auth.getUser() instead which authenticates the data by contacting the Supabase Auth server.

@ixxie
Copy link

ixxie commented May 5, 2024

As somebody just setting up a SvelteKit project with Supabase, this is quite confusing: copy-pasting code from your tutorial results in a warning about best practices! One more vote for a fix!

@j4w8n
Copy link

j4w8n commented May 9, 2024

Oops! I created an issue for this a couple of weeks after yours was created: supabase/auth-js#888

@sgriff96
Copy link

Should we open a separate ticket about addressing the incorrect code in the documentation for sveltekit? As @ixxie said it's very confusing that the documentation is incorrect and has us do something wrong/unsafe.

@j4w8n
Copy link

j4w8n commented May 26, 2024

Should we open a separate ticket about addressing the incorrect code in the documentation for sveltekit? As @ixxie said it's very confusing that the documentation is incorrect and has us do something wrong/unsafe.

You can, but there is currently no Supabase-recommended way to set up Sveltekit while avoiding these warnings. It's unfortunate, but that's where we are right now.

And you aren't doing anything wrong or unsafe, but rather, there are some unintended side-effects of their warning implementation.

@sgriff96
Copy link

You can, but there is currently no Supabase-recommended way to set up Sveltekit while avoiding these warnings. It's unfortunate, but that's where we are right now.

And you aren't doing anything wrong or unsafe, but rather, there are some unintended side-effects of their warning implementation.

Oh okay. So it is safe to access the session from locals whenever I want now because we used safeGetSession in the hooks.server.ts?

@j4w8n
Copy link

j4w8n commented May 26, 2024

You can, but there is currently no Supabase-recommended way to set up Sveltekit while avoiding these warnings. It's unfortunate, but that's where we are right now.
And you aren't doing anything wrong or unsafe, but rather, there are some unintended side-effects of their warning implementation.

Oh okay. So it is safe to access the session from locals whenever I want now because we used safeGetSession in the hooks.server.ts?

It's safe as long as you heed the warning (that some of us shouldn't be seeing): don't trust info from session.user on the server side - even after calling safeGetSession (SvelteKit). What they're implying with that function is you should use the returned user data instead of session.user.

I don't want the scope of this issue to grow beyond it's original purpose, but if you're wanting to understand why all of this has come up, read this. If you have further questions or comments about it, I'd recommend asking them on the discussion rather than this issue.

@sgriff96
Copy link

sgriff96 commented May 29, 2024

It's safe as long as you heed the warning (that some of us shouldn't be seeing): don't trust info from session.user on the server side - even after calling safeGetSession (SvelteKit). What they're implying with that function is you should use the returned user data instead of session.user.

I don't want the scope of this issue to grow beyond it's original purpose, but if you're wanting to understand why all of this has come up, read this. If you have further questions or comments about it, I'd recommend asking them on the discussion rather than this issue.

Ohh understood then, thank you for the clarification!

@thedelanyo
Copy link

It's safe as long as you heed the warning (that some of us shouldn't be seeing): don't trust info from session.user on the server side - even after calling safeGetSession (SvelteKit). What they're implying with that function is you should use the returned user data instead of session.user.
I don't want the scope of this issue to grow beyond it's original purpose, but if you're wanting to understand why all of this has come up, read this. If you have further questions or comments about it, I'd recommend asking them on the discussion rather than this issue.

Ohh understood then, thank you for the clarification!

But how do we to least make the warning disappears? It makes reading (debugging) using server logs, a nightmare.

@j4w8n
Copy link

j4w8n commented Jun 22, 2024

But how do we to least make the warning disappears? It makes reading (debugging) using server logs, a nightmare.

@delanyoyoko, there’s no native Supabase way to do this if you're using SvelteKit. Some people have created ways to silence the logs with custom console.log code. Another option is to verify and decode the access token, then return your own validated session - which I have an example of at https://github.com/j4w8n/sveltekit-supabase-ssr

@jdgamble555
Copy link

@j4w8n - Then your code is flawed, not SvelteKit. Make an option to turn it off. There is a reason there are probably over 100 complaints to this over three different Supabase packages. If you can't make a warning that properly works due to the limitations of SvelteKit, then don't make the warning, or make an option to silence it. At the VERY LEAST, it should not be able to display the warning more than once.

It was a HUGE oversight for the Supabase team to build this without proper testing.

J

@j4w8n
Copy link

j4w8n commented Jun 23, 2024

@jdgamble555 I'm with you, and I understand the frustration. There should've been more testing, and, in my opinion, this warning should've been rolled back by now.

Having said that, I was not involved in this code decision. I've contributed to the auth codebase, but I'm not part of the Supabase team; nor am I a collaborator. I'm sorry if I've implied or lead anyone to believe that I'm more involved than I actually am. Seeing my contributor tag, and possibly heavy involvement on Discord, can understandbly cause people to conclude what you have; because it's the same tag hf has, yet they are heavily involved with code decisions and are a part of the auth team.

I hope this gets resolved soon because it's clearly harming dx.

@jdgamble555
Copy link

@j4w8n - Fair enough. I wasn't necessarily venting towards you, just at the Supabase team in general for letting this issue get out of hand. I would imagine there is a way to solve this issue without just patching the problem with hacks. I think most people use the code from the examples, not insecurely.

J

@thedelanyo
Copy link

But how do we to least make the warning disappears? It makes reading (debugging) using server logs, a nightmare.

@delanyoyoko, there’s no native Supabase way to do this if you're using SvelteKit. Some people have created ways to silence the logs with custom console.log code. Another option is to verify and decode the access token, then return your own validated session - which I have an example of at https://github.com/j4w8n/sveltekit-supabase-ssr

This works fine. The logs are gone, session is validated and my dev server seem pretty fast. Thanks.

@mstibbard
Copy link

But how do we to least make the warning disappears? It makes reading (debugging) using server logs, a nightmare.

@delanyoyoko, there’s no native Supabase way to do this if you're using SvelteKit. Some people have created ways to silence the logs with custom console.log code. Another option is to verify and decode the access token, then return your own validated session - which I have an example of at https://github.com/j4w8n/sveltekit-supabase-ssr

I understand the warning is showing unnecessarily, but I'm confused how & why @j4w8n's implementation manages to not trigger the warnings when the SSR SvelteKit guide code does? It appears both implementations call getSession in a similar manner and neither implementation uses the unvalidated output.

@thedelanyo
Copy link

But how do we to least make the warning disappears? It makes reading (debugging) using server logs, a nightmare.

@delanyoyoko, there’s no native Supabase way to do this if you're using SvelteKit. Some people have created ways to silence the logs with custom console.log code. Another option is to verify and decode the access token, then return your own validated session - which I have an example of at https://github.com/j4w8n/sveltekit-supabase-ssr

I understand the warning is showing unnecessarily, but I'm confused how & why @j4w8n's implementation manages to not trigger the warnings when the SSR SvelteKit guide code does? It appears both implementations call getSession in a similar manner and neither implementation uses the unvalidated output.

Well I think it's not about calling the "getSession" method. Whether getSession is called or not, the message will be logged.

Even when you solely rely on user, thereby just calling getUser, your console will be flooded.

I guess the log is a bug sort, probably supposed to logged once, if the user is triggered on getSession.

@j4w8n
Copy link

j4w8n commented Jun 25, 2024

I understand the warning is showing unnecessarily, but I'm confused how & why @j4w8n's implementation manages to not trigger the warnings when the SSR SvelteKit guide code does? It appears both implementations call getSession in a similar manner and neither implementation uses the unvalidated output.

The short answer is: Because both SSR and SvelteKit code are accessing session.user at some point. The Supabase guide is preserving the Proxied version of session, allowing the logs to trigger; while I'm creating my own version of it.

  • SSR is doing it by calling JSON.stringify(session) in +layout.ts
  • SvelteKit is doing it when validating that we're returning POJOs from certain files

REF: supabase/auth-js#873 (comment)

@jdgamble555
Copy link

I don't understand why this can't be fixed under the hood.

@EmilienKopp
Copy link

EmilienKopp commented Jul 1, 2024

Leaving this here for whoever does not want to do a custom token validation workaround or still hasn't reworked their code.
This will at least silence the warnings. Importing that in hooks.server.ts did the trick.

const originalConsoleWarn = console.warn;

console.warn = function (...args) {
  const shouldLog = args.every((arg) => {
    if (typeof arg === 'string') {
      return !arg.includes('Using the user object');
    }
    return true;
  });
  if(shouldLog) {
    originalConsoleWarn.apply(console, args);
  }
};

@kvetoslavnovak
Copy link

kvetoslavnovak commented Jul 8, 2024

Sharing my implementation in SvelteKit, This setup mainly seems to solve the infamous user object warning logs. Also uses locals to store/pass the session and user which I consider more secure (see).

// hooks.server.js
import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public'
import { createServerClient } from '@supabase/ssr'

export const handle = async ({ event, resolve }) => {
  event.locals.supabaseServerClient = createServerClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
      cookies: {
          getAll() {
              return event.cookies.getAll()
          },
          setAll(cookiesToSet) {
              cookiesToSet.forEach(({ name, value, options }) =>
                  event.cookies.set(name, value, { ...options,path: '/' })
              )
          },
      },
  })


  const getSessionAndUser = async () => {
      const { data: { session } } = await event.locals.supabaseServerClient.auth.getSession()
      if (!session) {
          return {
              session: null,
              user: null
          }
      }

      const { data: { user }, error } = await event.locals.supabaseServerClient.auth.getUser()
      if (error) {
          // JWT validation has failed
          return {
              session: null,
              user: null
          }
      }

      delete session.user
      const sessionWithUserFromUser = { ...session, user: {...user} }

      return { session: sessionWithUserFromUser, user }
  }

  const { session, user } = await getSessionAndUser()

  event.locals.session = session
  event.locals.user = user

  return resolve(event, {
      filterSerializedResponseHeaders(name) {
          return name === 'content-range' || name === 'x-supabase-api-version'
      },
  })
}
// +layout.server.js
export const load = async (event) => {
// covering the case when the user was deleted from the database, the cookie needs to be deleted in the browser
  if (event.locals.session == null) {
    event.cookies.delete(event.locals.supabaseServerClient.storageKey, { path: '/' });
  }

  return {
      session: event.locals.session,
      user: event.locals.user
  };
};
// +layout.js
import { PUBLIC_SUPABASE_ANON_KEY, PUBLIC_SUPABASE_URL } from '$env/static/public'
import { createBrowserClient, createServerClient, isBrowser } from '@supabase/ssr'

export const load = async ({ fetch, data, depends }) => {
  depends('supabase:auth')

  const supabase = isBrowser()
    ? createBrowserClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
        global: {
          fetch,
        },
      })
    : createServerClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
        global: {
          fetch,
        },
        cookies: {
          getAll() {
            return data.cookies
          },
        },
      })

      const session = isBrowser()
      ? (await supabase.auth.getSession()).data.session 
      : data.session

  return {
    supabase,
    session,
    user: data.user
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests