Query firestore on the server with auth info in a nuxt app - firebase

I plan to query some data from Firestore within the fetch() method that Nuxt provides and then send it to the store. The problem is that the query requires the Firebase Auth info (the Firestore rules more precise), and afaik will the Firebase Auth not yet be connected or have loaded the active user since that happens client side. So that would mean that the query wouldn't have the auth info? How would I go about solving this? I have looked around and found that you could use cookies to store the Firebase Auth id and then within nuxtServerInit() in the store, load the user and get the correct uid and so forth, but Firebase will still not know about the user and I haven't found a way to load the user into Firebase Auth on the server side using the id from the cookie.
Any help would be really appreciated! (I released this got quite messy but hopefully you guys get the main point)
Worth nothing that I'm using Google as the sign in provider.
UPDATE:
I've done some digging and found that you can get the idToken and accessToken from the AuthCredential you get back after successful sign in. I think you could store those instead in a cookie and then sign in the user on the server using signInWithCredential() and pass a new GoogleAuthProvider that you could create with GoogleAuthProvider.credential(idToken, accessToken) using the tokens from the cookie.
Again, I'm not sure if this is safe to do or the correct way but I think it should work at least because now Firebase would now about the user already on the server side and therefore should the call to Firestore be no problem regarding the auth info.
I'm not able to test this right now but some thoughts on this would be great, thanks!
Still not able to test it but would like someone thoughts on this.

Related

Firebase database call working even when Authenticated user is disabled

