skip to Main Content

I have used firebase to authenticate a user inside my app. However getting their metadata to show last sign in date and account creation data has been a hassle. The documentation here doesn’t help much. Is quite confusing.

I know I can import {UserMetadata} from "firebase/auth" but whatever I’ve tried after that does not work. It seems like the documentation is based on Typescript and I’ve been getting errors.

I am expeting to get the metadata in a similar format to this if possible

<div className="membership_start_date account_overview_card">
   <h2 className='account_overview_card_title'>Member since</h2>
   <p className='account_overview_card_detail'>{metadata}</p>
</div>

I have tried importing UserMetaData in this way:

import {UserMetadata} from "firebase/auth"

const Account = () => {
  const metadata = UserMetadata()

  return (
     <p className='account_overview_card_detail'>{metadata.lastSignIn}</p>
  )
}
export default Account

The whole code is quite long so I’ve tried to resume it to the most necessary part. What am I doing wrong?

2

Answers


  1. First make sure you has fbAuth properly exported:

    import { initializeApp } from "firebase/app";
    import { getFunctions, connectFunctionsEmulator } from "firebase/functions";
    import { getAuth, connectAuthEmulator } from "firebase/auth";
    import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
    
    import fbConfig from "../../firebase.json";
    
    export const fbApp = initializeApp({
      apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
      authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
      databaseURL: import.meta.env.VITE_FIREBASE_DATABASE_URL,
      projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
      storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
      messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
      appId: import.meta.env.VITE_FIREBASE_APP_ID,
    });
    
    export const fbFunctions = getFunctions(fbApp);
    
    export const fbAuth = getAuth(fbApp);
    
    export const db = getFirestore(fbApp);
    
    if (import.meta.env.DEV) {
      connectFunctionsEmulator(
        fbFunctions,
        "localhost",
        fbConfig.emulators.functions.port
      );
      connectAuthEmulator(
        fbAuth,
        `http://localhost:${fbConfig.emulators.auth.port}`
      );
      connectFirestoreEmulator(db, `localhost`, fbConfig.emulators.firestore.port);
    }
    

    Then call at some point your desired authentication method:

    import { ref } from "vue";
    import { defineStore } from "pinia";
    import { GoogleAuthProvider, signInWithPopup, signOut } from "firebase/auth";
    import { fbAuth } from "../config/firebase";
    
    export const useUserStore = defineStore("user", () => {
    
      const user = ref({ uid: null });
      const lastUser = localStorage.getItem("lastUser");
    
      if (lastUser) {
        user.value = JSON.parse(lastUser);
      }
    
      const fbLogin = (e) => {
        console.log(e);
        if (!user.value || !user.value.uid) {
          const provider = new GoogleAuthProvider();
          signInWithPopup(fbAuth, provider).then((result) => {
            console.log(result);
            const {
              accessToken,
              displayName,
              email,
              emailVerified,
              isAnonymous,
              uid
            } = result.user;
            user.value = result.user;
            localStorage.setItem(
              "lastUser",
              JSON.stringify({
                accessToken,
                displayName,
                email,
                emailVerified,
                isAnonymous,
                uid
              })
            );
          });
        } else {
          signOut(fbAuth).then((e) => {
            user.value = { uid: null };
            console.log(e);
            console.log("user sign out");
            localStorage.removeItem("lastUser");
          });
        }
      };
    
      return { user, fbLogin };
    });
    

    Finally chek on your current user:

    <template>
      <div>
        <h1>Authenticate</h1>
        <button @click="userStore.fbLogin">Login/Logout</button>
        <p v-if="userStore?.user && userStore?.user?.uid">
          Hello, {{ userStore?.user?.displayName }}!
        </p>
        <p v-else>Not logged</p>
      </div>
    </template>
    
    <script setup>
    // https://firebase.google.com/docs/auth/web/manage-users#get_a_users_profile
    import { useUserStore } from "../stores/user";
    
    const userStore = useUserStore();
    </script>
    

    Full source code here. It’s written in vue but the general idea is very similar to it.

    Login or Signup to reply.
  2. UserMetadata is part of a user object. Assuming you already have sign in method. Then in auth state subscription method you can access user’s data:

    useEffect(() => {
        const unregisterAuthObserver = getAuth(firebaseApp).onAuthStateChanged(
          async (authUser) => {
            if (authUser) {
              // authUser.metadata?.creationTime <--- here
              // authUser.metadata?.lastSignInTime <-- and here
            }
          },
        );
    
         // Make sure we un-register Firebase observers when the component unmounts.
        return () => unregisterAuthObserver(); 
      }, [firebaseApp]);
    
    

    You can even test a short version having firebase globally set up:

    getAuth().currentUser?.metadata
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search