-
-
Notifications
You must be signed in to change notification settings - Fork 168
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
feat: remove deprecated session methods #340
Conversation
2adb1df
to
24c5e8c
Compare
24c5e8c
to
19184f4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Still need to convert the Errors to the custom ones :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me
fix: add custom error classes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm! nice!
🎉 This PR is included in version 1.23.0-next.7 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Is there going to be a replacement/alternative to this function? I think the primary usecase would be in server-side environments, where the server has a user's JWT and wants to perform an operation using the user's credentials to enforce RLS policies. The The local storage example given would definitely be more complicated, and also wouldn't be feasible on server-side environments. |
@inian that code is no longer needed as Regarding the The way we should be recommending people setup their supabase client serverside if the want to send requests as the end user is creating a supabase client per request. For example: app.get('/example', (req, res) => {
const supabase = createClient(process.env.SUPABASE_URL, req.cookies['sb-access-token'])
...
}) |
That makes sense Alaister. The client libraries for our other products still need something like setAuth but since gotrue is responsible for managing its own session, it doesn't make sense to have the user set it manually. |
I strongly agree to remove I support the idea of creating the client on a per request basis. Although i'm not quite sure if passing the AT instead of the anon key to Reusing a client in a multi user/session environment (eg. long running express process) should be avoided as it might lead to unwanted behavior like this: 1.) req from user A hits server |
Hello supabase team, I'm the maintainer of the supabase module for Nuxt and I'm currently working on the migration to your v2. For the v1, I was using the What is the way to achieve this ? 🙏 |
Hey @larbish, As @kangmingtay explains, you can use the Not sure if I'm helping... the |
@larbish try to set the Authorization Header: import { createClient } from '@supabase/supabase-js';
createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {global: { headers: {
Authorization: `Bearer ${access_token}`
}}}) You can find the type for the options here: https://github.com/supabase/supabase-js/blob/c487683bf9ba9368f502a497ec67a2231c053612/src/lib/types.ts#L10 If you directly use gotrue-js it would be: new GoTrueClient({headers: {Authorization: 'Bearer ...'}}) |
Thank you @pixtron, that is exactly what I was looking for. |
Hey @larbish, The only way you'd get the Would you mind checking that you are passing a token in there? |
Related to realtime-js. Currently a user can change the jwt with setAuth (today two users were doing so with custom jwts and hit an issue with jwt format in their realtime handlers but it is same for just changing the jwt) and setAuth generates a refresh token event which realtime uses to update it's user token. It is not clear (at least to me without more research into code) how in v2 a change in the jwt header (custom or just to another Supabase jwt like, anon key to real user) gets communicated to realtime-js which is already running a subscription. Maybe when supabase client is "reset" with new jwt header, the currently running realtime channel gets update? At a minimum needs to be documented how to do that as there is probably a realtime-js call that would also have to be made in addition to the header change. Or it may be that if you change the jwt you need to close and restart the subscription. I'll look into it more when I get time, but just throwing it out there. |
It would be nice to have a slightly easier path for custom JWT: What I was hoping for was a SignInWithToken(...) api |
A workaround can be found on:
|
Is there something I'm missing from this new configuration to create a SupabaseClient per server-side route request? I'm unable to get a session or user when setting an accessToken in |
I'm having the same problem. createClient(Environment.Supabase.URL, Environment.Supabase.ANON_KEY, {
...clientOptions,
global: {
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
}); Getting session: const authenticatedClient = // Create with the method above
const { data: sessionData, error: sessionError } =
await authenticatedClient.auth.getSession();
console.log('Session data');
console.log(sessionData, sessionError); Output is:
Getting user: const authenticatedClient = // Create with the method above
const { data: userData, error: userError } = await authenticatedClient.auth.getUser();
console.log('User data');
console.log(userData, userError); Output:
--- Update Raw HTTP request to GoTrue server on path |
I have finally figured out the real issue. In v2, by default
Here's the code snippet function inMemoryStorageProvider(): SupportedStorage {
const items = new Map();
return ({
getItem: (key: string) => items.get(key),
setItem: (key: string, value: string) => {
items.set(key, value);
},
removeItem: (key: string) => {
items.delete(key);
}
}) as SupportedStorage;
}
const client = createClient(supabaseUrl, anonKey, {
auth: { storage: inMemoryStorageProvider() },
global: {headers: {Authorization: `Bearer ${access_token}`}}
});
client.auth.onAuthStateChange((event) => {
console.log(`client-2 event`, event); // ✅
})
const {data: data2} = await client.auth.getSession(); ✅ |
@bhvngt If you set |
@bhvngt I'm new to SSR, but I'd be weary of that in-memory store implementation. What if you have a multi-region site? I'm using a cookie implementation (bypassing supabase storage), and it's been working great so far (not yet in production, very soon). You should check out cookie support for your SSR framework. I'm using Remix, so if you have any questions let me know. But yup, it still wouldn't fix the issue with |
@galizar @miguelespinoza I tried with Here's the full script that I ran as a function inMemoryStorageProvider(): SupportedStorage {
const items = new Map();
return ({
getItem: (key: string) => items.get(key),
setItem: (key: string, value: string) => {
items.set(key, value);
},
removeItem: (key: string) => {
items.delete(key);
}
}) as SupportedStorage;
}
const supabaseUrl = process.env.PUBLIC_SUPABASE_URL ?? "";
const anonKey = process.env.PUBLIC_SUPABASE_ANON_KEY ?? "";
// const authOptions = {auth: { persistSession: false }}; // returns null session ❌
const authOptions = {auth: { storage: inMemoryStorageProvider() }};
const signInClient = createClient(supabaseUrl, anonKey, {...authOptions});
signInClient.auth.onAuthStateChange(async (event) => {
console.log(`signInClient event`, event); // prints SIGN_IN ✅
})
const {data: {session}} = await signInClient.auth.signInWithPassword({email, password});
console.log("signInClient session access_token - " , session?.access_token) // prints access_token ✅
const directSessionClient = createClient(supabaseUrl, anonKey, {...authOptions, global: {headers: {Authorization: `Bearer ${session?.access_token}`}}});
directSessionClient.auth.onAuthStateChange((event) => {
console.log(`directSessionClient event`, event); // gets called ✅
})
const {data: getSessionResult} = await directSessionClient.auth.getSession();
console.log(`getSessionResult session`, getSessionResult.session); // prints session object ✅ Output is as follows
@miguelespinoza Thanks for offering help on the cookie implementation. I am using |
@bhvngt do you still get a session with const {data: {session}} = await signInClient.auth.signInWithPassword({email, password});
console.log("signInClient session access_token - " , session?.access_token) My assumption is that Setting the option a.) call b.) cretate a custom storage (see example above Be careful to not share a single supabase client between different requests in a single process & multi user environment like a long running express server. Edit: there is also a method to get the user (but no session initialization) with an access token: |
@pixtron Thanks for the info. You are right. Commenting out
I can confirm that this approach works.
This approach has one down side. When session gets initiated with
Thanks for the input. In my app, my server is
Interesting. Thanks for sharing this info. For initiating server based With Global Authorization header
Here's the code snippet that follows the above approach const access_token = "*********";
const globalOptions = {global: { headers: { Authorization: `Bearer ${access_token}` } }};
const sbClient = createClient(supabaseUrl, anonKey, { ...globalOptions});
sbClient.auth.onAuthStateChange((event) => {
console.log(`sbClient event`, event); // does not get called ❌
});
const { data: getUserResult } = await sbClient.auth.getUser(access_token);
console.log(`getUserResult user`, getUserResult.user); // prints user object ✅
console.log(`sbClient.from("private_table")`, await sbClient.from("private_table").select("private_col")); // fetches private data for authenticated cllient ✅ One downside is that With In memory storageIn order to trigger Here's the code snippet that takes this approach. Here, I could skip using function inMemoryStorageProvider(): SupportedStorage {
const items = new Map();
return ({
getItem: (key: string) => items.get(key),
setItem: (key: string, value: string) => {
items.set(key, value);
},
removeItem: (key: string) => {
items.delete(key);
},
}) as SupportedStorage;
}
const session = {
access_token: "*******",
refresh_token: "******",
expires_at: 1664427836
};
const storage = inMemoryStorageProvider();
storage.setItem(`sb-${host}-auth-token`, JSON.stringify(session)); // host is either localhost or supabase subdomain depending on the env
const authOptions = {auth: { storage }};
const sbClient = createClient(supabaseUrl, anonKey, { ...authOptions, });
sbClient.auth.onAuthStateChange((event) => {
console.log(`sbClient event`, event); // gets called ✅
});
const { data: getUserResult } = await sbClient.auth.getUser();
console.log(`getUserResult user`, getUserResult.user); // prints session object ✅
console.log(`sbClient.from("private_table")`, await sbClient.from("private_table").select("private_col")); Would have preferred a simpler or at least well documented method to make |
I tried this on localhost, and when I try to log in with a user, the key used is |
@aruke As in two or more users on the same computer or on different computers? if the former then no as the token key would be the same for both user's and one would have to log out before the other could log in, but generally this is how sessions work in any application. If the latter then yes this will work for two or more users. |
@silentworks Thanks for the answer. |
What kind of change does this PR introduce?
Remove the following deprecated functions and properties
setAuth(accessToken)
user()
,session()
,this.currentSession
,this.currentUser
getSession()
Updated the session type which guarantees that if an object is of type
Session
, it will always have anaccess_token
,refresh_token
anduser
.