I have a SvelteKit app and am using Firebase and Node to do simple Google SSO auth. I am using an API that requires the IDToken of the currently signed in user to authenticate requests. Ideally I'd like to use the +page.ts
load function to load in the data, something like this:
export const load = (async () => {
// Get user, token
const auth = getAuth();
const user = auth.currentUser;
const token = await user?.getIDToken();
if (!token) throw error(401, "Could not authenticate");
// Use token to get data needed to load page
const data = api.requestData(token);
return { data };
}) satisfies PageLoad;
export const ssr = false;
The issue is that user
is always null when this function executes. I imagine this is because this is called before the page loads and Firebase hasn't had a way to access the session and get the current user.
My question is, what approach do I take to solve this without simply requesting the data after the page is rendered? Is there a way to authenticate the user server side? Thanks so much.
Here's a video that goes through option 1 from my previous answer below:
I have the same problem, and there are three solutions as far as I've been able to tell.
Meaning in your root folder for the authenticated routes (e.g. In the first layout file), do all your Auth, get the user and put in a readable store which you use everywhere. You can get the access token from the Firebase user. You can also show a loading screen whilst Firebase is doing it's thing.
But on every page refresh, the authentication has to happen again. This is similar to Gmail for example.
You'll also need some loading UX for every page or component whilst data is being fetched from your API. But this is standard UX today, and apps like YouTube do a good job of that.
Here you'll need a sign-in page where you authenticate the user and create a session cookie (as Tonton-Blax mentioned). You'll also then sign out the user on the client side using Firebase (since you'll be using the cookie). Then in your *server.js files you fetch the cookie to authenticate your requests. And you'll need to implement another sign out feature which expires the cookie you've created. This option requires a bit more work to secure your cookie, set expiry, deal with CSRF, etc.
Here you'll authenticate the user, but also import the firestore to make changes to your db. If you can't directly call your DB, or if you're using spanner for example, you'll need to create cloud functions that do that for you. But you can import your functions and treat them like API endpoints.
I'm still not sure what's the better approach, I guess it'll depend mostly on your requirements and what kind of user experience you want. Personally I don't want the hassle of dealing with cookies from a security perspective, and I chose to have my own API Vs using cloud functions (read up on my decision process here). If your requirements also mean you'll need your own API, then option 1 is the way to go - which is what I'm doing. I haven't implemented code that I'm happy with yet, otherwise I'd share :)
Hope this is helpful!