Firebase References - Local Authentication - firebase

When I create a firebase reference and take a snapshot of that reference while authenticated through firebase authentication then I log out, that data remains.
Requirements:
Page cannot be reloaded or force reloaded after logout
Cannot Clear Firebase Session or all data will need to be reloaded
Must clear only the data that was accessable to the user and not to the public
Must also reload data that is owned or is in the same group as the non-escalated or guest user after the other user has logged out.
I am considering creating objects that wrap my references that will supply a user group and other permissions property as is commonly seen on linux. This will allow me to use the current user object that provides group and user details as a base for deactivating or clearing local data.
Is there a standard way of doing this?
Am I making more work of this than is needed?
I will be hardcoding the knowledge of what groups have permission on the clientside to be replaced later with metadata provided by firebase. I plan to eventually keep track of all references available to a specific user under the user id as well as keep track of the references available publicly and as well again keep track of references available to specific groups where the highest permissions takes priority.
Step one I am taking is creating a way to manage the references clientside and build in checks for authentication change and then utilizing the user details provided in the current auth apply needed changes with authenitication change kicks off. Is it easier to just initiate another call to the server for that snapshot, will that snapshot change if it is no longer authorized?

You control your own app and the prefs based snapshot (or wherever else you save the data) is under your app control as well. Assuming that whatever local storage is protected to your app only (whether natively by Android OS such as private prefs or otherwise), you can simply save the local cache under the user id of the currently authenticated user. So your app can check if the authenticated user matches that user id of the cache and if it does not, then access is denied. In fact, the local cache should be keyed minimally by the logged-in user so you get that kind of check for free (basically the snapshot data won't be found).

Related

Have one user signup another user with custom fields in firebase/flutter

I am trying to determine if the following scenario is possible with flutter and firebase:
we have users within the company who will be given access to the app, where on the homepage will be a signup another user button where they enter in that user's email and password, they get signed up, and then the original user specifies custom fields for the 2nd user, such as company name, role, position, etc.
Is this possible with flutter and firebase?
Have asked the flutter google group and was told about custom authentications, but from what I see that is just an external authentication system and doesn't show me how to let one user create another users profile with fields.
Any ideas?
The first thing to consider is whether those properties need to be in the user profile at all. The user profile is sent with every request, and should only contain information that is relevant for securing access. If you have additional information to store about the user, you should store it elsewhere (such as in one of Firebase's databases) using the UID of each user as its key.
Assuming that the information is about security (such as the role seems to be, there is no secure way to let one user set security properties (typically referred to as claims) from client-side code. As soon as this is allowed from client-side code, anyone could set such properties for anyone else. That's why setting custom claims for a user is only possible with Firebase's Admin SDKs, which are designed to run in a trusted environment - such as your development machine, a server you control, or Cloud Functions.
There are a few other options, but it's important to realize they're all implemented on top of the above approach.
There is an experimental extension that allows you to set auth claims by writing a document into Firestore, which something like this (JavaScript syntax, but the Flutter code will be similar):
db.collection("user_claims")
.doc("abc123")
.set({
role: "admin",
groups: ["example1", "example2"],
});
Now of course you'll want to make sure that you secure writing to the user_claims collection, as otherwise you'll end up with the same security risk I mentioned in the first paragraph, where everyone can claim any role they want.
Alternatively you can write your own server-side API (for example on Cloud Functions) that you expose to your application, and that then calls the Admin SDK. Here too, it is important to secure access to this API, to ensure only authorized users can call it.

how to make singups and signins with different group of users

I am developing an app for my college and there are different types of users called students ,teachers , hod's
etc. When they login, how do I know a teacher logged in, or a student logged in? Is there any function in firestore for role based signups and signins?
I was thinking that when a teacher signs up, I will add a tag end of her uid.username that if username is 'DANIEL' while signup, I will add a tea for teachers and stu for students at the end of the name what they provided.
So when they login i will get the uid and do the string manupulations and get the last three letters so that i can know who logged in so that i can show different UI to Different types of users
Is there any best way to do like this ?
while singning up user enters his username example:"daniel"
i will update that username in uid.username like this "daniel-stu"(if student signed up),"daniel-tea" if techer signsup.
Storing this information in the user's display name can work. You can read it back from there next time, and take action in your application's client-side code. But note that this means that any user can change their role, since they can also call the same code to update their profile. If that is not a concern for your app, then this approach sounds like it would work.
If malicious users should not be able to change their role, then you shouldn't set that role from the client-side application code. In that case, you can set the role from a server (or your development machine, or Cloud Functions) using the Admin SDK. Since the Admin SDK runs in a trusted environment, it has expanded privileges and can update the profile of any user. So the Admin SDK could update the display name of the user in the same way you have in mind.
But this still isn't secure, since you're still setting a property that anyone can modify for their own profile. Again... if that is no problem for your app that is fine, but if the use-case requires that you can rely on the property to be correct, we have to keep looking elsewhere.
The Admin SDK can set additional so-called claims on a user profile that client-side code can't modify. Such claims are for things that affect the permissions of the user, such if the user is an admin, or what role/group your users belong to. This sounds quite close to what you are describing, so can also be used. And this time, only your code that runs in a trusted environment will be able to do so.
Finally, you could store the additional information about a user in the database. It's quite common to have a collection (Users or Profiles) in the database, where you store a document for each user (with the document name being User.uid). You create the document when the user first signs in, and update whenever you need to. You can do this from the client-side code (if there is no need to control what gets written), or from code that runs in a trusted environment (such as your development machine, a server you control, or Cloud Functions) if you do need to keep control. A big advantage of this approach is that all users can potentially see the information in this collection, where the client-side Authentication SDK only allows a user to read their own user profile.
For more on this, see:
Adding new data to firebase users (in which I essentially list the same options with fewer words)
Add extra User Information with firebase (store the information in the realtime database)
Associate Firebase Users to Database Records (also using the realtime database for the additional information)
Cloud Firestore saving additional user data
this video explaining custom claims
and many more previous questions on this topic

Updating Remote Configuration data when a user property changes

I use Firebase Remote configuration to control my app features per user segment and so I apply conditions on remote configuration parameter based on some user properties.
The issue is that some of these user properties could be changed when the app user make some actions that change his/her segment (like user was free user and becomes a paid users) and in this case, Remote configuration doesn't fetch the new values so the user sees wrong data in the current app session (sees data related to his previous segment not the new one) and will not see the right data until he/she closes the app and opens it again.
-Are there any solution to force Remote Configuration to update the cached value?
-Is it right to use Remote Configuration in these case or we have to move to another solution like RTDB?
You can trigger Firebase reload by sending silent FCM message either to devices with specific property value or to all devices. Naturally you need to implement handling for the notification and reload triggering. This page describes the implementation very well.

FirebaseAuth signin vs linking an anonymous user

We login users anonymously in our app using FirebaseAuth, and allow them a read-only access to some of our content. At a later point of time the user can decide to login with credentials and have access to more stuff and write user specific data. The question is, do we gain anything by linking the anonymous user with the one with credentials?
Since we do not have any user specific data when the user is anonymous, it looks like a performance overhead (linking and merging seem to be slower) to link/merge as opposed to a plain sign in. Is there a downside to not linking in this scenario?
You will end up with a lot of stale/abandoned anonymous user accounts and if you are saving anonymous user keyed data in your database, that will also need to be cleaned up if you choose to sign in instead of linking.
In that case (sign in instead of linking), you should consider deleting that anonymous user's data.
If you decide the linking flow, you will not run into the above.

Using Dynamic Links to Accept Invites

Before I go into the issue I am having I'd like to provide you with some context. Currently I have users and sessions. Users are the what you would normally think of when you think of users, however sessions can be thought of as meetings. These meetings can be marked as private, in which case I have Firebase Database security rules in place which prevent users from reading and writing to the meeting unless they are a part of it. In app invites are the only way to get invited (originating from the organizer)
Until Now, here's the problem: I would like to use Dynamic links to invite users to sessions by linking straight to the session, however I don't know how I would model this in database security rules.
Does anyone have any idea how I would say: "Anyone that was invited here from a dynamic link has access to invite themselves to a session"? In this case I guess the issue is that I don't know who the user will invite.
Looks like I solved my own problem using my previous comment. I decided to generate a new push key and distribute the key using dynamic links.
What does this look like in the DB?
I created a path in firebase to hold the session's random key:
dynamicInvites/sessions/{sessionId}
"somerandomkey"
and a path to hold the key distributed to users
dynamicInvites/users/{userId}
{
"somerandomkey": {timestamp}
}
In addition there are security rules that say that session X and random key for session X cannot be read unless user A has the random push key for session X or they are a member of the session.
How did you distribute the key?
Since users of the session have access to the random key they can generate a dynamic link with the random key and sessionId as querystrings.
When the user clicks the link they are redirected to the app which pulls the random key and session id from the link and puts the random key under their dynamicinvites user path along with the current time and then opens the session using the session id. The current time is used in the event that I want to perform some type of periodic cleanup of these keys.
Why use a separate push key and not the one from the session?
The push key for the session is in multiple places in the DB and is not considered private as it may be loaded to the client.
Performing a DB update at app startup is not user friendly though
I masked this time using a splash screen when the user clicks the link. Since I have a splash screen at normal startup time this is the normal behavior that users will expect.

Resources