Skip to main content

Overview

Argument Analysis Tool uses Firebase Authentication to manage user accounts and secure access to the platform. All users must be authenticated to analyze arguments and save their work.
Firebase Authentication provides enterprise-grade security with features like token-based sessions, automatic token refresh, and secure credential storage.

Authentication flow

The application uses Firebase Authentication with email/password as the primary sign-in method.

How it works

1

User signs up or logs in

Users provide their email and password through the signup or login form
2

Firebase validates credentials

Firebase Authentication verifies the credentials and returns a user object
3

Token generation

A secure ID token is generated for the authenticated user
4

Session management

The token is stored in cookies and sent with subsequent requests
5

Protected access

The user can now access protected features like argument analysis

Firebase setup

The application initializes Firebase on the client side with the following configuration:
// src/firebase/config.ts
export const firebaseConfig = {
  "projectId": "studio-7810500568-bbe5f",
  "appId": "1:316540606453:web:d3d4a0f08275a6f2e772bc",
  "apiKey": "AIzaSyDlUm2UEmDtWFTaNkLdWOXCC1FYlZgAqAM",
  "authDomain": "studio-7810500568-bbe5f.firebaseapp.com",
  "measurementId": "",
  "messagingSenderId": "316540606453"
};

Initialization

Firebase is initialized once when the app loads:
// src/firebase/index.ts
import { initializeApp, getApps, getApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';

export function initializeFirebase() {
  if (!getApps().length) {
    let firebaseApp;
    try {
      // Attempt automatic initialization (Firebase App Hosting)
      firebaseApp = initializeApp();
    } catch (e) {
      // Fall back to manual configuration
      firebaseApp = initializeApp(firebaseConfig);
    }
    return getSdks(firebaseApp);
  }
  return getSdks(getApp());
}

export function getSdks(firebaseApp: FirebaseApp) {
  return {
    firebaseApp,
    auth: getAuth(firebaseApp),
    firestore: getFirestore(firebaseApp)
  };
}
The initialization function first attempts to use Firebase App Hosting environment variables, then falls back to the explicit config. This enables seamless deployment across environments.

Creating an account

Users can create a new account through the signup page.

Signup process

// src/app/signup/page.tsx
import { createUserWithEmailAndPassword } from 'firebase/auth';
import { useAuth } from '@/firebase';

const handleSignup = async (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  setIsLoading(true);
  setError(null);

  if (!email || !password) {
    setError('Email and password are required.');
    setIsLoading(false);
    return;
  }

  try {
    await createUserWithEmailAndPassword(auth, email, password);
    toast({
      title: 'Signup Successful',
      description: 'Please log in with your new account.',
    });
    router.push('/login');
  } catch (e: unknown) {
    if (e instanceof FirebaseError) {
      if (e.code === 'auth/email-already-in-use') {
        setError('This email address is already in use.');
      } else {
        setError(e.message);
      }
    }
  }
};

Error handling

The signup form handles common Firebase errors:
Error CodeUser Message
auth/email-already-in-useThis email address is already in use
auth/weak-passwordPassword should be at least 6 characters
auth/invalid-emailPlease enter a valid email address
Passwords must be at least 6 characters long. Firebase enforces this minimum for security.

Logging in

Existing users can log in using their email and password.

Login process

// src/app/login/page.tsx
import { signInWithEmailAndPassword } from 'firebase/auth';
import Cookies from 'js-cookie';

const handleLogin = async (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  setIsLoading(true);
  setError(null);

  try {
    const userCredential = await signInWithEmailAndPassword(
      auth, 
      email, 
      password
    );
    const token = await userCredential.user.getIdToken();
    
    // Store token in cookie for subsequent requests
    Cookies.set('AuthToken', token, { expires: 1, path: '/' });
    
    router.push('/');
  } catch (e: unknown) {
    if (e instanceof FirebaseError) {
      switch (e.code) {
        case 'auth/user-not-found':
          setError('No user found with this email.');
          break;
        case 'auth/wrong-password':
          setError('Incorrect password. Please try again.');
          break;
        case 'auth/invalid-credential':
          setError('Invalid credentials. Please check your email and password.');
          break;
        default:
          setError(e.message);
      }
    }
  }
};

Login error handling

Error CodeUser Message
auth/user-not-foundNo user found with this email
auth/wrong-passwordIncorrect password. Please try again
auth/invalid-credentialInvalid credentials. Please check your email and password
auth/too-many-requestsToo many failed attempts. Try again later

Session management

Once authenticated, the user’s session is maintained through ID tokens.

Token storage

ID tokens are stored in cookies:
// Set token after login
const token = await userCredential.user.getIdToken();
Cookies.set('AuthToken', token, { 
  expires: 1,  // 1 day
  path: '/'    // Available to all routes
});

Token usage

The authentication token is included with API requests:
// src/app/page.tsx
const { user } = useUser();
const [authToken, setAuthToken] = useState<string | null>(null);

useEffect(() => {
  if (user) {
    user.getIdToken().then(token => setAuthToken(token));
  }
}, [user]);

// Token is sent with analysis requests
<InputForm formAction={formAction} authToken={authToken} />

Protected routes

The home page automatically redirects unauthenticated users:
// src/app/page.tsx
const { user, isUserLoading } = useUser();
const router = useRouter();

useEffect(() => {
  if (!isUserLoading && !user) {
    router.push('/login');
  }
}, [user, isUserLoading, router]);

if (isUserLoading || !user) {
  return <LoadingSpinner />;
}
The useUser hook provides reactive access to the current user state, automatically updating components when authentication status changes.

User context

The application uses React Context to provide user information throughout the component tree.

Using the useUser hook

import { useUser } from '@/firebase';

export default function MyComponent() {
  const { user, isUserLoading } = useUser();
  
  if (isUserLoading) {
    return <LoadingSpinner />;
  }
  
  if (!user) {
    return <div>Please log in</div>;
  }
  
  return <div>Welcome, {user.email}</div>;
}

Using the useAuth hook

For direct access to the Firebase Auth instance:
import { useAuth } from '@/firebase';
import { signOut } from 'firebase/auth';

export default function LogoutButton() {
  const auth = useAuth();
  
  const handleLogout = async () => {
    await signOut(auth);
  };
  
  return <button onClick={handleLogout}>Logout</button>;
}

Security considerations

Token expiration

Firebase ID tokens expire after 1 hour. The Firebase SDK automatically refreshes tokens:
  • Tokens are refreshed in the background
  • No user action required
  • Seamless continuation of sessions
Authentication cookies are configured for security:
Cookies.set('AuthToken', token, { 
  expires: 1,      // 1 day expiration
  path: '/',       // Available to all routes
  // In production, also set:
  // secure: true,     // HTTPS only
  // sameSite: 'strict' // CSRF protection
});
In production environments, ensure cookies are set with secure: true to require HTTPS and sameSite: 'strict' for CSRF protection.

Client-side validation

All authentication forms include client-side validation:
  • Email format validation
  • Password length requirements
  • Required field checks
  • Real-time error feedback

Common authentication patterns

Check if user is logged in

const { user, isUserLoading } = useUser();

if (isUserLoading) {
  return <LoadingSpinner />;
}

if (user) {
  // User is authenticated
} else {
  // User is not authenticated
}

Redirect after login

const handleLogin = async () => {
  await signInWithEmailAndPassword(auth, email, password);
  router.push('/');  // Redirect to home page
};

Logout user

import { signOut } from 'firebase/auth';

const handleLogout = async () => {
  await signOut(auth);
  router.push('/login');
};

Get current user’s token

const token = await user.getIdToken();
// Use token in API requests

User Profile

Once authenticated, users can access their profile page at /profile to view their account information:
  • Email address - The email associated with the account
  • User ID - The unique Firebase user identifier
The profile page is protected and requires authentication. If a user is not logged in, they will be redirected to the login page.

Next steps

Start analyzing arguments

Follow the quickstart guide to analyze your first argument

Back to introduction

Return to the main documentation page

Build docs developers (and LLMs) love