User is authenticated with multiple git providers, but the session returns one provider token.

I've ran into a pretty interesting problem. My app gives an option to the users to log in with multiple oauth providers, mostly git. This user has 4 providers - gitlab, github, bitbucket and google. I've go a feature where i select all the repos from the users git account and show them, however when there are multiple providers, supabase sets them like this in the app_metadata:
app_metadata: {
provider: "gitlab",
providers : {
0: "gitlab",
1: "github",
2: "bitbucket",
3: "google",
}
}
app_metadata: {
provider: "gitlab",
providers : {
0: "gitlab",
1: "github",
2: "bitbucket",
3: "google",
}
}
I have the following function which desides which git provider to fetch from:
const checkProviderAndFetchRepos = async () => {
setLoading(true);
setError(null);

try {
const supabase = await createClient();
const {
data: { session },
} = await supabase.auth.getSession();

if (!session) {
setError("Please sign in to access repositories");
return;
}

const authProvider = session.user.app_metadata.provider as string;

// Check if user logged in with a git provider
if (
authProvider === "github" ||
authProvider === "gitlab" ||
authProvider === "bitbucket"
) {
setProvider(authProvider);
await fetchRepositories(authProvider);
} else {
// User logged in with email or Google, needs to link account

} catch (err) {
...
} finally {
...
}
};
const checkProviderAndFetchRepos = async () => {
setLoading(true);
setError(null);

try {
const supabase = await createClient();
const {
data: { session },
} = await supabase.auth.getSession();

if (!session) {
setError("Please sign in to access repositories");
return;
}

const authProvider = session.user.app_metadata.provider as string;

// Check if user logged in with a git provider
if (
authProvider === "github" ||
authProvider === "gitlab" ||
authProvider === "bitbucket"
) {
setProvider(authProvider);
await fetchRepositories(authProvider);
} else {
// User logged in with email or Google, needs to link account

} catch (err) {
...
} finally {
...
}
};
Then, on the server side, based on the provider, one of 3 routes.ts files is chosen. It fetches the user's session and there is only one provider_token available, but instead of returning a provider token for the first provider - gitlab, it returns a token for github -
gho_etc
gho_etc
This means i cannot base my fetches on the app_metadata.provider, because the token is different.
8 Replies
mide
mide2w ago
I can help with that the issue happens because Supabase only stores the last used OAuth provider’s token in the session, even if multiple providers are linked. That’s why you’re seeing the GitHub token instead of GitLab’s. Do you need to always fetch repos from all linked providers, or just from the one the user selects manually?
Borislav Borisov
Borislav BorisovOP2w ago
just from the ones the user selects manually, but it would be good to have it fetch from all the providers too, since i may use it.
mide
mide2w ago
If you don’t mind I can help with that the issue is that Supabase only keeps the latest provider’s token, so older ones get overwritten. Do you want to store each provider’s token separately so you can fetch from all linked accounts later?
Borislav Borisov
Borislav BorisovOP2w ago
yes, that was my idea too, storing each provider's token, but what is the best way to do that?
j4
j42w ago
@Borislav Borisov while getting help, don't give anyone access to your supabase project unless you know and trust them. If a user is logged out, then logs in, any provider_token in the session should be for whatever provider they just logged in as. If you believe this isn't the case, create an issue on github. Also be aware that upon token refreshes, that provider_token will drop from the user's session, as Supabase no longer stores it.
Borislav Borisov
Borislav BorisovOP2w ago
yes, that is indeed the case, whenever a user logs in, the provider token is for the oauth provider used. however is there a way to store them in my public.profiles table and have a trigger watch and update them whenever there’s a new provider token?
j4
j42w ago
I'd assume that's possible to do in a custom access token hook. https://supabase.com/docs/guides/auth/auth-hooks/custom-access-token-hook
Borislav Borisov
Borislav BorisovOP2w ago
thank you, i'll see what i can do

Did you find this page helpful?