DEV Community

Cover image for Full Stack Instagram: Authentication + Guest
Arnold Samuel Chan
Arnold Samuel Chan

Posted on

Full Stack Instagram: Authentication + Guest

With Firebase Auth, life is much better in handling authentication.

We can authenticate and manage users from a variety of providers without server-side code.

Features that I love from Firebase Auth:

  • CRUD of user
  • Handling session cookies
  • Forget password emailing system
  • Easy sign up with any other platform
  • Reliable security
  • Can be handled only from client side

And the best part of this, that we can use it for free! For any number of users!

Table of contents:

  • Demo
  • Overview
  • Setting up Firebase
  • Sign up
  • Sign in
  • Anonymous sign in
  • Content Update
  • Log out

Demo

You can check on the full source code and try them in Replit.

Repl url: https://replit.com/@arnoldschan/AuthManagement

394856ce167079f6cbe42c76c0e738ec

Overview

User flow

  1. As a user, they can:
    • Sign up using: email, username, and password
    • Sign in by registered email and password
    • Sign in as a guest (without any credentials)
  2. The page body greets the user with their registered username (if the user is a guest, a random username will be generated)
  3. The page body shows "Logged out" if the user is not authenticated in the app.

File tree:

Untitled (1)

This is how the project file tree looks like.

  • The main App.jsx is in root folder
  • The smaller components in components/ folder
  • Components' css in css/ folder
  • Anything related to firebase is inside firebase/folder

Setting up Firebase

Setting up the project

To use Firebase you need to create a Google Cloud Platform account. Don't worry you don't need to fill in any payment information.

  1. Login to Firebase
  2. Create a project, then go to firebase auth
  3. Add a web app to your project

2c2086c604f003d135b163ce7e06c5a8

  1. Get your config afterward in the "Add Firebase SDK" section. Copy the JSON config and store it in firebaseConfig.js. This how I store the JSON config:
// firebaseConfig.js

const firebaseConfig = {
    apiKey: "AIzaSyAdqA_wVseC23-5-q5Fo1f0dGiB-177Tu0",
    authDomain: "codepen-arnold.firebaseapp.com",
    projectId: "codepen-arnold",
    storageBucket: "codepen-arnold.appspot.com",
    messagingSenderId: "1080777819655",
    appId: "1:1080777819655:web:5269709a063489308acca2",
    measurementId: "G-4Y54EK18HW"
  };

export default firebaseConfig;
Enter fullscreen mode Exit fullscreen mode

Don't worry this config is needed to be publicly available for interacting with Firebase services. Nothing to hide here 😂

