supabase
supabase copied to clipboard
Auth not set on server side with link (magic link) login
Version
@nuxtjs/supabase: v0.1.9 nuxt: v3.0.0-rc.1
Steps to reproduce
Set up a login form using the just the email to receive a magic link
const { session, error } = await client.auth.signIn({ email: email.value })
Use a middleware like this
export default defineNuxtRouteMiddleware((to) => {
const user = useSupabaseUser()
if (!(user.value))
return navigateTo({ name: 'login', query: { redirect: to.path } })
})
What is Expected?
The user should be set on the server side.
What is actually happening?
The token on the server side plugin is null:
export default defineNuxtPlugin(async () => {
const user = useSupabaseUser();
const client = useSupabaseClient();
const token = useSupabaseToken();
if (!token.value) {
return;
}
const { user: supabaseUser, error } = await client.auth.api.getUser(token.value);
user.value = error ? null : supabaseUser;
});
Therefore the middleware redirects the user to the login and the user only becomes available after the middleware has run, leaving the user on the login page. A fix would involve watching the user, but thats still leads to the login page shortly showing up before the user is redirected again.
This issue is linked to #28 but singles out the ssr issue when using magic links
I have no choice, the Supabase onAuthStateChange
event is sent on client side. Once the event is received, it shares the data between server and client. Until then, the server is not synced. 😞
To avoid the redirect to login page and the display of the login form there are two solutions depending on if you are using providers or magic link.
Solution using providers
Add the redirectTo
option in the signIn method:
client.auth.signIn({ email: '[email protected]' }, {
redirectTo: 'localhost:3000/confirm'
})
Create you confirm.vue
file and listen to user change
<template>
<div>
Redirecting...
</div>
</template>
<script setup>
const user = useSupabaseUser()
watchEffect(() => {
if (user.value) {
navigateTo('/')
}
})
</script>
Don't forget to add your redirect Url in your Supabase dashboard:
Solution using magic link
This one is a little bit tricky because the ConfirmationUrl
is not override by the redirect one.
But you can override the confirmation template and use the confirm.vue
file in the exact same way as described in the first solution
Hope it helps 🤞
Hello @larbish can you please explain what you mean with the magic link solution? A sample codebase for both signup and signin will be great. Will there be a more permanent solution or this is it?
Hey @nosizejosh, that's a way I found to avoid the display of the login form highlited by @mwohlan. That was just a proposition.
@larbish from this tutorial https://vueschool.io/articles/vuejs-tutorials/use-supabase-auth-with-vue-js-3/ and this snippet
// setup auth state listener
supabase.auth.onAuthStateChange((event, session) => {
// the "event" is a string indicating what trigger the state change (ie. SIGN_IN, SIGN_OUT, etc)
// the session contains info about the current session most importanly the user dat
const { user } = useAuthUser();
// if the user exists in the session we're logged in
// and we can set our user reactive ref
user.value = session?.user || null;
});
does this module create an auth state listener to be able to solve this issue? if not, how can I integrate this for example in my codebase so auth state change can be monitored to solve this issue? Thank you
@nosizejosh Please refer to my response. Auth state changes are monitored and synced with server (you can check the code) but the supabase event is fired on client side. You can also read this issue that explains the same server side sync issue.
Thank you @larbish