I use Firebase Firestore and Firebase Authentication in my project.
I am testing out what would happen if I go into firebase console and manually click the "Disable account".
I would expect that if the account is suspended, the authenticated user (test#mail.com in this case) will immediately receive error whenever a Firestore database is called (eg. getDocs(q) or setDoc()). The reason behind this assumption is that I assume Firestore tries to authenticate each call before doing CRUD.
However, after testing out, here is the test and result
Login user (test#mail.com)
Do a db read or write ensure everything works which it does
Go to firebase console and disable the account (test#mail.com).
Try to do another db read or write. The result here is that I was able to still read and write which is not what I expected.
So here are my questions
Is this a normal behavior?
Can I write Firebase security rule to overcome this issue?
It would be less idea if I have to check if user is logged in everytime I do a firestore call. But if that is what I have to do, how can I do that. I believe getAuth()and onAuthStateChanged is not really suitable in this case. Reason being getAuth() seems to only check the database the first time it is called. Any subsequence call it only checks the app memory and do not perform any network request at all (Verified by looking into console network tab). Which is kinda weird. And onAuthStateChanged does not listen to firebase state change, it only listens to if my app logs a user in or out.
Abit of background on what I am trying to achieve
I want to be able to lock a user out from my app by changing something from the db. And ideally not having to PING every few second .
Update:
It seems like it takes about 1-2 hour for my app to automatically recognise that the account has been disabled. It took takes alot longer than what I anticipated. I would still like to know if there is a better solution rather than wait though.
Firebase Authentication works with a combination of long-lived refresh tokens and short-lived ID tokens. The latter tokens are valid for one hour from the moment they are minted, and cannot be made invalid after they are minted.
So it may take up to an hour before your client gets a new token, and detects that its account has been disabled. You can force the client to update its ID token at any time by calling getIDToken(true). This will ensure the client has an updated ID token, but it won't invalidate the older ID token (since it's impossible to invalidate a bearer token).
What you'll want to do is write the UID or ID token to your database when you disable the user account, and then check for that in your security rules.
Also see the Firebase documentation on detecting token revocation.

Is there a way to get idToken of an user from Firebase Console?

Im developing a backend for mobile which is using Firebase for authentication and authorization. When the mobile ends the authentication process it sends through http methods to my backend an idToken signed by Google, which then I verify the signature and payload of the provided idtoken.
Is there a way to get the idToken from Google Firebase Console?
At the time I only figured out how to get it from mobile through a method called getIdToken for Kotlin. I can't keep getting the token this way, I need to do it without the mobile.
Thanks!
There is no server-side API to get ID tokens of your users from Firebase Authentication. You will have to get it on the client, and pass it to your server to be verified, exactly as you already seem to be doing.
That is also the process that the Firebase services and SDKs themselves follow, so you might want to reconsider whether this is feasible for your use-case too, or edit your question to better explain why it isn't possible.

With Firebase is using CustomUserClaims a good idea to give access to paying users?

In my app using Firebase as back-end, I wanted to implement a new feature based on Firebase Storage to allow my users to save some files.
Knowing that my app can be accessed only by people who are paying a subscription, I'm already filtering the access to Firestore (used in my project to store user data) via a document that stores if the subscrition is valid or not and this is filtered by the Firestore security rules.
I saw that there is no linkage between Firestore and Storage, so I can't in the Storage security rules read my Firestore documents. So I had the idea to use CustomClaims to add to the Auth token an attribute if the subscription is valid or not.
After tinkering a bit with it, I noticed and checked that it takes up to an hour to client to have a refreshed token. Since my app follow roughtly this workflow:
I don't think that is a good user experience to wait for an hour to have access to a service the user just paid.
Is there something I didn't see ? Is there a way to circumvent this problem ? Is there an other way to have a refresh token than to force the user to logout ?
You can force the ID token to be refreshed with currentUser.getIdToken(true) with the JS SDK. There are similar methods for the other Client SDKs.
See the doc for more details.

Flutter - Understanding Firebase Admin and how to get a user's information from email/uid/name

I'm making a little Snapchat clone, and a part of this app I'm trying to build is the ability to add a friend and start a conversation with them. I'm using Firebase to manage my users and I'm a little stuck now trying to figure out what works and why I'm getting problems trying to use some methods or functions.
What I want is this simple line of code to work:
var userByEmail = await _admin.app().auth().getUserByEmail("b#gmail.com");
print(userByEmail.toString());
However this has been giving my some problems, most recently, the following error message:
Unhandled Exception: FirebaseAuthError(auth/invalid-credential): Must initialize app with a cert credential or set your Firebase project ID as the GOOGLE_CLOUD_PROJECT environment variable to call verifyIdToken().
Getting to this point made me want to first ask a question about FirebaseAdmin and Auth before continuing and potentially screwing up my app settings.
Is there a simple way to do what I'm trying to do?
I have a Firebase.instance.initializeApp() in my Main function, do I only ever call that once or should I start initilizeApp in the initState of each Stateful Widget where needed?
What does this error message actually mean?
You are trying to use the Firebase Admin SDK in your Flutter code, which is not possible. The Admin SDKs give full administrative access to your Firebase project, which would be a serious security concern if you allow that in your Flutter app.
If you want to allow certain administrative functionality in your application, you will have to make that functionality available yourself. For example, to look up a user by their email address, there are two common approaches:
Store the minimal information about each user in a cloud-accessible database (such as Firebase's Realtime Database or Cloud Firestore) when each user registers with your app, and then look it up from there.
Wrap the getUserByEmail from the Admin SDK in a custom API that you make for yourself, on a server you control or in Cloud Functions. In that API you validate that the user making the call is authorized to do so, then call Firebase through the API you were trying to use, and return the minimal result back to the caller.
Both of these are feasible and can work to solve a variety of use-cases. But if you've never built backend code before, you might find the first approach easier to get started with.
Also see:
How to get Firebase UID knowing email user?
Flutter get User Data from Firebase
The right way to do what you want is using Firebase auth, authenticating your user and using a collection to store and retrieve users information. That auth information provided by firebase should only be used for authentication and security purposes.
The Firebase admin must have a user logged in to work properly, but its purpose is to provide a more administration environment and should not be used inside a clients app, unless its an admin app.
With all that said, lets go for the rescue:
Authenticate your user (using firebase auth);
After auth, save all the user information you want to share with other user inside its own collection (you will need to create one);
When an authenticated user (this is important) 'request any other users data, you query for the data in the previous created collection.

How to detect that firebase auth is now trying to sign in user?

When a page first loads on our React app / frontend, one of two cases is true:
Firebase auth found persisted creds and is trying to authenticate the user -- there will shortly be a callback on onAuthStateChanged
This isn't a registered user / no persisted creds found: Firebase auth is not trying to authenticate the user (they need to sign-in for the first time, or sign up), so there is not going to be a callback on onAuthStateChanged
We want to render different things in these two cases. To do this we need some way to know that Firebase Auth is actually attempting the sign-in.
How can we do this?
Simliar to Firebase Auth: How can I detect that firebase trying to auto signIn current user?
The only way of knowing if Auth is attempting to sign in is through your own knowledge of how the APIs are being invoked. There is no provided way to "spy" on the progress of the APIs. If you're not the one invoking the APIs (for example, using Firebase UI), then all you know is what an auth state observer tells you (fully signed in or signed out).
If you've just launched the app, and Firebase is trying to refresh the user token (from having previously been signed in), you don't really have a way of knowing how that's going. You have to wait for the first call to your observer to know if there is a user signed in or not. Your app should wait until that first callback in order to figure out how to proceed. The documentation doesn't really do a good job of explaining this.

Resources