supabase / supabase-js

An isomorphic Javascript client for Supabase. Query your Supabase database, subscribe to realtime events, upload and download files, browse typescript examples, invoke postgres functions via rpc, invoke supabase edge functions, query pgvector.
https://supabase.com
MIT License
2.86k stars 220 forks source link

Large Auth Cookie Split Into 2 Causing Realtime Failures, etc #963

Closed ghost closed 3 months ago

ghost commented 3 months ago

Bug report

Describe the bug

Using Keycloak, cookies can be quite large. This has been an issue already (see https://github.com/supabase/realtime/issues/761 and https://github.com/supabase/realtime/pull/762) with some fixes implemented already (see, e.g., https://github.com/supabase/cli/issues/1784).

I am noticing that at a certain character length, supabase-js is splitting authentication cookies into two (see screenshots below). Not only does this ignore any custom cookie name, but it also creates errors when tying to retrieve the cookie manually, as well as, I suspect, issues with realtime data connections automatically refreshing (it would explain why I am experiencing the open issue here https://github.com/supabase/realtime-js/issues/274 along with possibly other users).

I am using the recommended approach for Next.js, of using @supabase/ssr (https://github.com/supabase/auth-helpers/blob/main/packages/ssr/src/createBrowserClient.ts).

Update 1

It looks like the first cookie has an exact length of 3180. This seems to coincide with the chunker used by supabase/ssr:

const MAX_CHUNK_SIZE = 3180;

https://github.com/supabase/auth-helpers/blob/a68e78bc9cb863217db75ac561de93874a85aafa/packages/ssr/src/utils/chunker.ts#L6

I'm wondering if I should just implement my own version of createBrowserClient that I can use to strip out unnecessry information from the JSON object... wondering what fields could be removed? The total length of the cookie I paste below is 4805, which would exceed the maximum length of 4096 stipulated by RFC (I believe they are RFC 2109 (#6.3), RFC 2965 (#5.3), and RFC 6265 from searching around).

Thoughts:

To Reproduce

Unless you are using Keycloak, which is generating obscenely long cookies, it may be hard to reproduce this. However, I have attached below an exact JSON copy of what the cookie would look like before it is being split into two somewhere. I have also attached the react code we are using to create our client.

src/hooks/useSupabaseClient.tsx


"use client";

import { useAppSelector } from "@inspire-tms/vault/components/store/hooks"; import { createBrowserClient } from "@supabase/ssr"; import Cookies from "js-cookie"; import { useState } from "react";

export const useSupabaseClient = (): SupabaseClient => { const state = useAppSelector(app => app.supabase); if (!state.supabase) throw new Error("[useSupabaseClient] function invoked outside of SupabaseProvider!");

const AUTH_COOKIE = "supabase-inspire-tms-vault"; const isAuthCookie = (name: string) => name.endsWith("auth-token") || (name.includes(".") && name.split(".")[0].endsWith("auth-token"));

const [ client ] = useState(() => createBrowserClient(state.supabase!.url, state.supabase!.anonKey, { cookieOptions: { name: AUTH_COOKIE }, cookies: { get: (key) => { if (key.includes("auth-token-code-verifier")) return Cookies.get(key); if (isAuthCookie(key)) return Cookies.get(AUTH_COOKIE);

    // bad cookie
    console.error("request to get cookie rejected:", { key });
  },
  set: (key, value) => {
    (() => {
      console.log(`set '${key}' to '${value}'`)
      if (key.includes("auth-token-code-verifier")) return Cookies.set(key, value);
      if (isAuthCookie(key)) return Cookies.set("supabase-inspire-tms-vault", value);

      // bad cookie
      console.error("request to set cookie rejected:", { key, value });
    })();
  },
  remove: (key) => {
    if (isAuthCookie(key)) Cookies.remove(AUTH_COOKIE);
    else Cookies.remove(key);
  }
}

}));

return client; };


## Expected behavior

A clear and concise description of what you expected to happen.

## Screenshots

> Note in the screenshot below how the cookie is split, literally breaking any attempt to `JSON.parse` the cookie as it is no longer a valid JSON object (see the first`console.log` which begins with a proper `'{"access_token":"eyJhb` but ends abruptly in `NjZXNzI'`)

![Screenshot 2024-01-31 at 7 09 15 PM](https://github.com/supabase/supabase-js/assets/127700939/14775b8f-673d-4cb6-afc6-94d7deaca366)

If I **manually** copy and paste the two separate cookies, I get the following **(valid)** JSON object:
```json
{
   "access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNzA2NzQ5Njc0LCJpYXQiOjE3MDY3NDYwNzQsImlzcyI6Imh0dHA6Ly8xMjcuMC4wLjE6NTQzMjEvYXV0aC92MSIsInN1YiI6ImFhZDA3YTRlLTAxNzYtNDQ3YS04ZWNlLWNjNjU1OGYzYTkyZSIsImVtYWlsIjoibmJhcnJvd0BpbnNwaXJldG1zdGVjaC5jb20iLCJwaG9uZSI6IiIsImFwcF9tZXRhZGF0YSI6eyJwcm92aWRlciI6ImtleWNsb2FrIiwicHJvdmlkZXJzIjpbImtleWNsb2FrIl19LCJ1c2VyX21ldGFkYXRhIjp7ImVtYWlsIjoibmJhcnJvd0BpbnNwaXJldG1zdGVjaC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZnVsbF9uYW1lIjoiTmljaG9sYXMgQmFycm93IiwiaXNzIjoiaHR0cHM6Ly9vbmUtaWQuaW5zcGlyZXRtc2Nvbm5lY3QuY29tL3JlYWxtcy9pbnNwaXJlIiwibmFtZSI6Ik5pY2hvbGFzIEJhcnJvdyIsInBob25lX3ZlcmlmaWVkIjpmYWxzZSwicHJvdmlkZXJfaWQiOiI5M2I3ZmJiYi02Y2I4LTQ1MmMtYWJlNC01NTcwYjUxNjM4ZGUiLCJzdWIiOiI5M2I3ZmJiYi02Y2I4LTQ1MmMtYWJlNC01NTcwYjUxNjM4ZGUifSwicm9sZSI6ImF1dGhlbnRpY2F0ZWQiLCJhYWwiOiJhYWwxIiwiYW1yIjpbeyJtZXRob2QiOiJvYXV0aCIsInRpbWVzdGFtcCI6MTcwNjc0NjA3NH1dLCJzZXNzaW9uX2lkIjoiNTBiYWQyMDgtMGQ5Ni00OTRlLTkwZmYtNjRiZDA0MWRjODQ1In0.NIR5kt8yCUsRfBbqxoEUTfnPb0hlrkVwVgGXSLLI3MQ",
   "token_type":"bearer",
   "expires_in":3600,
   "expires_at":1706749674,
   "refresh_token":"ImhX3j7x3b1ASBeaqXHhyw",
   "user":{
      "id":"aad07a4e-0176-447a-8ece-cc6558f3a92e",
      "aud":"authenticated",
      "role":"authenticated",
      "email":"nbarrow@inspiretmstech.com",
      "email_confirmed_at":"2024-01-31T23:52:25.239995Z",
      "phone":"",
      "confirmed_at":"2024-01-31T23:52:25.239995Z",
      "last_sign_in_at":"2024-02-01T00:07:54.970531429Z",
      "app_metadata":{
         "provider":"keycloak",
         "providers":[
            "keycloak"
         ]
      },
      "user_metadata":{
         "email":"nbarrow@inspiretmstech.com",
         "email_verified":true,
         "full_name":"Nicholas Barrow",
         "iss":"https://one-id.inspiretmsconnect.com/realms/inspire",
         "name":"Nicholas Barrow",
         "phone_verified":false,
         "provider_id":"93b7fbbb-6cb8-452c-abe4-5570b51638de",
         "sub":"93b7fbbb-6cb8-452c-abe4-5570b51638de"
      },
      "identities":[
         {
            "identity_id":"d8f31cee-84e8-4b6e-a335-dce2c41d4868",
            "id":"93b7fbbb-6cb8-452c-abe4-5570b51638de",
            "user_id":"aad07a4e-0176-447a-8ece-cc6558f3a92e",
            "identity_data":{
               "email":"nbarrow@inspiretmstech.com",
               "email_verified":true,
               "full_name":"Nicholas Barrow",
               "iss":"https://one-id.inspiretmsconnect.com/realms/inspire",
               "name":"Nicholas Barrow",
               "phone_verified":false,
               "provider_id":"93b7fbbb-6cb8-452c-abe4-5570b51638de",
               "sub":"93b7fbbb-6cb8-452c-abe4-5570b51638de"
            },
            "provider":"keycloak",
            "last_sign_in_at":"2024-01-31T23:52:25.228859Z",
            "created_at":"2024-01-31T23:52:25.228898Z",
            "updated_at":"2024-02-01T00:07:53.775429Z",
            "email":"nbarrow@inspiretmstech.com"
         }
      ],
      "created_at":"2024-01-31T23:52:25.220433Z",
      "updated_at":"2024-02-01T00:07:54.975724Z"
   },
   "provider_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXZTlwZ0pJMDJKT3BqeGtfSnBBRW43VVNpOGtCRDBPTDhrLXVhUTRPTFJZIn0.eyJleHAiOjE3MDY3NDYzNzMsImlhdCI6MTcwNjc0NjA3MywiYXV0aF90aW1lIjoxNzA2NzQ1MTQ0LCJqdGkiOiIwMGIzODA1ZS02OGU2LTQyMWItODVmMy0zNmUwZWY1N2I1N2IiLCJpc3MiOiJodHRwczovL29uZS1pZC5pbnNwaXJldG1zY29ubmVjdC5jb20vcmVhbG1zL2luc3BpcmUiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiOTNiN2ZiYmItNmNiOC00NTJjLWFiZTQtNTU3MGI1MTYzOGRlIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiaW5zcGlyZS10bXMiLCJzZXNzaW9uX3N0YXRlIjoiY2EzYjUyYzQtYjFiOS00Njk3LTk1YzYtN2M2ODFmYTdlMDI0IiwiYWNyIjoiMCIsImFsbG93ZWQtb3JpZ2lucyI6WyIiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtaW5zcGlyZSIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIiwic2lkIjoiY2EzYjUyYzQtYjFiOS00Njk3LTk1YzYtN2M2ODFmYTdlMDI0IiwiZW1haWxfdmVyaWZpZWQiOnRydWUsIm5hbWUiOiJOaWNob2xhcyBCYXJyb3ciLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJiYXJyb3duaWNob2xhcyIsImdpdmVuX25hbWUiOiJOaWNob2xhcyIsImZhbWlseV9uYW1lIjoiQmFycm93IiwiZW1haWwiOiJuYmFycm93QGluc3BpcmV0bXN0ZWNoLmNvbSJ9.ARx9UqYRW8ojbZVWPliG_14BMhEibmdIQe-jcJnuRiwgJMnZEuOs-fjVlfwF-OrxxJHsLOMB-_e-Z4v3ZuFPBs9QFW-3VJm3Kwltttf_lV79nQcOp-zXO_DtYPKkNEEZckmEfpjxmhigNaHjOB3Rw8tvQicTpTTEccuwGmqoChE1StrBVlxYc9uDIAeKIqFDYfkT7kwhSNZEJkqlrxy0RMwq_p6HDOeaoJbJVSxg5UzdpXkJSrkohUGgkui85sIDxDrPRTL6N-ANm32SJNL5T-gQSYDMU8JyMgdiCB2rDlGSpoVP9tXZiB8zY9l_vjgopttGvN65Al5tkqB8aJ3zXQ",
   "provider_refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0N2Y1NTRmMS04MmM0LTRmNDUtOGFmNi1hMjQ1MmNkMjhkMzQifQ.eyJleHAiOjE3MDY3NDc4NzMsImlhdCI6MTcwNjc0NjA3MywianRpIjoiYzgyNDhmZjUtNWU5YS00N2QwLWJiZjgtZWZmYTMxY2RhNjFlIiwiaXNzIjoiaHR0cHM6Ly9vbmUtaWQuaW5zcGlyZXRtc2Nvbm5lY3QuY29tL3JlYWxtcy9pbnNwaXJlIiwiYXVkIjoiaHR0cHM6Ly9vbmUtaWQuaW5zcGlyZXRtc2Nvbm5lY3QuY29tL3JlYWxtcy9pbnNwaXJlIiwic3ViIjoiOTNiN2ZiYmItNmNiOC00NTJjLWFiZTQtNTU3MGI1MTYzOGRlIiwidHlwIjoiUmVmcmVzaCIsImF6cCI6Imluc3BpcmUtdG1zIiwic2Vzc2lvbl9zdGF0ZSI6ImNhM2I1MmM0LWIxYjktNDY5Ny05NWM2LTdjNjgxZmE3ZTAyNCIsInNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJzaWQiOiJjYTNiNTJjNC1iMWI5LTQ2OTctOTVjNi03YzY4MWZhN2UwMjQifQ.HTJEpTHA3bwttIcz6nQcnolY3EOUVy7yo9lnka6CQ2k"
}

System information

kangmingtay commented 3 months ago

Hi @nbarrow-inspire-labs, we recently fixed an issue with the cookie chunking algorithm in https://github.com/supabase/auth-helpers/pull/726. You may want to upgrade your supabase/ssr version from 0.0.10 to 0.1.0 and try again.

ghost commented 3 months ago

@kangmingtay thanks for the heads up! I'll take a look and close this out.

bearbricknik commented 1 month ago

Is this solved? I use "@supabase/ssr": "^0.1.0" but when accessing cookies from request (NextRequest) it splits the cookie in 2 different parts, .0 and .1. But not for all users, only for some which is weird.

uncvrd commented 1 month ago

@bearbricknik do you have social and email/password auth set up? I think with Social Login, it tries to add a bit more metadata from the auth provider in the cookie (like email, username etc) which can make it larger. For me email auth can fit in one cookie, but social auth from google splits the cookie in two