Firebase Auth Built-in identity - javascript

I am building a web platform to connect learners with tutors using Firebase Auth and Firestore. I am storing the learners' user info in a Firestore collection, and the tutor's info in another. I am building a function that can detect if a client is a learner or a tutor upon login.
One solution I was thinking is to query in which collection the user is found using UID. Although, this is a potential solution. But it sounds like it requires a lot of transaction, and may have a long run time if collections get big. Is there something else I can do for that? I am wondering if I can use authentication to build an embedded identity to each user to differentiate between "Tutor" and "Learner"? So each time the user logs in, we know the identity immediately?
I know that in the decoded authentication token, there is info such as this:
{ iss: 'https://securetoken.google.com/xxxx',
aud: 'xxxx',
auth_time: 1569886929,
user_id: 'aB03',
sub: 'aB03',
iat: 1570582588,
exp: 1570586188,
email: 'aa#gmail.com',
email_verified: false,
firebase:
{ identities: { email: [Array] }, sign_in_provider: 'password' },
uid: 'aa3' }
Can I leverage one of these to build what I want?
Really appreciate your time and help.

Since you mention "collection", I assume you're looking to use Firestore. In that case: the size of the collection has no effect on the query performance. No matter if there are 1,000 user documents in the collection, 1,000,000 or even 1,000,000,000, the time it takes to query for a single user document will always be the same.
Aside from that you can also store the user's type in the ID token (which is what you've shown in your question). This is known as a "custom claim", since you're adding a custom property for your app to the information. You'll want to do this from a trusted environment (your development machine, a server you control, or Cloud Functions), as I'd assume users should not be able to change their own role. See the documentation on controlling access with custom claims for more information on this.

Related

Storing sensitive data in Vuex

