30

I need to get a user object, specifically the user email, I will have the user id in this format:

simplelogin:6

So I need to write a function something like this:

getUserEmail('simplelogin:6')

Is that possible?

Qwerty
  • 29,062
  • 22
  • 108
  • 136
Jordash
  • 2,926
  • 8
  • 38
  • 77
  • 2
    This is old but no good answer. Did you ever solve it yourself? Is it similar for phone numbers (new feature since this question was asked) – Peter Bengtsson Jul 17 '17 at 12:17

6 Answers6

31

It is possible with Admin SDK

Admin SDK cannot be used on client, only in Firebase Cloud Functions which you can then call from client. You will be provided with these promises: (it's really easy to set a cloud function up.)

admin.auth().getUser(uid)
admin.auth().getUserByEmail(email)
admin.auth().getUserByPhoneNumber(phoneNumber)

See here https://firebase.google.com/docs/auth/admin/manage-users#retrieve_user_data


In short, this is what you are looking for

admin.auth().getUser(data.uid)
  .then(userRecord => resolve(userRecord.toJSON().email))
  .catch(error => reject({status: 'error', code: 500, error}))

full snippet

In the code below, I first verify that the user who calls this function is authorized to display such sensitive information about anybody by checking if his uid is under the node userRights/admin.

export const getUser = functions.https.onCall((data, context) => {
  if (!context.auth) return {status: 'error', code: 401, message: 'Not signed in'}

  return new Promise((resolve, reject) => {
    // verify user's rights
    admin.database().ref('userRights/admin').child(context.auth.uid).once('value', snapshot => {
      if (snapshot.val() === true) {
        // query user data
        admin.auth().getUser(data.uid)
          .then(userRecord => {
            resolve(userRecord.toJSON()) // WARNING! Filter the json first, it contains password hash!
          })
          .catch(error => {
            console.error('Error fetching user data:', error)
            reject({status: 'error', code: 500, error})
          })
      } else {
        reject({status: 'error', code: 403, message: 'Forbidden'})
      }
    })
  })
})

BTW, read about difference between onCall() and onRequest() here.

Qwerty
  • 29,062
  • 22
  • 108
  • 136
  • You don't need Firebase Functions for this. See my answer: https://stackoverflow.com/a/66544110/336753 – kub1x Mar 09 '21 at 09:25
  • 1
    @kub1x Admin SDK (which you also use in your answer) doesn't run on client and if you only have a client-side application without server, your only option (and frankly easiest) is to use one Firebase Function (full code above). Anyway, my solution doesn't actually require the use of Functions. If you only care about server-side, then the first snippet is what you are looking for. The Function snippet is there as a bonus, which just allows the user to get the information back to client. – Qwerty Mar 09 '21 at 20:46
  • 1
    OP didn't specify if he needs to do this as part of app logic or as a one-time batch script (like in my case). Such script can be called from my computer and be completely separate from the app infrastructure. Writing and deploying a cloud function, and writing and deploying client code to call the function is a lot of needless work when you want to initiate the process manually. It is different case than in your answer but it still answers the question. I was relieved to figure out no cloud function was needed for this, hence the comment. – kub1x Mar 15 '21 at 13:10
  • 1
    Oh, lol , I see @kub1x, forgive me then. It is now obvious how your solution works, I missed that, sorry. Yes, your solution is perfect in that sense. I just assumed the OP needs to use it in the code somewhere, so my solution allows that both on server and client. I figured that if they needed it only one-time they could as well use the firebase web interface, but your batch script is also a valid solution and serves a purpose. – Qwerty Mar 16 '21 at 15:29
12

Current solution as per latest update of Firebase framework:

firebase.auth().currentUser && firebase.auth().currentUser.email

See: https://firebase.google.com/docs/reference/js/firebase.auth.Auth.html#currentuser

Every provider haven't a defined email address, but if user authenticate with email. then it will be a possible way to achieve above solution.

Sumit singh
  • 2,398
  • 1
  • 15
  • 30
Leonid Shevtsov
  • 14,024
  • 9
  • 51
  • 82
  • 1
    How is this going to give the e-mail of any user by a given id? – scopchanov May 29 '20 at 02:01
  • because this question was renamed from "current user" to "any user". These are two very different questions, because you can only get _any_ user's email from the Admin SDK, meaning, from the backend. However, you can get the _current_ user's email from their session. – Leonid Shevtsov May 29 '20 at 07:04
  • 1
    The original title was _How to get any user object in Firebase based on user id_ though. – scopchanov May 29 '20 at 14:24
  • 1
    However, even with the _any_ part of the title omitted, the code still does not give any e-mail, but a boolean value. The sentence below make no sense as well. For me it is a strangely upvoted link only answer. – scopchanov May 29 '20 at 14:31
  • @LeonidShevtsov Even with the _any_ part of the title omitted, the body of the question makes very clear that it should be an email of any user. – Qwerty Feb 13 '21 at 11:56
  • I didn't know how to get the email of the currentUser. Thank You! – LUISAO Apr 21 '21 at 15:00
  • 1
    Just saying perfect use case for an optional chaining operator. `firebase.auth().currentUser?.email` – Marc M. Mar 10 '23 at 11:12
9

To get the email address of the currently logged in user, use the getAuth function. For email and password / simplelogin you should be able to get the email like this:

ref = new Firebase('https://YourFirebase.firebaseio.com');
email = ref.getAuth().password.email;

In my opinion, the password object is not very aptly named, since it contains the email field.

I believe it is not a Firebase feature to get the email address of just any user by uid. Certainly, this would expose the emails of all users to all users. If you do want this, you will need to save the email of each user to the database, by their uid, at the time of account creation. Other users will then be able to retrieve the email from the database by the uid .

6

simple get the firebaseauth instance. i created one default email and password in firebase. this is only for the security so that no one can get used other than who knows or who purchased our product to use our app. Next step we are providing singup screen for user account creation.

FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
    String email = user.getEmail();

every time user opens the app, user redirecting to dashboard if current user is not equal to our default email. below is the code

mAuth = FirebaseAuth.getInstance();
    if (mAuth.getCurrentUser() != null){
        String EMAIL= mAuth.getCurrentUser().getEmail();
            if (!EMAIL.equals("example@gmail.com")){
                startActivity(new Intent(LoginActivity.this,MainActivity.class));
                finish();
            }
    }

i Am also searching for the same solution finally i got it.

2

I had the same problem. Needed to replace email in Firestore by uid in order to not keep emails all around the place. It is possible to call it from a script on your computer using Service Account. You don't need Firebase Functions for this.

First Generate service account and download its json key.
Firebase Console > gear icon > Project settings > Service accounts > Generate a new private key button.
https://console.firebase.google.com/u/0/project/MYPROJECT/settings/serviceaccounts/adminsdk

Then create project, add the key and call the Admin SDK.

  1. npm init
  2. npm install dotenv firebase-admin
  3. Place the json key file from above into .keys directory, keeping the project directory clean of keys files. Also .gitignore the directory.
  4. Write the path of the json key file into .env file like this: GOOGLE_APPLICATION_CREDENTIALS=".keys/MYPROJECT-firebase-adminsdk-asdf-234lkjjfsoi.json". We will user dotenv to load it later.
  5. Write following code into index.js:
const admin = require('firebase-admin');

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
});

(async () => {
  const email = "admin@example.com";
  const auth = admin.auth();
  const user = await auth.getUserByEmail(email);
  // Or by uid as asked
  //const user = await auth.getUser(uid);
  console.log(user.uid, user.email);
  //const firestore = admin.firestore();
  // Here be dragons...
})();
  1. Run as follows node -r dotenv/config index.js

See the docs

kub1x
  • 3,272
  • 37
  • 38
0

Current solution (Xcode 11.0)

Auth.auth().currentUser? ?? "Mail"
Auth.auth().currentUser?.email ?? "User"