Migrate users to firebase auth, force uid generation before login - firebase

We are building an app that will launch soon on which users can authenticate using Firebase (Google and Facebook). Previously we have run a website to preregister users. On this website users can authenticate through Google and Facebook. On the website we haven't been using Firebase authentication.
The problem is that a lot of our code in the app works on the firebase auth uid. If a user that has signed in on the website contacts another user through the app, we connect them using the Firebase uid. This is a problem if the user hasn't logged in on the app after registering on the website. (The uid we keep in the backend changes from FB or Google uid to Firebase uid).
How should we connect the users on the website to the users in firebase? Is there a way we can predict/force the uid to something we can control?
Ideally registrations on the website should also still work after go-live.

You need to migrate your Google/Facebook user to Firebase Auth using the Firebase CLI SDK and then use Firebase to authenticate these users after migration. During migration you can use whatever UID you need for these users: https://firebase.google.com/docs/cli/auth#authimport

You can set up a server where you can create users with the Firebase Admin SDK. By default, a random uid is created, but you have the option to assign a specific uid. Here's the website's example using Node.js:
admin.auth().createUser({
uid: "some-uid",
email: "user#example.com",
phoneNumber: "+11234567890"
})
.then(function(userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully created new user:", userRecord.uid);
})
.catch(function(error) {
console.log("Error creating new user:", error);
});
The Admin SDK also offers the functionality for Java and Python if you prefer one of those languages.

Related

Firebase Authentication Admin Login Only

I'm building two Flutter apps that will use the same Firebase project.
The first app is public and used by users to create accounts, login and use the application within the allowed access rules.
The second is for admins to approve user posts.
You have to login to use both apps. With the first anyone can create an account and login. Admins can also login with the same admin account. But with the second only admin users should be able to login. I'm enforcing security via access rules. But I need the second admin app to reject non-admin users from login in in the first place. So I can't simply create a collection and put the admin user UIDs in it.
How do I differentiate regular users from admin users, and most importantly use that differentiation to disallow non-admin users from login in into the admin app?
Currently for login I'm simply using
FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
I read about something called user claims, but there doesn't seem to be a way to modify this in the dashboard nor is there a way to specify some kind of condition via the code above.
I hope this makes enough sense.
Thank you all
You cannot prevent anyone from logging in to your application. The best you can do is check if the user is an admin. If yes, proceed else force logout them. You can use Firebase Custom Claims to add admin users or you can even store their UIDs in Firestore or Realtime Database.
UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: "barry.allen#example.com",
password: "SuperSecretPassword!"
);
// Check for claims here
if (admin) {
//...
} else {
await FirebaseAuth.instance.signOut();
// or just show alert that user is not an admin
}
You can use the getIdTokenResult method to get user's custom claims. This answer explains how to verify custom claims in Flutter.

Can we use firebase with flutter just for authentication and custom server for everything else?

I an planning to make a social media application using flutter. I want to give the user ability to sign in using Google or Facebook accounts which can be easily done using firebase authentication but I am worried about the cost because within 2 months the number of users will be approximately 100,000. I was thinking of we could just sign up/sign in using firebase and store data and push/pull all the other requests from a hostgator server(mysql db).
And if it is possible can I do it using just dart language or do I need some other languages too like ruby, C# it python (I am not a big fan of php)
Yes, you can use Firebase just for authentication and your mysql db on Hostgator for everything else. Firebase auth is free (except to phone auth), as #Doug Stevenson has mentioned.
The (firebase) authentication can be done in your Flutter app. You do not need a server code to do this. Firebase auth gives back 'user' object with attributes like user name, email, profile photo url etc which you can store in your mySQL db as well (if required).
Firebase Authentication doesn't cost anything to use for signing in with Google or Facebook accounts. It doesn't cost any more based on the number of users you have. You are only going to be charged if you use phone authentication past the initial free tier limits, as described on the pricing page. So I wouldn't bee too concerned about costs.
You can do all the signups in client app code. You don't need a backend at all to use Firebase Auth, but you can bring any backend you want.
import 'package:express/express.dart';
import 'package:firebase_admin/firebase_admin.dart';
void main() async {
// Initialize the Firebase Admin SDK
await FirebaseAdmin.initializeApp(
credential: FirebaseAdmin.ServiceAccountCredential(
'/path/to/serviceAccountKey.json'));
// Create a new Express app
var app = Express();
// Implement the API endpoint for authentication
app.post('/login', (request, response) async {
// Get the user's email and password from the request body
var email = request.body['email'];
var password = request.body['password'];
// Verify the user's credentials using the Firebase Admin SDK
try {
var userRecord = await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
// If the login was successful, create a new session for the user
request.session['uid'] = userRecord.uid;
// Return a success response
response.send({'success': true});
} catch (error) {
// If the login failed, return an error response
response.send({'success': false, 'error': error.toString()});
}
});
// Start the server
app.listen(3000);
}