To summarize, we are using Vue on the front-end and Hapi JS on the back-end. The front end uses MSAL.js to authenticate users and then passes an access token to the back-end. The access token is decoded with hapi-auth-jwt2 and the validate() function returns { isValid: true, credentials : { ps_ref: 12345, md_userid: asfasgsg#5874.com }}. This object is then passed to the handler function of a route which extracts authentication groups/user roles (i.e.Auids) from our DB and user data and returns that.
Imagine that the user object looks like this:
{
Auids: (4) ["user", "webadmin", "accounts"]
md_clock: 5678
md_picture: "./images/"
ps_fname1: "Test Name"
ps_surname: "Test Surname"
psname: "Test Name Test Surname"
psref: 125125
}
Now, we would like to store this object in Vuex, however, we are concerned that it will be visible to anybody who has installed the Vue Devtools in their browser or anybody who executes something like rootElementOfApp.__vue__.$store
Our questions are:
How easy it is for somebody to access the Vuex in production?
If it is easy enough to access Vuex by the public, is Vuex the best way to store this object? If we go for Vuex should we encode the user object or at least the Auids in it ?
Everything you store in the js/html/cookies is not save on it's own. But it is all related how you will manage it. Basically you can store almost everything in the front end, as long it isn't sensitive data that's usable for ethical hacking. Things like addresses, contract numbers, bank accounts etc.
Data like userIds (as long only used for programmatic reasons) or a user roles can be stored in the front end. But if you do it right you always have every client side validation also in your back-end application.
In terms of dev tools of vue they are only available in development mode not production. But a good hacker doesn't mind.

Password protect a page with Firebase

I'm building a CMS with Firebase, but struggling to assess whether what I require is possible, or if I'm missing something.
What I require is the ability to password-protect a page only, and remember that browser as having access. A full user account (using the in built auth) is required to edit the content of the page, but only a password is required to view it.
I know I can use the auth flow with email, but am looking for the editor to be able to create a password for viewing only.
Is this possible, or should I look elsewhere?
The way I commonly do this is a bit like Jeremy's answer, but simpler.
You ask the user for a password when they enter the page, and store that password locally (for reloads).
Then you store data in your database under a path that includes the password. So say that your password is geheim, you could store the data under:
data: {
geheim: {
value: "This is the secret value"
}
}
Now you secure your database with rules like these:
{
"rules": {
".read": false,
"data": {
"geheim": {
".read": true
}
}
}
}
Now somebody can only read the data at /data/geheim if they know the entire path. So you'll enter the data part in your code, but require them to enter geheim as the password. Then you attach a listener with:
firebase.database().ref("data").child(password).once("value", function(snapshot) {
console.log(snapshot.val());
});
And if the user entered the correct value for password, this will read the value.
Firebase Authentication only deals with authenticated user accounts. It doesn't deal with simple password protection of content.
It's definitely possible, but as Doug's answer indicated, you'll have to do it outside normal means. Off the top of my head, the way I would accomplish this is...
When a user enters a password, it stores the password in their local storage.
On page load, or on password entry... pull the password from local storage
Make a request to a Firebase cloud function, makes sure to include the password it just retrieved from local storage, and which page it is requesting content for
Firebase cloud function validates password
Firebase cloud function retrieves data for specific page
Firebase cloud function returns said data
Load data on front-end like normal
As you already identified, you should stick with the built-in Firebase auth for content editing.
I definitely suggest Frank's answer because it's simple and it works. Btw the moral of the story is that you use the firebase Database to store you view-only password but, if you want to complicate your life because you need a strong view-only password system, the Authentication product provides the custom authentication method that you can integrate with your existing auth system (for example fb login). It obviously needs a server-side implementation that is a code that takes the password, check if it's valid and sends the token back to the Auth system.
Here more details: https://firebase.google.com/docs/auth/web/custom-auth

Twilio Video/Chat

I am working on a reactjs - Twilio video/chat application. Its a requirement to include the name of the person as a tag on top of the video.
However when I look at the json response with the participatory information - it only lists an identity id -- is there a way of pushing a name into the service, or doing a lookup on Twilio for the name of the person?
So where you have
identity: "17003",
personName: "Bob Pip"
https://www.npmjs.com/package/twilio-video
I am able to get the sid and the identity.
During video connect tried to pump in a custom value for this localparticipant to push it into the service.
var connectOptions = {
name: roomName,
personName: 'Collin Baker',
logLevel: 'debug'
}
Video.connect(data.token, connectOptions)
but it doesn't come out.
"Hey, so, the short answer is "no" you can't do that through the Video SDK itself."
"However, I would recommend checking out Twilio Sync (https://www.twilio.com/docs/api/sync ). Sync is an API that let's you sync data across devices. So, you could create a sync object that contains the id that you use with the Video SDK paired with the user's visible name."
"They wouldn't link up directly, but if you keep your identities consistent (i.e. User Id from your db) and then keep the visible user name also in sync in the Sync object, then you can share that object between calling parties and display the names. You might, for example, also keep one sync document per video room."
https://www.twilio.com/docs/api/sync/sync-sdk-download
https://www.twilio.com/sync
https://www.twilio.com/docs/api/sync/quickstart-js
https://www.twilio.com/docs/api/sync/identity-and-access-tokens
"Ah, Sync is in beta, so you need to install the alpha version of the npm library. Slightly confusing I appreciate, it's something like twilio#3.4.0-alpha1"

Add keys to Firebase user Object using AngularFire2

I'm trying to implement a role system with Firebase and at least I did it creating a collection into my database and comparing the actual uid vs the table (more or less).
But my question is if it's possible to set any property in the Firebase User object, like role: 'foo'. It's more a theoretical question.
Let's say that I create a user programmatically, like:
this.af.auth.createUser({ 'email': email, 'password': password })
.then(createdUser => {
...
createdUser['role'] = foo;
...... // How can I update the Firebase users database with this new user?
})
.catch(err => console.log(err));
I was watching around for some answer but nothing appears. Can anyone bring me some help?
Thanks!
The only secure way to add such roles to your user object is by using custom authentication, where you fully control the contents of the user JWT.
Most developers take an alternative route, where they store information about their users and roles in the Firebase Database and then secure data access through security rules. I recommend reading this blog post about implementing group security, and some of the results in this query.

Firebase/NoSQL schema for an instant messaging system

I'm using Firebase for an app and the built-in real-time capabilities seem well suited for instant messaging. I'm just having a hard time working out in my head how the database should be set up. Ideally, it's something like this:
messages: {
<messageId>: {
from: <userId>,
to: <userId>,
text: <String>,
dateSent: <Date>
dateRead: <Date>
}
}
And that's all fine for sending messages, but reading message threads becomes difficult. I need to query the (potentially huge) list of messages for messages that match the current thread's sender and receiver, and then order those by dateSent. If that is possible with Firebase's new querying API, then I have yet to figure out exactly how to do it.
Querying a huge list of messages is never a good idea. If you want a fast-performing Firebase/NoSQL application, you'll need to model the data to allow fast look up.
In a chat scenario that typically means that you'll model your chat rooms into the data structure. So instead of storing one long list of messages, store the messages for each chat "room" separately.
messages
<roomId>
<messageId1>: "..."
<messageId2>: "..."
<messageId3>: "..."
Now you can access the messages for the chat without a query, just ref.child(roomId).on(....
If you want a persistent mapping that ensures the same two users end up in the same room, have a look at Best way to manage Chat channels in Firebase

Categories

Resources