Use Firebase with custom authentication (JWT) - firebase

I currently have a frontend (Swift, iOS) and backend (node.js) completely running. I am now looking into real time updates for certain parts of my application and I have decided to go with Firebase because it allows me to deploy quickly and scale easily later on.
However, as I already have an entire backend setup, which authenticates the user and sends back a token (JWT), I would like to know how I can use the same authentication for Firebase. The idea would be to set custom rules in Firebase based on the userID, and to use this userID (which is just a regular id, e.g. my userID is 1, not a UUID) to create collections inside the real time database and Firestore.
I have already read the docs on custom tokens, but I am left with a couple of concerns:
Can I use this to sign a user in, without using Firebase Auth? Or will this create a user in Firebase Auth too?
I can only sign the JWT with an expiry for max. 60 mins from now, so one hour. Would this mean I have to re-authenticate every hour? How should I go about this? My current app grants a JWT which is valid for 21 days.
Should I use the same JWT for Firebase as I use for my entire application, or should I generate a new one and send this one back too, with the main purpose to use it for Firebase Auth in my Swift application?

The JWT needs to be generated with a different set of keys provided by Google in order for Firebase to verify the JWT. You can't use your existing JWT which was signed by another set of keys on your existing server.
But what you could do is use your existing user ids and sign them with Google's keys at the same time when signing the keys for your existing system and end up with 2 JWTs which you pass to your client.

Related

How to allow user to create and switch between multiple accounts in Flutter?

I am trying to make a Flutter app where the user can sign in into multiple accounts (different email IDs) and can switch between them from the UserAccounsDrawerHeader. For example, in Gmail app, users can switch between multiple Gmail accounts. Is this possible using Firebase Auth for Flutter?
In the default scenario, Firebase Auth generally does not support allowing a user to be signed in with multiple accounts at the same time. If you want to add support, what you will have to do is use initailizeApp() to initialize a new App instance - one for each user account, and sign in the user to each one of them. You will then have to pass that app instance around to the other Firebase APIs to use that account for authenticated access (for example, Firestore queries).
To be honest, it's not clear to me from the provided APIs how to do that last part. but perhaps Firestore.getInstance(app) might do it.
In any event, it is not trivial to implement. There is not a simple configuration or trick that will allow multiple simultaneous sign-ins. Usually apps just make the user sign out, then in again with another account.

Flutter Firebase How to integrate third party authentication that generates a token

I have a third party API that generates a token that lasts 60mins. I want to use the token to retrieve user information from the third party database which I want to save in Firestone so I can query later and take advantage of Firestore features like offline data persistence, notifications to specific user info, and analytics.
In order to generate this token, I give the input parameters of:
cardNumber (int)
PIN (int)
How do I create a Firestore user while using a third party API that generates a token? What’s the best way to go about copying the user information into the user on Firebase? Cloud function?
I couldn’t find any guides with flutter and am confused. Thanks!
Firebase Authentication ID tokens are JWTs that are signed with your Firebase project's credentials. In the case of custom authentication, you mint that token, and then sign in to Firebase with signInWithCustomToken.
If the third party API already delivers such a JWT signed with the correct key, it should work as is. More often the third party API will use a different format, and you will have to mint the JWT yourself using the Firebase Admin SDK or one of the third party libraries. Since this is a sensitive operation, it should only be done in a trusted environment, such as your development machine, a server you control, or Cloud Functions.

Where should the OAUTH2.0 Server be for Actions on Google/Firebase