firebase react-native: convert anonymous user to a permanent user via phone auth

My react-native application allows users to sign in anonymously using firebase. After that I am hoping to allow user to create an account via firebase phone auth and convert this anonymous account into a permanent account.
I think this is possible based on the api & documentation provided by firebase
anonymous account creation:
https://rnfirebase.io/docs/v5.x.x/auth/reference/auth#signInAnonymously
phone auth creation & retrieve credential:
https://rnfirebase.io/docs/v5.x.x/auth/reference/PhoneAuthProvider#credential
Linking an existing user with a new credential:
https://rnfirebase.io/docs/v5.x.x/auth/reference/User#linkWithCredential
https://firebase.google.com/docs/auth/web/account-linking
Here's what I did
anonymous account creation:
const {user: {uid: userID}} = await firebase.auth().signInAnonymously();
// successfully created and save this user's id
get the users to authenticate and get the phone auth credential:
const credential = firebase.auth.PhoneAuthProvider.credential(verificationId, code);
at this point I would have a valid credential & an existing anonymous user ready for linking
I then provide the phone auth credential to my anonymous user for linking
const authUser = await firebaseAuth.currentUser.linkWithCredential(credential);
I expected a successful linking to happen based on my inputs, but I'm getting errors instead, the error I'm getting is
Error: This credential is already associated with a different user account.
Error code is: ERROR_CREDENTIAL_ALREADY_IN_USE
in the documentation under ERROR_CREDENTIAL_ALREADY_IN_USE, they did mention:
this error could be thrown if you are upgrading an anonymous user to a Google user by linking a Google credential to it and the Google credential used is already associated with an existing Firebase Google user.The fields error.email, error.phoneNumber, and error.credential (AuthCredential) may be provided, depending on the type of credential. You can recover from this error by signing in with error.credential directly via auth#signInWithCredential.
But I have not been able to find error.credential under the error object to come back from the error.
I have seen many working example of linking anonymous user with other auth providers, but never seen the linking of a firebase anonymous user with a firebase phone auth crendential. Does anyone know if this type of linking is supported? Could anyone point out what I'm doing wrong here?
Follow up:
So I actually found out that my code did work, and that is how you'd implement firebase anonymous user -> firebase phone auth account linking.
The reason this didn't work for me was because..... for our app, we had a micro-service creating accounts in the backend every time the user inputs the confirmation code. In hindsight I should have really double checked our own codebase, lesson learned.

Sending a Welcome email using Google Cloud Functions when the app uses Phone verification for authentication

I am trying to send a Welcome email using Google Cloud Functions, similar to what is done here:
https://github.com/firebase/functions-samples/tree/master/quickstarts/email-users
The problem is that my app uses Phone verification for authentication, we do however upload the users email and save it under the users UID in the Firebase Real time database.
Could we pull the email using the cloud function using the UID and then insert that into the javascript code? or is there another way of doing this?
Best,
Feras A.
You should be able to read from the realtime database with the Firebase Admin SDK:
return admin.database().ref(/* path to user's email */).once("value").then(function(snapshot) {
if (snapshot.val() === null) {
console.log("Error getting user email: user does not exist");
return;
}
const email = snapshot.child("email").val();
// Send email here
});
More information and examples can be found on the Firebase Admin Auth Guide (See the example under Authenticate with admin privileges).

.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