Nuxt Sign-in With Firebase Auth V9 Modular With FirebaseUI

Setup Nuxt With Firebase V9 Modular.

Create components/SignIn.vue.

<template>  <div id="firebaseui-auth-container">    <!-- <b-skeleton height="48px" v-if="loading"></b-skeleton>-->    <v-if="loading">Loading ...</v-if="loading">  </div></template><script>import { GoogleAuthProvider } from "firebase/auth";// cannot put here, else window is not defined// import firebaseui from "firebaseui";import "firebaseui/dist/firebaseui.css"export default {  data() {    return {      loading: true    }  },  async mounted() {    const auth = await this.$fire.getAuth()    // const { GoogleAuthProvider } = await import("firebase/auth");    const firebaseui = await import('firebaseui')    // import("firebaseui/dist/firebaseui.css")    const ui = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(auth)    const _this = this    const config = {      signInOptions: [        // this.$fireModule.auth.GoogleAuthProvider.PROVIDER_ID        GoogleAuthProvider.PROVIDER_ID      ],      signInFlow: 'popup',      // signInSuccessUrl: '/',      // tosUrl: '/tos',      // privacyPolicyUrl: '/privacy',      callbacks: {        signInSuccessWithAuthResult() {          // console.log('signInSuccessWithAuthResult')          _this.$emit('success')        },        uiShown: () => {          // console.log('uiShown')          this.loading = false        }      }    }    ui.start('#firebaseui-auth-container', config)  }}  </script>

Usage

<template>  <div>    <sign-in v-on:success="onSignIn()" />  </div></template><script>export default {  props: ['value'],  methods: {    onSignIn() {      // this.$emit('update:value', false)      const user = this.$fire.auth.currentUser;    },    signOut() {      // assume await this.$fire.getAuth() is already called      this.$fire.auth.signOut()    }    /*    async signOut() {      const auth = await this.$fire.getAuth()      auth.signOut()    }     */  },}</script>

Listen to user sign-in via onAuthStateChanged, and write to vuex store.

async getAuth() {  if (!this.auth) {    const { getAuth, onAuthStateChanged } = await import("firebase/auth")    const firebaseApp = await this.getApp()    this.auth = getAuth(firebaseApp)    onAuthStateChanged(this.auth, async (authUser) => {      const claims = authUser ? (await authUser.getIdTokenResult(true)).claims : null      if (authUser) {        // I only run app check when user signin        await fire.getAppCheck()      }      // store       await store.dispatch('onAuthStateChangedAction', { authUser, claims })    })  }  return this.auth}

Edit store/index.js

export const state = () => ({  user: false,})export const mutations = {  ON_AUTH_STATE_CHANGED_MUTATION: async (state, { authUser, claims, user }) => {    if (authUser) {      const data = {        uid: authUser.uid,        // email: authUser.email,        displayName: authUser.displayName,      }      if (user) {        data.displayName = user.name      }      if (claims.isAdmin) {        data.isAdmin = true      }      state.user = data    }    else {      state.user = false    }    if (process.client && window.localStorage) {      /**       * Auth.onAuthStateChanged is delayed by 0.35s on first load before you can access the user object       * Alternatively you can store part of user object in window.localStorage for quicker access, but less safe       */       /*      try {        let data = JSON.stringify(state.user)        localStorage.setItem('__user__', data)      }      catch(err) {        console.error('localStorage fail', err)      }       */    }  },}export const actions = {  async onAuthStateChangedAction({ commit }, { authUser, claims }) {    let user = null    if (authUser) {      const db = await this.$fire.getFirestore()       // fetch user object from database      // getItem is my custom helper funtion      user = await db.getItem('user', authUser.uid)    }    commit('ON_AUTH_STATE_CHANGED_MUTATION', { authUser, claims, user })  }}

Access user object from any page or component.

<script>export default {  computed: {    currentUser() {      /*      if (process.client && !this.$store.state.user && window.localStorage) {        const json = localStorage.getItem('__user__')        if (json) {          try {             return JSON.parse(json)           }          catch (err) {            console.error('localStorage fail', err)          }        }      }       */      return this.$store.state.user    },    },}</script>

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.