Setting up authentication

  1. Activate email sign in method 508cc75abe265bbf8be537036aca5735
  2. Activate anonymous Authentication (optional) 0415b606ce60c3731e5387216aa55ac7
  3. Initiate firebase module in firebase.js (don't forget to npm install firebase)
// firebase.js
import firebase from 'firebase';
import firebaseConfig from "./firebaseConfig";
const firebaseApp = firebase.initializeApp(
    firebaseConfig
)
const auth = firebaseApp.auth();

export { auth }
Enter fullscreen mode Exit fullscreen mode

This short and simple lines would boost our app capability!

auth consists of various methods needed for interacting with the user's authentication information. You can read more here in Firebase auth documentation.

Now we're ready to store our user information! Let's move on to handling the user flow scenarios.

State Hooks

const [openModalSignup, setOpenModalSignup] = useState(false)
const [openModalLogin, setOpenModalLogin] = useState(false)
const [user, setUser] = useState(null)
Enter fullscreen mode Exit fullscreen mode

There are 3 state hooks in this App:

  • openModalSignup and openModalLogin: Control 2 modals: Sign up and Sign in form. If the state value is true then the modal will be visible, otherwise closed.
  • user : stores the Firebase user information attached in the app session.

All of the user authentication processes happen in AuthModal.jsx. Because in this modal, the user interacts with their credentials and all of the action needed for authentications.

User sign up

The sign up process is controlled by a single function: registerUser

// AuthModal.jsx
import { auth } from "../firebase/firebase";
// ...
const registerUser = () => {
        auth.createUserWithEmailAndPassword(email, password)
        .then((authUser)=>{
            authUser.user.updateProfile({
                displayName: username
            }).then((user)=> setUser(user))
        })
        .catch((error)=> alert(error.message));
        setOpenModalSignup(false);
    }
// ...
Enter fullscreen mode Exit fullscreen mode

After importing auth module from the initiated firebase modules, we can use auth.createUserWithEmailAndPassword method. It's quite self-explanatory what does this method do, right?

The method takes 2 arguments: email and password . And boom, a new user is created in our Firebase Auth database. Very easy, no more pain in creating the API, Database, and everything!

This method then chained into adding displayName attached to this user through user.updateProfile method. Firebase provides several additional information for users. Check more here. After that, the new user information is updated into user state hooks through setUser. The sign-up modal is then closed through setOpenModalSignup state hooks.

User sign in

The sign in process is controlled by loginUser function

// AuthModal.jsx
import { auth } from "../firebase/firebase";
// ...
const loginUser = () => {
        auth.signInWithEmailAndPassword(email, password)
        .catch((error)=> alert(error.message));
        setOpenModalLogin(false);
    }
// ...
Enter fullscreen mode Exit fullscreen mode

After creating the user through auth.createUserWithEmailAndPassword , we can sign the user in using auth.signInWithEmailAndPassword method. The arguments are email and password as well. The login modal then closed by turning setOpenModalLogin value to false .

Anonymous Sign In

For some apps, it'll be a big barrier for users if they needed to register before trying the apps. Firebase provides an "anonymous sign-in" feature. Here, the user doesn't need to fill any email information, and can try the apps right away!

The anonymous sign-in is controlled by guestButtonPress function

// AuthModal.jsx
import { auth } from "../firebase/firebase";
// ...
const guestButtonPress = () => {
        let randomName = "guest-" + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
        auth.signInAnonymously()
        .then((user) => {
            user.user.updateProfile({
                displayName: randomName
            }).then((user)=> setUser(user))
            setOpenModalLogin(false);
        })
    }
Enter fullscreen mode Exit fullscreen mode

There are 3 fields in our registration form: e-mail , display name, and password. We can skip e-mail and password for anonymous sign-in, but we need to manually set the display name information. Otherwise, the missing display name will break our app.

To handle this, the app generates a randomName for the user's display name before firing the firebase auth.signInAnonymously method. The generated randomName has pattern of: guest-xxxxx with x represents a random letter.

Just like in the sign-up process, the new user displayName is updated through user.updateProfile method and then sequentially update our user state hooks by calling setUser. The login modal then closed by setting setOpenModalLogin as false.

Content Update

// App.jsx
import { auth } from "./firebase/firebase";
// ...
useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged((authUser)=>{
      if (authUser){
        setUser(authUser);
      } else {
        setUser(null);
      }})
    return () => {
      unsubscribe();
    }
  }, [ user ])
//...
Enter fullscreen mode Exit fullscreen mode

The useEffect hooks in App.jsx contains the Firebase Auth state listener. Any event done by user in the previous scenarios (sign-in, sign-out) updates the Firebase's auth state.

This listener also remembers the user's previous session (session stored in the user's browser) and automatically loads all of the information. This feature is very convenient as the user doesn't need to re-enter the credentials again.

//App.jsx
//...
<div className="contents">
        <h1>
        { user ?
            "Welcome back " + user.displayName + "!"
            : 
            "Logged out!"
        }
        </h1>
</div>
//...
Enter fullscreen mode Exit fullscreen mode

By using the ternary operator, the content shows "Welcome back {displayName}" if user contains the session information. Otherwise, the content shows "Logged out!".

User Sign out

Finally, if the user wants to log out from the session, we can call auth.signOut method. Here's the log-out button in AuthButton.jsx.

// AuthButton.jsx
// ...
<Button onClick={() => {
      auth.signOut();
    }}>
Log Out
</Button>
//...
Enter fullscreen mode Exit fullscreen mode

Conclusion

Cool, isn't it?

With Firebase, it's faster for us to implement many basic features. In this article, we can see how easy to interact with Firebase authentication feature. Everything can be done from client-side.

Which benefit of Firebase Auth that you're really love about? Leave your thoughts in the comment below!

Top comments (2)

Collapse
 
bam92 profile image
Abel Lifaefi Mbula

Great post. Thanks for sharing.

Collapse
 
arnoldschan profile image
Arnold Samuel Chan

Hi Abel,
Thank you! You are very welcomed.