BowlerKit
Features

Authentication

8/20/2026

Secure authentication flows with Login, Register, Social Sign-in, and Session Management.

The Expo boilerplate comes with a fully-featured, production-ready authentication system. It includes secure token persistence, background session validation, protected routing, and support for both email/password and social login.

How it Works

The authentication system is built on four main pillars:

  1. Zustand for global state management.
  2. Expo Secure Store for persistent token storage.
  3. React Query for server state and mutations.
  4. Expo Router for protected navigation and redirects.

1. State Management

Authentication state is managed by the useAuthStore located in store/auth-store.ts. It tracks the current user, the authentication token, and initialization status.

// Example of accessing auth state and actions
import { useAuthStore, useUser, useIsAuthenticated } from '@/store/auth-store';

function ProfileComponent() {
  const user = useUser();
  const isAuthenticated = useIsAuthenticated();
  const clearAuth = useAuthStore(state => state.clearAuth);

  if (!isAuthenticated) return <Text>Please Log In</Text>;

  return (
    <View>
      <Text>Welcome, {user?.name}</Text>
      <Button title="Logout" onPress={clearAuth} />
    </View>
  );
}

2. Token Persistence

We use expo-secure-store to ensure the authentication token is stored safely on the device (Encrypted on iOS and Keystore on Android). The wrapper for this is found in services/storage.ts.

When the app starts, the initialize function in auth-store.ts retrieves the token and attempts to validate it in the background while letting the user access the app immediately for a better UX.

3. API Integration

Every API request made through our custom api service (services/api.ts) automatically injects the Bearer token if it exists.

Additionally, the service includes a global interceptor that handles 401 Unauthorized responses. If a session expires, the app will automatically:

  1. Clear the local auth state and secure storage.
  2. Redirect the user back to the login screen.

4. Initialization & Protected Routes

Routing is handled in app/_layout.tsx. The app uses a "waiting" state during initialization to prevent a "flash" of the login screen for authenticated users.

The layout monitors the isAuthenticated and isAuthInitialized states to decide where to send the user:

  • Authenticated: Redirects to /(tabs).
  • Unauthenticated: Redirects to /(auth)/login.
  • First Time: If onboarding hasn't been completed, redirects to /onboarding.

Features

Email & Password

Full implementation of:

  • Registration: Custom validation and device name tracking.
  • Login: Fast login with session persistence.
  • Password Recovery: Integrated "Forgot Password" and "Reset Password" flows.
  • Email Verification: Support for email verification tokens.

Social Login (Google)

Native Google Sign-in is integrated using @react-native-google-signin/google-signin.

To configure Google login:

  1. Get your Web Client ID from the Google Cloud Console.
  2. Add it to your .env file as EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID.
  3. Add your google-services.json (Android) and GoogleService-Info.plist (iOS) to the mobile-app root.

Mutations

We use custom React Query hooks for auth operations, found in mutations/:

  • useLogin()
  • useRegister()
  • useGoogleLogin()
  • useForgotPassword()
  • useResetPassword()

Example usage of the login mutation:

const loginMutation = useLogin();

const handleLogin = async () => {
  await loginMutation.mutateAsync({
    email,
    password,
    device_name: 'iPhone 15',
  });
  // On success, the store is updated and the user is redirected automatically
};

Security & Account Management

Beyond basic login, the system includes:

  • Authentication Logs: Track login activity and security events.
  • Active Sessions: View and manage active sessions across different devices.
  • Account Deletion: Secure process for users to delete their account and data.
  • Biometric Lock: The boilerplate is prepared for biometric integration (FaceID/Fingerprint).

Directory Structure

  • app/(auth)/: Authentication screens (Login, Register, etc.).
  • app/settings/security/: Security-related screens (Sessions, Auth Logs).
  • store/auth-store.ts: Zustand store for state management.
  • store/security-store.ts: Zustand store for security management.
  • services/api.ts: API client with token injection and 401 handling.
  • services/storage.ts: Secure storage wrapper.
  • mutations/use-login-mutation.ts: React Query mutation for login.
  • queries/use-auth.ts: Queries for fetching the current user.
  • queries/use-security.ts: Queries for fetching security logs and sessions.