Supabase Auth and Convex
Hey everyone! I've been trying to setup Supabase auth to be used with Convex (their free tier is more appealing than Clerk) but I've not been about to get it working, It errors out
This is for a
I changed the
From there I have a hook
which is then used in my
I've set the env variables on the Convex dashboard and have my Supabase public and private keys.
Any suggestions or feedback on how I could get this setup? I can sign into the app and log the access_token, but it appears to not be making it to Convex.
Uncaught Error: Not authenticatedUncaught Error: Not authenticatedThis is for a
React NativeReact Native mobile application.I changed the
auth.config.tsauth.config.ts toexport default {
providers: [
{
type: 'jwt',
domain: process.env.CONVEX_OIDC_ISSUER,
key: process.env.CONVEX_JWT_KEY!,
applicationID: 'supabase-client',
},
],
};export default {
providers: [
{
type: 'jwt',
domain: process.env.CONVEX_OIDC_ISSUER,
key: process.env.CONVEX_JWT_KEY!,
applicationID: 'supabase-client',
},
],
};From there I have a hook
useSupabaseConvexAuthuseSupabaseConvexAuthimport { supabase } from '@/lib/supabase';
import { useEffect, useState } from 'react';
export function useSupabaseConvexAuth() {
const [accessToken, setAccessToken] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const fetchSession = async () => {
const { data } = await supabase.auth.getSession();
setAccessToken(data?.session?.access_token ?? null);
setIsLoading(false);
};
fetchSession();
const { data: listener } = supabase.auth.onAuthStateChange(
(_event, session) => {
console.log(session?.access_token);
setAccessToken(session?.access_token ?? null);
}
);
return () => {
listener.subscription.unsubscribe();
};
}, []);
return {
isLoading,
isAuthenticated: !!accessToken,
fetchAccessToken: async () => accessToken,
};
}import { supabase } from '@/lib/supabase';
import { useEffect, useState } from 'react';
export function useSupabaseConvexAuth() {
const [accessToken, setAccessToken] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const fetchSession = async () => {
const { data } = await supabase.auth.getSession();
setAccessToken(data?.session?.access_token ?? null);
setIsLoading(false);
};
fetchSession();
const { data: listener } = supabase.auth.onAuthStateChange(
(_event, session) => {
console.log(session?.access_token);
setAccessToken(session?.access_token ?? null);
}
);
return () => {
listener.subscription.unsubscribe();
};
}, []);
return {
isLoading,
isAuthenticated: !!accessToken,
fetchAccessToken: async () => accessToken,
};
}which is then used in my
_layout.tsx_layout.tsximport {
DarkTheme,
DefaultTheme,
ThemeProvider,
} from '@react-navigation/native';
import { useFonts } from 'expo-font';
import { SplashScreen, Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import 'react-native-reanimated';
import { useColorScheme } from '@/hooks/useColorScheme';
import { useSupabaseConvexAuth } from '@/hooks/useSupabaseConvexAuth';
import { Providers } from '@/providers';
import { ConvexProviderWithAuth, ConvexReactClient } from 'convex/react';
import { useEffect } from 'react';
SplashScreen.preventAutoHideAsync();
const convex = new ConvexReactClient(process.env.EXPO_PUBLIC_CONVEX_URL!);
export default function RootLayout() {
const auth = useSupabaseConvexAuth();
const colorScheme = useColorScheme();
const [loaded] = useFonts({
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
});
useEffect(() => {
if (loaded) {
SplashScreen.hideAsync();
}
}, [loaded]);
if (!loaded) {
return null;
}
return (
<Providers>
<ConvexProviderWithAuth client={convex} useAuth={() => auth}>
<ThemeProvider
value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}
>
<Stack>
<Stack.Screen name='(tabs)' options={{ headerShown: false }} />
<Stack.Screen name='+not-found' />
</Stack>
<StatusBar style='auto' />
</ThemeProvider>
</ConvexProviderWithAuth>
</Providers>
);
}import {
DarkTheme,
DefaultTheme,
ThemeProvider,
} from '@react-navigation/native';
import { useFonts } from 'expo-font';
import { SplashScreen, Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import 'react-native-reanimated';
import { useColorScheme } from '@/hooks/useColorScheme';
import { useSupabaseConvexAuth } from '@/hooks/useSupabaseConvexAuth';
import { Providers } from '@/providers';
import { ConvexProviderWithAuth, ConvexReactClient } from 'convex/react';
import { useEffect } from 'react';
SplashScreen.preventAutoHideAsync();
const convex = new ConvexReactClient(process.env.EXPO_PUBLIC_CONVEX_URL!);
export default function RootLayout() {
const auth = useSupabaseConvexAuth();
const colorScheme = useColorScheme();
const [loaded] = useFonts({
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
});
useEffect(() => {
if (loaded) {
SplashScreen.hideAsync();
}
}, [loaded]);
if (!loaded) {
return null;
}
return (
<Providers>
<ConvexProviderWithAuth client={convex} useAuth={() => auth}>
<ThemeProvider
value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}
>
<Stack>
<Stack.Screen name='(tabs)' options={{ headerShown: false }} />
<Stack.Screen name='+not-found' />
</Stack>
<StatusBar style='auto' />
</ThemeProvider>
</ConvexProviderWithAuth>
</Providers>
);
}I've set the env variables on the Convex dashboard and have my Supabase public and private keys.
Any suggestions or feedback on how I could get this setup? I can sign into the app and log the access_token, but it appears to not be making it to Convex.
