DEV Community

Chinwendu Agbaetuo
Chinwendu Agbaetuo

Posted on • Edited on

Firebase Authentication with Next

I had to work on a project that required me to setup Firebase authentication. This is my first time using Firebase, after countless research and numerous YouTube tutorials. I finally got a hang of it, so I would love to share how I was able to configure it as well as setup protected routes.

Step One: Setup Firebase Console
To setup the console this tutorial was helpful.

Step Two: Install Firebase packages

yarn add firebase

yarn add react-firebase-hooks

Step Three: Create .env.local file and add setup Firebase configuration

// .env.local 
NEXT_PUBLIC_FIREBASE_API_KEY=<YOUR API KEY>
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=<YOUR AUTH DOMAIN>
NEXT_PUBLIC_FIREBASE_PROJECT_ID=<YOUR PROJECT ID>
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=<YOUR STORAGE BUCKET>
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=<YOUR SENDER ID>
NEXT_PUBLIC_FIREBASE_APP_ID=<YOUR APP ID>
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=<YOUR MEASUREMENT ID>
Enter fullscreen mode Exit fullscreen mode

Step Four: Setup Firebase configuration file

//firebaseClient.tsx
import { getAuth, GoogleAuthProvider } from "@firebase/auth";
import { initializeApp } from "firebase/app";

// Nextjs Web Firebase configuration
const firebaseConfig = { 
    apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
    authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
    projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
    storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
    measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};

const firebaseApp = initializeApp(firebaseConfig);

export const googleProvider = new GoogleAuthProvider();

export const firebaseAuth = getAuth(firebaseApp);

Enter fullscreen mode Exit fullscreen mode

Step Five: Pass firebase auth state where it is needed

// google-login.tsx
import { useAuthState } from "react-firebase-hooks/auth";
import { firebaseAuth, googleProvider } from "config/firebaseClient";
import { signInWithPopup } from "firebase/auth";
import Link from "next/link";

export default function GoogleSignIn () {
  const handleLogin = async () => {
        await signInWithPopup(firebaseAuth, googleProvider);  
  };

  const [user, loading] = useAuthState(firebaseAuth);

return (
   {loading ? (
        <></> 
        ) : (
            <>
            {user ? (                
                <img 
                  src={user?.photoURL}
                  alt={user?.displayName} />               
                ) : (
                <button onClick={handleLogin}>
                  Login
                </button>
              )}
            </>
          )}
     )
}

Enter fullscreen mode Exit fullscreen mode

Step Six: Protected routes
Protecting routes that can only be accessed when user is authenticated.

// profile.tsx
import { useAuthState } from "react-firebase-hooks/auth";
import { firebaseAuth } from "config/firebaseClient";
import { signOut } from "firebase/auth";
import Link from "next/link";

export default function Profile() {
    const [user] = useAuthState(firebaseAuth);

    return <h1>This is the profile page</h1>
}

// Navigate to login page if user isn't authenticated 
Profile.getInitialProps async function(ctx: any) {
  const { req } = ctx;
  const user = await firebaseAuth.currentUser;
  if (!user) {
    ctx.res.writeHead(302, {
      Location: "/login",
    });
    ctx.res.end();
  }
  return { user };
};

Enter fullscreen mode Exit fullscreen mode

Step Seven: Pass Environment variables into hosting platform
The .env.local file is included in the .gitignore file, that means it needs to be configured on the hosting platform. If hosting with vercel, go to the project settings, and proceed to the Environment Variables section, and fill in the Firebase configuration.

Please, let me know, if this method worked for you, or what can be improved. Thanks for reading!!!

Top comments (0)