Referring to - https://developers.google.com/actions/identity/oauth2-code-flow Im using Actions SDK which implies Im using Firebase Functions for the fulfillment handling.
Im storing information in Firebase against the UID I got from FirebaseUser.getUid() in an Android app. So far so good.
I've setup a mock OAuth2.0 server and this seems to be happy exchanging tokens.
However later on in the documentation it states:
"Your service's API endpoints use the access token to identify the user on whose behalf Google is making the API call, and to verify that Google has authorization to access the endpoint on the user's behalf."
My fulfillment however is in Firebase Functions. So...
Do I need to get my FirebaseFunction to get the User ID from the OAuth2.0 server? Do I need to setup an OAuth2.0 server in Firebase Functions? Where does the OAuth2.0 server sit? And how do I get my Firebase Function to get the same User ID as reported by Android?
First - you're starting with a small misconception. Actions on Google and the Actions SDK do not require Firebase Functions for fulfillment. Firebase Functions do make it easier - they provide the publicly accessible HTTPS endpoint that you need for a webhook, but if you have your own server (with valid SSL certificate) or if you want to use AWS Lambda or something similar, you can certainly do so. And if you want to use a language besides JavaScript, the JSON protocol used is documented (although sometimes not clearly).
To answer your questions:
If you need the UserID in your webhook, then yes, it needs some way to get that UserID given the access token it will be handed. But how you do this depends on how you implemented your OAuth server and token. For example:
If you used signed JTWs as your token, then the UserID is part of the JWT and all your webhook needs to do is extract this and verify the signature and timeframe on the JWT are valid. You don't need to contact any other server to do this.
If you're storing the tokens and corresponding user info in Firebase or in some other database or data store - just read the token from your webhook!
You certainly can create another HTTPS endpoint you can use to validate the token and get the info from it - this is what Google does, for example.
Your OAuth server does not need to live in Firebase Functions any more than your webhook does. It might be a good place for it to live (along with the authentication page on Firebase Hosting), but it isn't required.
Your OAuth server can sit... anywhere. Well, anywhere public on the Internet with a valid SSL certificate anyway.
This last point is exactly what account linking is all about. You need to make sure that, when they authenticate against your server, you get the UserID that is "reported by Android", whatever that means in your context (but see my update below). Once you have this UserID, you need to make sure it gets associated against any of the tokens that you issue for this user, and you need to provide a way for your service to get this UserID from the token.
How you do this is up to you, and depends on the rest of your architecture and what you're trying to do with it. The Google Assistant doesn't care - it has its own notion of a UserId which is separate from yours, so to identify the user with your UserId, you'll use the token that it hands you.
Update
You raise a good point in the comments about the statement "The user ID on Android devices will also be the same as the user ID on a Google Home". This is true, but talks about the anonymous cookie-like UserID that is available through the Assistant platform only (which is why it is in the section on Anonymous User Identity). It doesn't talk about any ID that you can get through other Android apps. To associate the ID you get through other apps to the Assistant's ID, you need to use Account Linking as described on the following page.
If all you need is a consistent way to track a user that visits your Action multiple times, and you want that to be consistent on any Assistant platform (Google Home, Assistant for Android, or Assistant for iOS), then you just need to use the UserID that is provided through the API/JSON. You don't need Account Linking or an OAuth server. But this is not a Google ID or the Firebase ID, it is a anonymous UserID that is valid on the Assistant platforms only (and then, only within certain conditions if the user does not reset it).
Update 2 To be clear about OAuth and JWTs:
You ask in the questions "Where else can I get the JWT?"
In short - you build it yourself.
Remember that, if you are providing an OAuth server, one of the things you need to do is to issue auth tokens and refresh tokens. Those tokens can be anything you want - the only criteria is that your webhook be able to take the token and, somehow, get the information it needs out of it that ties it to a user.
But you are responsible for putting that information in there in the first place.
So when the user logs in during account linking, you might use Firebase Authentication to log them in. Once you've done so, you can get a Firebase ID and/or a Google ID for them. (After all, they've logged into your OAuth web page - you have to know something about them.)
After they log in, you're redirecting them to some place Google has asked you to, and you're including a token as part of that. That token can be the JWT that you're creating, and in that JWT, you can include the ID information you have from their login.
(And, again... it doesn't have to be a JWT. It can be anything you want. The only requirement is that you be able to validate it and use it to get the information you need.)

Can I set Firebase Database rules based on Instance ID?

I am new to Firebase Database and I am not planning to use the Firebase Authentication.
Is it possibile to set Firebase Database rules based on the Firebase Instance ID, rather than on the authenticated User ID ?
This is the structure I am thinking to implement:
/instanceIDs
/iid1
/somedata
/someotherdata
/iid2
...
/iid3
...
and I would like to restrict read/write permission only to that specific instance ID
anyone can show how to set such rule?
Otherwise, if I set read/write to true for all users, what is the security risk?
If my native mobile app code only reads/writes on the specific instance ID branch, can I expect some security issues?
The Instance ID in an app that uses Firebase Cloud Messaging identifies the installation of that specific app on that specific device. This value is not available in Firebase security rules.
While it sounds like an interesting idea to secure based on this instance ID, it would in longer term not work. The Instance ID can change over time, and every time that happens, the device would lose access to its data.
Access to Firebase (database and storage) is typically based on the user of the app. Unlike the Instance ID, the user's ID is stable over time: meaning that the same user will always have the same UID and thus have access to the same resources. If you don't want to ask your users to sign in, you can use Firebase's anonymous authentication.
PS: if you feel like experimenting with using the Instance ID to secure access, you can easily pass the Instance ID to a server, mint a Firebase Authentication token from it (you could use Cloud Functions for this), and then use that custom token to sign in.

Firebase Security Rules Without Firebase Authentication

I use Firebase to store real time status updates for an app. I have my own authentication system for logging users in. I would like to share the data I store on Firebase to vendors who use our API, but I want to make sure they have only read access to our data.
From what I've read, it seems like securing data by user must be done through Firebase's own authentication system. Is there a way to do this without using their authentication system (maybe through a token system)?
You can definitely generate Firebase tokens in your application code, with custom properties that may be subsequently used in the Firebase security rules. Take a look at Generating a Secure Token in the Firebase docs.
Also see Can a Firebase Security Rule check if someone has specific access rights?, where #Frank van Puffelen offered a more comprehensive role-based approach.
I ended up using a system where a vendor calls one of my APIs (protected by my own internal authorization system) that returns a token that the user can use to authenticate with Firebase.
I use PHP and there is a token generator written by the Firebase team here. Don't forget the JWT PHP library this token generator relies on.
The token generator takes what is called a Firebase secret (you can find this in your particular Firebase instance page) passed into its class constructor and returns a random token based on this secret.

Resources