Which firebase value from firebase-auth to use as uid in my own database?

Viewed 687

I'm using Firebase auth and I need to store the authenticated user in my own User table (I only plan to use firebase auth, and not their backend services). However, I'm unsure which value provided by firebase should be used as the unique identifier.

In the docs, Firebase states:

 uid = user.uid;  // The user's ID, unique to the Firebase project. Do NOT use
                   // this value to authenticate with your backend server, if
                   // you have one. Use User.getToken() instead.

According to that comment above (seen here: https://firebase.google.com/docs/auth/web/manage-users) that mean that I can't rely on the uid?

Are they saying I should use

 user.getIdToken().then((token) => {
  // is this my UUID that I should store in my own db
  // this one? Its 926 characters long, 
  console.log(token);
 });
2 Answers

Key your own user table using the Firebase Auth user.uid.

Client side:

Your web application runs in your end-user's browser and makes use of the Firebase Client SDK. For example, an email and password signin might look something like this:

firebase.auth().signInWithEmailAndPassword(email, password)
  .then((user) => {
    // Signed in 
    // ...
  })
  .catch((error) => {
    var errorCode = error.code;
    var errorMessage = error.message;
  });

https://firebase.google.com/docs/auth/web/start#sign_in_existing_users

Behind the scenes the browser gets a JWT from the Firebase Auth Service. Each hour the tokens are renewed and you can get these by using an event listener.

firebase.auth().onAuthStateChanged((user) => {
  if (user) {
    // User is signed in, see docs for a list of available properties
    // https://firebase.google.com/docs/reference/js/firebase.User
    var uid = user.uid;
    // ...
    // Get the JWT (see line below)
  } else {
    // User is signed out
    // ...
  }
});

From the user object you can get hold of the JWT (stored in the client's browser).

const jwt = await getIdToken().token;

(Note, I've mixed async/await style and .then paradigms here, so you will need to pick one).

Once your have a JWT you use this to call your backend service, typically sending it within the header of an HTTP request.

Server side:

Extract the JWT from the HTTP request header into idToken and then verify the token using verifyIdToken(idToken). This method runs in a privileged environment (Admin SDK). Behind the scenes the verifyIdToken contacts the Firebase Auth Service to authenticate the JWT. The Firebase Auth Service is hosted within Google's infrastructure but you have no access to it direct- only via the verifyIdToken call.

If your backend service is running on the other side of the planet there will be a higher latency when calling verifyIdToken. There maybe some caching but this certaintly applies on your first request at the very least. This is why I wrote in my comment under your question that you might want to consider hosting your backend service within GCP.

You should not be storing JWTs inside your database as they are regenerated hourly by the Firebase Auth Client.

Once authenticated by your backend you can extract the uid from the JWT.

// idToken comes from the client app
admin
  .auth()
  .verifyIdToken(idToken)
  .then((decodedToken) => {
    const uid = decodedToken.uid;
    // ...
  })
  .catch((error) => {
    // Handle error
  });

https://firebase.google.com/docs/auth/admin/verify-id-tokens#verify_id_tokens_using_the_firebase_admin_sdk

You can definitely use the UID as the unique key for per-user data in your database. That's what way it's intended to be used.

I think you might be misinterpreting the comment. The problem that it's trying to address is sending the UID to your own backend via an API call. That call could be faked by anyone who knows how to call the API endpoint, which means they could send any UID they want. For those cases, the client app is supposed to instead supply an ID token to the back for it to validate with the Firebase Admin SDK. This is the only secure way to send information about the user for your backend so that it can't be hacked.

If you aren't sending the UID to a backend, then you don't need to send a token and validate it. If you are simply using the UID locally or through other Firebase products that implement security rules, you don't need to worry about tokens at all.

Related