Cloud function authentication with limited privileges - firebase

I am creating a RESTful API for my firebase database using Cloud functions. All the tutorials and guides I found suggest using firebase-admin to get admin access to the database.
Here is my question:
Is there a way to access the database the same way as the user would have directly? Like getting the auth token from the user and passing it on to the database to make changes the same way the user would. The security rules should prevent me if I try to make changes to a different user.
Possible solution:
Access the database using the built-in REST API of the database and use ?auth=CREDENTIAL to authenticate the user. Is there an alternative using the firebase SDK?

Is there a way to access the database the same way as the user would have directly?
Yes there is, I recommend you check out the sample here. But it requires that your code decodes and verifies the JWT of that user. The easiest way to do this is with the Admin SDK.
The sample uses the JavaScript SDK to get the token from the client:
firebase.auth().currentUser.getToken()
It passes this token to the server, which then verifies it using the Admin SDK:
admin.auth().verifyIdToken(idToken)
You can then create a second instance of the admin SDK and set this UID for your database requests:
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://databaseName.firebaseio.com",
databaseAuthVariableOverride: {
uid: "my-service-worker"
}
});

Related

Can I use Firebase's authentication to protect data on my own private server?

Due to some constraints of my project I need to manage my api server and database separately from firebase, however there is nothing stoping me from using their other tools like analytics and in this particular case authentication.
I wanted to ask if following scenario is possible:
I authenticate user on my client app using their SDK's
I send relevant jwt data in headers of my API
Can I then somehow validate this on my server, so in essence avoid complex auth service and use firebase for this instead? Are there any examples, preferably for NodeJS server.
Yes you can, it's very common use case and firebase auth has been made with such usage in mind. As you said, send jwt data on headers, then on the server, you verify the token with firebase service:
var admin = require('firebase-admin');
admin.initializeApp(); //may require other steps, see last link
// idToken comes from the client app
admin.auth().verifyIdToken(idToken, true)//second argument is optional, checks whether the ID token was revoked
.then(function(decodedToken) {
let uid = decodedToken.uid;
// ...
}).catch(function(error) {
// Handle error
});
https://firebase.google.com/docs/auth/admin/verify-id-tokens
https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#verifyidtoken
https://firebase.google.com/docs/admin/setup

Is it possible to login as another user in Firebase?

I'm working on an application where I'll need to help users with certain tasks as part of my customer service. Rather than build a separate admin interface, I'd prefer to have the ability to impersonate users to use the app for them.
Is this something that Firebase can do?
Yes!
Using admin SDK and service account initialize Firebase app backend with:
admin.initializeApp({
credential: admin.credential.cert(service_account_json),
})
Obtain authentication token for the user you wish to impersonate:
const userId = "[impersonating user uid string]"
const token = await admin.auth().createCustomToken(userId)
Using frontend Firebase SDK authenticate user with:
const token = "[token string obtained in step 2]"
firebase.auth().signInWithCustomToken(token)
Done! You're now impersonating selected user.
For obvious security reasons the backend endpoint, like Google Cloud Function should require authentication and verify if user requesting custom token is actually a privileged user (admin), to avoid situation where any authenticated user is able to impersonate anyone.
The Firebase Authentication client-side SDKs have no built-in impersonation mechanism. To sign in as a specific user on these SDKs, you must know that user's credentials.
The Firebase Admin SDKs supports impersonating a user in its interaction with the Realtime Database. Since the Admin SDK is meant to be run in a trusted environment (such as your development machine, a server you control, or Cloud Functions) they run with administrative privileges. To learn more about impersonating a regular user here, see the documentation on authenticating with limited privileges.

In Firebase Realtime Database, how can an unauthenticated third-party server (using the Admin SDK) read unprotected data from my database?

Regarding the Firebase Realtime Database Admin SDK, in JAVA:
I have some info, in the database, which is not secret, and I allow its reading by unauthenticated devices. But I also need to let any third-party SERVERS read this info.
However, how can a server, using the Admin SDK, connect to my database without credentials:
FirebaseOptions options = new FirebaseOptions.Builder()
.setDatabaseUrl("https://xxx.firebaseio.com/")
.build();
The above code doesn't work:
java.lang.NullPointerException: FirebaseOptions must be initialized with setCredentials().
The error message is telling you that you need admin credentials to initialize the SDK. That's because the implication with using the Admin SDK is that you want admin access to the resources in a Firebase projects. If you don't want admin access, don't use the Admin SDK. Instead you can use the REST API.

Angularfire - Get email by uid? #askfirebase

I have an Ionic application using Firebase so I opted to use Angularfire. Currently running Angularfire4. In my application I store the uid and I want to get email related with that uid. I use the email/password login provided by firebase. How can I translate the uid to an email?
The only method found is when using nodejs.
The only data that is exposed in the client-side Authentication SDKs is the profile of the currently authenticated user.
There is no way to look up user data for a UID with the Firebase Authentication client-side SDKs. While admittedly convenient, it would make leaking user-data way too easy.
The only way to look up user data by UID is using the Admin SDK that you found. The idea is that you run those in a trusted environment (e.g. a server you control, or Cloud Functions) and selectively expose the user data that your app needs.

.net core Web API and Firebase Auth

I am developing a web application using .net Core Web API. So far I have used Identity to authenticate and manage users. Is it often the case and suggested to use an auth service like Google Firebase Auth while still having an own server backend?
I am thinking about using Google Firebase Auth so that users can login in different ways (using Facebook, Google, etc.).
However, I want to have a self hosted backend application and database.
Now I am asking myself:
How do I store user data on my server: Should I use the uid (returned from Firebase) as foreign key to save user related data in my database?
How can I make use of Roles (Identity)? How can I add/remove a Role from a particular user?
Should I store additional user data (like email, name, etc.) in my database or should I always retrieve those infos from the token!? Are those infos provided by Firebase Auth at all?
Thank you for bringing light into the darkness!
You have your own user database. You can verify the Firebase ID token when a user signs in and get your internal users Firebase custom token.
docs/auth/users
You store them in you own database and add them to you Firebase custom token.
That depends on how much data you need and if the data can differ from the Firebase base data.
Add Firebase to Your app
<script src="https://www.gstatic.com/firebasejs/4.1.3/firebase.js"></script>
<script>
// Initialize Firebase
// TODO: Replace with your project's customized code snippet
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>",
};
firebase.initializeApp(config);
</script>
If you haven't yet connected your app to your Firebase project, do so from the Firebase console.
Enable Email/Password sign-in:
In the Firebase console, open the Auth section.
On the Sign in method tab, enable the Email/password sign-in method and click Save.
Create a password-based account
Create a new account by passing the new user's email address and password to createUserWithEmailAndPassword:
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
for more information please go through
https://firebase.google.com/docs/auth/web/password-auth

Resources