Authentication in the BAP Beta Tau frontend is centralised inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/asubap/website/llms.txt
Use this file to discover all available pages before exploring further.
src/context/auth/authProvider.tsx. It wraps the entire application in <AuthProvider>, which manages the Supabase session, resolves it to an application role via the backend, and exposes everything downstream through the useAuth() hook. Sponsor users follow a passcode-based path; members use Google OAuth. Both paths converge at the same AuthContext.
Supabase Client
Path:src/context/auth/supabaseClient.ts
The Supabase client is a singleton created with the anon key, configured to persist sessions in localStorage.
RoleType
TheRoleType union is the central type representing what a logged-in user is within the application.
| Value | Who it represents |
|---|---|
"general-member" | Standard inducted member |
"e-board" | Executive board member (admin-level access) |
"admin" | System administrator (treated like e-board) |
"pledge" | Pledge/candidate member |
"alumni" | Alumni member |
{ type: "sponsor", companyName: string } | Company sponsor user |
null | Not yet resolved, or unauthenticated |
AuthContext Shape
isAuthenticated is a derived boolean — it is true only when all three conditions hold:
sessionis non-null (Supabase session exists)roleis non-null (backend confirmed the user’s role)authErroris null (no auth errors)
AuthProvider
Path:src/context/auth/authProvider.tsx
AuthProvider wraps the entire React tree in App.tsx and drives the full auth lifecycle.
Initialization Flow
initializeAuth runs:
Get existing session
supabase.auth.getSession() checks localStorage for a persisted Supabase session. If found, setSession(session) is called immediately.Resolve role from backend
If
session?.user?.email exists, fetchUserRole(token, email) posts to POST /users with Authorization: Bearer <token>. A successful response calls setRole(data).Auth State Listener
role stays in sync with the Supabase session at all times.
Periodic Role Validation
Every 30 seconds,AuthProvider silently re-validates the session by calling fetchUserRole again:
useAuth Hook
useAuth() outside <AuthProvider> throws at runtime. Consume the hook in any component that needs auth state:
Return values
| Property | Type | Description |
|---|---|---|
session | Session | null | Raw Supabase session; contains access_token, user, etc. |
role | RoleType | Resolved application role |
loading | boolean | true during initial auth resolution |
authError | string | null | Error message from /users or Supabase |
isAuthenticated | boolean | session && role && !authError |
setSession | (session) => void | Used by SponsorAuth to inject a session |
setRole | (role) => void | Used by SponsorAuth to set "sponsor" role |
setAuthError | (error) => void | Used to clear errors programmatically |
Member Authentication — GoogleLogin
Path:src/components/auth/GoogleLogin.tsx
Members authenticate via Google OAuth using supabase.auth.signInWithOAuth. After OAuth completes, Supabase redirects to /login, where AuthProvider’s onAuthStateChange listener fires and calls fetchUserRole.
Sponsor Authentication — SponsorAuth
Path:src/components/auth/SponsorAuth.tsx
Sponsors do not use OAuth. Instead, they select their company from a dropdown and enter a passcode. Internally, the company name is slugified to form a synthetic Supabase email:
GET /sponsors/names — a public endpoint that requires no auth token.
Full Auth Flow Diagram
Login
Members:
Sponsors:
supabase.auth.signInWithOAuth → OAuth redirect → onAuthStateChange fires.Sponsors:
supabase.auth.signInWithPassword → direct → setSession + setRole.Route access
ProtectedRoute reads session, loading, role from useAuth(). Renders <Outlet /> or redirects.Periodic validation
Every 30 seconds, role is re-validated. Archived users get
authError set; they are shown an error on /auth/Home.