Overview
The authentication system handles user sessions, role-based access control, and guest sessions across both mobile and web platforms.
Mobile Authentication Flow
The mobile app implements a role-based authentication system with support for admin, employee (empleado), and guest users.
Session Check
On app launch, the system checks for existing sessions and routes users accordingly.
const bootstrap = async () => {
const { data } = await supabase.auth.getSession();
if (data.session) {
const { data: profile } = await supabase
.from("profiles")
.select("role")
.eq("id", data.session.user.id)
.single();
if (profile?.role === "admin") {
router.replace("/(admin)");
return;
}
if (profile?.role === "empleado") {
router.replace("/(empleado)");
return;
}
await supabase.auth.signOut();
router.replace("/(auth)/login");
return;
}
const guestSession = await SecureStore.getItemAsync("guest_session");
if (guestSession) {
router.replace("/(guest)/home");
return;
}
router.replace("/(auth)/login");
};
Authentication Methods
Get Current Session
const { data, error } = await supabase.auth.getSession();
if (data.session) {
console.log('User ID:', data.session.user.id);
console.log('Email:', data.session.user.email);
}
Refresh token for session renewal
Sign In
const { data, error } = await supabase.auth.signInWithPassword({
email: '[email protected]',
password: 'password123'
});
Sign Out
await supabase.auth.signOut();
router.replace("/(auth)/login");
Role-Based Access Control
The app supports three user roles:
Administrator role with full system access. Routes to /(admin) layout.
Employee role with limited access. Routes to /(empleado) layout.
Guest role for unauthenticated browsing. Uses SecureStore for session management instead of Supabase auth.
Guest Sessions
Guest sessions are managed using Expo SecureStore:
// Check for guest session
const guestSession = await SecureStore.getItemAsync("guest_session");
if (guestSession) {
router.replace("/(guest)/home");
}
// Create guest session
await SecureStore.setItemAsync("guest_session", "true");
// Clear guest session
await SecureStore.deleteItemAsync("guest_session");
Web Authentication Flow
The web application uses Next.js middleware for lightweight authentication checks.
Middleware Authentication
The middleware checks for Supabase authentication cookies before allowing access to protected routes.
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
if (pathname.startsWith("/dashboard")) {
// Supabase persists the session in a cookie named "sb-<project>-auth-token"
const hasSession = Array.from(request.cookies.getAll()).some(
(c) => c.name.startsWith("sb-") && c.name.endsWith("-auth-token")
);
if (!hasSession) {
return NextResponse.redirect(new URL("/", request.url));
}
}
return NextResponse.next();
}
export const config = {
matcher: ["/dashboard/:path*"],
};
Array of route patterns to apply middleware to. Protects all /dashboard routes and sub-routes.
Cookie-Based Authentication
Supabase authentication tokens are stored in cookies with the naming pattern:
sb-<project-ref>-auth-token
Cookie name following pattern sb-<project>-auth-token
Encrypted authentication token
Cookie is not accessible via JavaScript
Cookie only sent over HTTPS
Server-Side Authentication
Full role validation happens server-side in protected pages:
import { createClient } from '@/lib/supabase-server'
export default async function DashboardPage() {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) {
redirect('/');
}
const { data: profile } = await supabase
.from('profiles')
.select('role')
.eq('id', user.id)
.single();
// Validate role and render accordingly
}
Profile Schema
User profiles are stored in the profiles table:
interface Profile {
id: string; // Matches auth.users.id
role: 'admin' | 'empleado'; // User role
created_at: string; // ISO timestamp
updated_at: string; // ISO timestamp
}
Best Practices
Mobile
- Always check for valid sessions on app launch
- Validate user roles before routing
- Sign out users with invalid or missing roles
- Use SecureStore for guest session management
- Clear guest sessions when users sign in
Web
- Use middleware for initial authentication checks
- Perform full role validation server-side
- Read user data from cookies in server components
- Redirect unauthenticated users to login page
- Never trust client-side authentication alone
Error Handling
// Mobile authentication with error handling
try {
const { data, error } = await supabase.auth.getSession();
if (error) {
console.error('Session error:', error);
router.replace('/(auth)/login');
return;
}
if (!data.session) {
router.replace('/(auth)/login');
return;
}
// Proceed with authenticated flow
} catch (err) {
console.error('Authentication failed:', err);
router.replace('/(auth)/login');
}