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

Realtime connection failing when custom JWT is used #470

Closed
gouthamraj-r opened this issue Feb 3, 2023 · 12 comments · Fixed by supabase/supabase#12175
Closed

Realtime connection failing when custom JWT is used #470

gouthamraj-r opened this issue Feb 3, 2023 · 12 comments · Fixed by supabase/supabase#12175
Labels
bug Something isn't working

Comments

@gouthamraj-r
Copy link

gouthamraj-r commented Feb 3, 2023

Bug report

Describe the bug

I'm using supabase self-hosted and auth0 for my authentication instead of the default authentication provided by supabase. So I'm signing my auth0's payload with supabase secret and sending it in headers.

const payload = {
    userId: user.email,
    exp: Math.floor(Date.now() / 1000) + 60 * 60,
}
const accessToken = jwt.sign(payload, SUPABASE_SECRET_KEY)

const options = {}

if (accessToken) {
  options.global = {
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  }
}
const supabase = createClient(supabaseUrl, supabaseAnonKey, options)
supabase.channel('custom-update-channel')
.on(
  'postgres_changes',
  { event: 'UPDATE', schema: 'public', table: 'user_notifications' },
  (payload) => { 
      console.log('Change received!', payload)
  }
)
.subscribe()

I also enabled the RLS policy on my table. Using the above headers I'm able to query my database. Now I wanted to enable real-time on my table. But when I try to create a subscription with my custom headers, the Realtime web socket connection throws an Authentication error. When I don't send the custom JWT in the header, it works fine but I need my custom JWT's payload to be stored in the subscription table. realtime so that I can use it on my RLS Policy. What should I do to fix this?

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Follow these steps
  2. Add your custom accessToken in the headers
  3. Try creating a subscription on one of your tables

Expected behavior

I want a realtime websocket connection to be created using my custom JWT and the payload of my custom JWT should be inserted into the claims column of 'realtime. subscription' table.

System information

  • OS: macOS 13
  • Browser : chrome
  • Version of supabase-js: 2.7.0
  • Version of Node.js: 16
@gouthamraj-r gouthamraj-r added the bug Something isn't working label Feb 3, 2023
@w3b6x9
Copy link
Member

w3b6x9 commented Feb 4, 2023

@gouthamraj-r how did you set up self-host supabase?

@gouthamraj-r
Copy link
Author

gouthamraj-r commented Feb 4, 2023

@w3b6x9 In my local docker setup like mentioned in this doc

@itsgouthamraj
Copy link

@w3b6x9 This seems to be a bug in supabase-js. I made some changes to it and now its working fine for me. Here's a PR for it - supabase/supabase-js#704

@w3b6x9
Copy link
Member

w3b6x9 commented Feb 5, 2023

@gouthamraj-r
Copy link
Author

@w3b6x9 It doesn't solve my problem, still getting a connection error.
Screenshot 2023-02-05 at 11 43 19 PM

Sending custom jwt through headers causes this issue. I tried sending anon key and it works fine. (note: my custom jwt is also signed with the same supabase secret key as anon key)

@gouthamraj-r
Copy link
Author

gouthamraj-r commented Feb 7, 2023

@w3b6x9 I'm able to fix this by doing this
const supabase = createClient(supabaseUrl, supabaseAnonKey)
supabase.realtime.accessToken = "<my custom jwt>"

@w3b6x9
Copy link
Member

w3b6x9 commented Feb 7, 2023

See https://supabase.com/docs/guides/realtime/postgres-changes#custom-tokens.

This only works for hosted Supabase Realtime.

For self-hosters, you can use realtime-js client to pass your custom token on setup. If you're using Supabase's Kong setup found https://github.com/supabase/supabase/blob/90afbded45620633f0bd66cf873da917f2fb32a8/docker/docker-compose.yml, it will only accept either the anon or service_role tokens so you'll have to call realtime-js setAuth in order to pass your custom token. You can always tweak the Kong config for Realtime to suit your needs or use something else.

@riderx
Copy link

riderx commented Mar 20, 2023

@w3b6x9 thanks a lot for the sharing.
I came across to this issue on my side too.
I made a CLI for my users, and they auth themselves to Supabase with an apikey system I made.
You can see how I mad it here:
https://gist.github.com/FelixZY/0aef530690458b381b8100afa19202c8?permalink_comment_id=4393151#gistcomment-4393151

That has worked super well, right now, I'm making an onboarding command who will watch a table change.
So, I need to listen real time changes.
And that don't work, so i did try to add the config suggested in https://supabase.com/docs/guides/realtime/postgres-changes#custom-tokens

export const createSupabaseClient = (apikey: string) => createClient<Database>(hostSupa, supaAnon, {
    global: {
        headers: {
            capgkey: apikey,
        }
    },
    realtime: {
        headers: {
            apikey: supaAnon,
        },
        params: {
            apikey,
            capgkey: apikey,
        },
    },
})

It seems my token is not present in RLS check with real-time request.
it is doable?
For the context here how i try to get it in the RLS

(current_setting('request.headers'::text, true))::json ->> 'capgkey'::text)

And this work with the rest of the SDK only in Real-time, it doesn't

@w3b6x9
Copy link
Member

w3b6x9 commented Mar 20, 2023

@riderx since capgkey is your custom apikey you can extract something inside your claims by calling current_setting on request.jwt.claims and then extracting out your custom field and casting it into its type.

@riderx
Copy link

riderx commented Mar 20, 2023

It would be like ?

((current_setting('request.jwt.claims'::text, true))::json ->> 'capgkey'::text)

@riderx
Copy link

riderx commented Mar 20, 2023

Even with that don't work, I tried to find in the logs the issue but i could locate in the log my issue, do you know how i could inspect what's happening ?
it feel a bit like a blackbox the RLS ^^

@riderx
Copy link

riderx commented Mar 20, 2023

In the CLI my users use the anon key with the capgokey to check they right, @w3b6x9 you are sure jwt.claims will help me ?
I have spend my day trying to understand this, if you are around to enlight me, i will be super glad.

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

Successfully merging a pull request may close this issue.

4 participants