firebase / friendlyeats-web

Apache License 2.0
437 stars 393 forks source link

Question: What is "getAuthenticatedAppForUser" for? #274

Open mrvfino opened 4 months ago

mrvfino commented 4 months ago

I've been using firebase on mobile for a long time already but kinda new to web. What's happening in "getAuthenticatedAppForUser" what purpose does it serve? I'm kinda confused because auth is client side right? Correct me if I'm wrong but outside what the codelab teaches this thing attempts to fetch the user from the server via the admin sdk, right?

Herohtar commented 4 months ago

From what I understand, it uses the Admin SDK to authenticate a user on the server side by verifying the token contained in the __session cookie passed from the client side via the header. I'm actually having some trouble getting this to work, as it seems Firebase Auth does not set that cookie. I'm not sure if it is something that changed in more recent versions of Firebase or something else...

mrvfino commented 4 months ago

@Herohtar thanks for the insight!

It looks kinda hacky for me and it feels like a gotcha because it's not in the codelab guide. So I didn't add it to what I'm working on.

Herohtar commented 4 months ago

I think the guide is out of date, and on top of that, I think the repo is missing some pieces. After doing a bit more digging, it looks like Firebase Auth doesn't, and never did, set a __session cookie, but rather, the client side part of the code needs to be storing the user's auth token in that cookie (or a similar one*) itself. The cookie then gets passed to the server actions via the request headers where it can be retrieved and used to authenticate Firebase on the server side of things.

* If you are using Firebase Hosting, it seems that the cookie has to be __session, as most other cookies are stripped from the request and __session is allowed through for exactly this kind of scenario..

Rohit1024 commented 1 month ago

Yeah, very eager to know how this should be implemented https://github.com/firebase/friendlyeats-web/blob/ddc901f79f19dc0968e3be35231a4d5e026f54bd/nextjs-end/src/lib/firebase/serverApp.js#L11

I've similar requirement but using the next-firebase-auth-edge package for now

rlw87 commented 1 month ago

The guide that links to this repo implements this method by pulling the user's token out of a header set by the auth-service-worker. This does seem to work, but the issue I'm having is the service worker doesn't seem to see the newly logged in user (or logged out) at the same time as it changes in your client components. This means you can't seem to reliably use any kind of guards on your server components such as

if (!user) {
    redirect('/login')
}

What I'm seeing is when a user logs in on my login page and the login page is listening for AuthStateChange events, when the auth state change changes to show the user is logged in, my component then sends the user to the user's account page, which has the guard in above. The issue is, when the service worker gets the current user to extract the token, the auth library tells it that nobody is logged in yet. Therefore when the user gets redirected to the accounts page, that page then immediately redirects them back to the login page. You can get around it by adding a sleep before redirecting to the account page, but this isn't reliable and doesn't always work.

I've been really happy with firebase for SPAs using React, but this example repo isn't making me want to use firebase for any Next.js apps.

moriverse commented 1 month ago

The guide that links to this repo implements this method by pulling the user's token out of a header set by the auth-service-worker. This does seem to work, but the issue I'm having is the service worker doesn't seem to see the newly logged in user (or logged out) at the same time as it changes in your client components. This means you can't seem to reliably use any kind of guards on your server components such as

if (!user) {
    redirect('/login')
}

What I'm seeing is when a user logs in on my login page and the login page is listening for AuthStateChange events, when the auth state change changes to show the user is logged in, my component then sends the user to the user's account page, which has the guard in above. The issue is, when the service worker gets the current user to extract the token, the auth library tells it that nobody is logged in yet. Therefore when the user gets redirected to the accounts page, that page then immediately redirects them back to the login page. You can get around it by adding a sleep before redirecting to the account page, but this isn't reliable and doesn't always work.

I've been really happy with firebase for SPAs using React, but this example repo isn't making me want to use firebase for any Next.js apps.

The guide that links to this repo implements this method by pulling the user's token out of a header set by the auth-service-worker. This does seem to work, but the issue I'm having is the service worker doesn't seem to see the newly logged in user (or logged out) at the same time as it changes in your client components. This means you can't seem to reliably use any kind of guards on your server components such as

if (!user) {
    redirect('/login')
}

What I'm seeing is when a user logs in on my login page and the login page is listening for AuthStateChange events, when the auth state change changes to show the user is logged in, my component then sends the user to the user's account page, which has the guard in above. The issue is, when the service worker gets the current user to extract the token, the auth library tells it that nobody is logged in yet. Therefore when the user gets redirected to the accounts page, that page then immediately redirects them back to the login page. You can get around it by adding a sleep before redirecting to the account page, but this isn't reliable and doesn't always work.

I've been really happy with firebase for SPAs using React, but this example repo isn't making me want to use firebase for any Next.js apps.

The guide that links to this repo implements this method by pulling the user's token out of a header set by the auth-service-worker. This does seem to work, but the issue I'm having is the service worker doesn't seem to see the newly logged in user (or logged out) at the same time as it changes in your client components. This means you can't seem to reliably use any kind of guards on your server components such as

if (!user) {
    redirect('/login')
}

What I'm seeing is when a user logs in on my login page and the login page is listening for AuthStateChange events, when the auth state change changes to show the user is logged in, my component then sends the user to the user's account page, which has the guard in above. The issue is, when the service worker gets the current user to extract the token, the auth library tells it that nobody is logged in yet. Therefore when the user gets redirected to the accounts page, that page then immediately redirects them back to the login page. You can get around it by adding a sleep before redirecting to the account page, but this isn't reliable and doesn't always work.

I've been really happy with firebase for SPAs using React, but this example repo isn't making me want to use firebase for any Next.js apps.

I have the exact same issue in the login scenario. Don't know if there is any way to solve this problem

moriverse commented 1 month ago

just figured that the following code can resolve the login redirect issue:

`const getAuthIdToken = async () => { const app = initializeApp(config); const auth = getAuth(app);

return new Promise((resolve, reject) => { const unsubscribe = onIdTokenChanged(auth, async (user) => { unsubscribe();

  resolve(user ? await getIdToken(user) : null);
});

}); };`

Looks like onAuthStateChange or authStateReady are not reliable across clients.