supabase / auth-js

An isomorphic Javascript library for Supabase Auth.
MIT License
318 stars 152 forks source link

`getSession` should validate the session with the JWT_SECRET #908

Open remorses opened 1 month ago

remorses commented 1 month ago

The function supabase.auth.getSession() is basically a vulnerability in every Supabase app, a lot of people are currently using it in the server, telling users to use getUser in a warning as currently happens is not enough. It would also mean calling supabase API every time an user does a request, which slow everything down and makes the use of JWTs pointless.

What you could do instead is to validate the jwt inside getSession.

This change would require passing the jwt secret as an argument when creating the client, then you would log the warning if the user doesn't pass the jwt secret.

example:

const supabase = createServerClient(
        env.PUBLIC_SUPABASE_URL!,
        env.PUBLIC_SUPABASE_ANON_KEY!,
        {
            jwtSecret: process.env.SUPABASE_JWT_SECRET,
       }
)
remorses commented 1 month ago

I just got an idea to fix this without having users change their code:

  1. Add a field in the jwt that is a signature created with a global Supabase public key. This signature would contain the project ref
  2. In getSession, validate this field with the Supabase public key and check that the project ref is right (so different projects cannot create JWTs that work in other apps)
  3. When creating a new token, add the signature. I think this should be possible because Supabase controls the JWT creation process and is done on your servers.
  4. Only do the signature check if the token was created since this change took effect, this can be done because a JWT has an expiration limit which means you cannot spoof a JWT by changing the creation date.
j4w8n commented 1 month ago

They're releasing asymmetric jwts "soon," but I've not seen a public timeline.

As part of that, I'm hoping they build in the functionality that you're talking about - pass the public jwt key either to the client or the getSession() method itself.