4

I was unable to use "firebese app check" in a Next.js 13.4 project with the "app" directory in development mode. I tried using ReactFire, but I only encountered errors. The latest version of Next.js is in SSR, so I attempted to use effects to access the window object, but that didn't work either. I couldn't find any help online, including Chat GPT. Please could you help me with this issue.

I would like to use firebase appcheck within Nextjs (13.4 app directory) in dev mode.

1 Answers1

0

There are two things you need to do in order to get it working.

  • The First is to ensure that the app check initialization is happening on the client. You can encapsulate the initialization in a component with the "use client" directive (I have a providers.tsx to do this sort of thing) and then further encapsulate it in a useEffect with empty dependency array to ensure it is only ran once.

  • Next, is to ensure that the FIREBASE_APPCHECK_DEBUG_TOKEN attribute is available on the windows namespace.

I will show my entire providers.tsx so that you have context as to where this is being ran in the tree:

"use cleint";

// other imports...

import {
  initializeAppCheck,
  ReCaptchaEnterpriseProvider,
} from 'firebase/app-check'
import { app } from '@/lib/firebase'

export default function Providers({ children }: { children: React.ReactNode }) {
  const userProps = useUserData()
  const toastProps = useToast()
  const modalProps = useModal()

  // service worker initialization omitted for brevity.

  useEffect(() => {
    console.log('initializing app check')
    // Firebase uses a global variable to check if app check is enabled in a dev environment
    if (process.env.NODE_ENV !== 'production') {
      Object.assign(window, {
        FIREBASE_APPCHECK_DEBUG_TOKEN:
          process.env.NEXT_PUBLIC_APP_CHECK_DEBUG_TOKEN,
      })
    }

    // NOTE* app is my Firebase APP instance, which I've imported
    initializeAppCheck(app, {
      provider: new ReCaptchaEnterpriseProvider(
        process.env.NEXT_PUBLIC_RECAPTCHA_ENTERPRISE_KEY as string
      ),
      isTokenAutoRefreshEnabled: true,
    })
  }, [])

  return (
    <UserContext.Provider value={userProps}>
      <Analytics />
      <ModalContext.Provider value={modalProps}>
        <ToastContext.Provider value={toastProps}>
          {children}
          <ToastContainer />
        </ToastContext.Provider>
      </ModalContext.Provider>
      <Modal
        open={modalProps.showModal}
        setOpen={modalProps.setShowModal}
        preventOutsideClick={modalProps.preventOutsideClick}
      >
        {modalProps.modalChildren}
      </Modal>
      <div id="recaptcha-container"></div>
    </UserContext.Provider>
  )
}

And this is how Providers is being used in the Root Layout:

export default function Rootlayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html
      lang="en"
    >
      <body>
        <Providers> 
          <Header />
          <main>{children}</main>
          <Footer />
        </Providers>
      </body>
    </html>
  )
}
Rafael Zasas
  • 891
  • 8
  • 27