S
SolidJS9mo ago
dmayo2

"Deep linking" Why the disparity btn local & prod

Hey, I'm developing an app that uses Supabase's magicLink auth system. The user enters their email and a login link is emailed to them. The link hits Supabase's server with a token. After verification the user is redirected back my app with a JWT token. Straight forward enough. In my case the redirect is to a page that is configed in my Routes. During development (localhost:3000/) everything works fine...the JWT is saved in local storage, I get logged in. No problems. I push the code to Netlify by way of github, Netlify builds the app with no issues. However, when trying to log in to the production site, I was getting an error from Supabase 401: invalid claim: missing sub claim. WTF. Ok, in the receiving page of the production code (I chose App.jsx, but I might change that -- chime in below please) I had to basically code a callback. Why? Why would it work on localhost but not production? This is the code I made. Should I keep it in App.jsx? I could move it to something like /token_process or whatever and have Supabase redirect to that single use page. Thoughts/Comments/Suggestions are all welcomed.
1 Reply
dmayo2
dmayo29mo ago
Here's the code
// App.jsx
createEffect(() => {
// Extract the part after the '#'
const fragment = window.location.hash.substring(1);
if (!fragment) return;

// Convert the fragment into an object
const params = new URLSearchParams(fragment);
const access_token = params.get('access_token');
const refresh_token = params.get('refresh_token');

if (
typeof access_token !== 'string' ||
typeof refresh_token !== 'string'
) {
// Handle the case where access_token or refresh_token is not a string
console.error('Invalid tokens');
return;
}

// Define an async function for setting the session
const setSessionAsync = async () => {
try {
const data = await supabase.auth.setSession({
access_token,
refresh_token,
});
console.log('setSession result:', data);
} catch (error) {
console.error(error);
}
};

// Call the async function and use async/await
supabase.auth.onAuthStateChange(async (event, session) => {
console.log(event, session);
await setSessionAsync(); // Wait for setSessionAsync to complete
navigate('/profile'); // Navigate after setSessionAsync has completed
});
});
// App.jsx
createEffect(() => {
// Extract the part after the '#'
const fragment = window.location.hash.substring(1);
if (!fragment) return;

// Convert the fragment into an object
const params = new URLSearchParams(fragment);
const access_token = params.get('access_token');
const refresh_token = params.get('refresh_token');

if (
typeof access_token !== 'string' ||
typeof refresh_token !== 'string'
) {
// Handle the case where access_token or refresh_token is not a string
console.error('Invalid tokens');
return;
}

// Define an async function for setting the session
const setSessionAsync = async () => {
try {
const data = await supabase.auth.setSession({
access_token,
refresh_token,
});
console.log('setSession result:', data);
} catch (error) {
console.error(error);
}
};

// Call the async function and use async/await
supabase.auth.onAuthStateChange(async (event, session) => {
console.log(event, session);
await setSessionAsync(); // Wait for setSessionAsync to complete
navigate('/profile'); // Navigate after setSessionAsync has completed
});
});
If URLSearchParams is a browser API why not use the built-in resource? If I'm not importing, useSearchParams() then I'd be shipping a smaller app, and, theoretically, it'd be faster ? Or is it that useSearchParams() does the grunt work in the background by assigning variables? At my code's scale, is this 'to-may-to' / 'to-mah-to' instance? Care to expand on storing in a cookie vs local storage? Security? I know that cookies get sent to the server, but in a SPA? Cookies also natively have an expiration date. The http vs https makes sense. Thanks for the thoughful responses. Appreciated.