Skip to content

4.1 Authentication Fundamentals

Learning Objectives

  • Define authentication vs authorization and their roles in app security
  • Explain token-based authentication and its advantages for mobile apps
  • Describe JSON Web Token (JWT) structure and purpose
  • Identify secure token storage patterns using device-level encryption
  • Diagram authentication flow from login to protected API requests

Authentication (not authentification!) is the process of proving who you are. When you log into an app, you’re authenticating yourself by providing credentials (like email and password) that prove your identity.

These two terms are often confused:

  • Authentication (AuthN)
    • “Who are you?” (proving identity)
    • User logs in with email/password → System verifies credentials → User is authenticated
  • Authorization (AuthZ)
    • “What can you do?” (checking permissions)
    • User tries to delete a post → System checks: Is this user the post owner? → Action allowed or denied

In this chapter, we focus on authentication, getting users logged in and keeping them logged in across app sessions.

Diagram

Modern mobile apps use token-based authentication. Here’s how it works:

  1. User logs in with email and password
  2. Server verifies credentials against database
  3. Server generates an access token (JWT) and a refresh token
  4. App stores tokens securely on device
  5. Every API request includes the access token to prove identity
  6. Token expires after a set time (e.g., 1 hour for access token)
  7. Refresh token is used to get a new access token without re-login

Traditional web apps use session-based authentication with cookies:

  • Server creates a session ID
  • Browser stores session ID in a cookie
  • Cookie sent automatically with every request

Mobile apps use token-based authentication instead because:

  • React Native doesn’t have browser cookies
  • Same tokens work on iOS, Android, and web
  • Server doesn’t need to store session data
  • Tokens can be sent in headers, work with APIs

A JWT (JSON Web Token) is a compact, URL-safe string that represents claims (information) about the user. It’s the most common format for access tokens. 1

A JWT has three parts separated by dots (.):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Breaking it down:

  1. Header (red): Algorithm and token type
  2. Payload (purple): User data and claims
  3. Signature (blue): Cryptographic verification
Diagram

The payload contains claims — pieces of information about the user:

{
"sub": "user-123", // Subject (user ID)
"email": "alice@example.com", // User email
"iat": 1678900000, // Issued at (timestamp)
"exp": 1678903600 // Expires at (timestamp)
}

When your app sends a JWT to the server:

  1. Server splits JWT into header, payload, signature
  2. Server re-creates the signature using the secret key
  3. Server compares: does the signature match?
  4. If yes → token is valid and hasn’t been tampered with
  5. If no → token is invalid, request denied

This is how the server knows the token is authentic without storing anything in a database.

Expo Router makes it easy to separate public screens (login, register) from protected screens (home, profile) using protected routes. 2

  • Directoryapp/
    • _layout.tsx
    • index.tsx
    • about.tsx
    • login.tsx Should only be available while not authenticated
    • Directoryprivate/
      • _layout.tsx Should only be available while authenticated
      • index.tsx
      • page.tsx
import { Stack } from 'expo-router';
const isLoggedIn = false;
export function AppLayout() {
return (
<Stack>
<Stack.Protected guard={!isLoggedIn}>
<Stack.Screen name="login" />
</Stack.Protected>
<Stack.Protected guard={isLoggedIn}>
<Stack.Screen name="private" />
</Stack.Protected>
{/* Expo Router includes all routes by default. Adding Stack.Protected creates exceptions for these screens. */}
</Stack>
);
}
Diagram

When a guard fails, the screen becomes inaccessible and the user is redirected to the first available screen.

You’ll use React Context to share auth state across the entire app. This is a simplified example and you’ll learn how to implement this for real in the next chapter.

contexts/AuthContext.tsx
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const [isLoading, setIsLoading] = useState(true);
// Check for existing session on mount
useEffect(() => {
checkSession();
}, []);
return (
<AuthContext.Provider value={{ user, isLoading }}>
{children}
</AuthContext.Provider>
);
}
// Use anywhere in the app
const { user, isLoading } = useAuth();

This will allow any component to access the current user without prop drilling.

Authentication in mobile apps involves:

  • Token-based auth: Using JWTs instead of sessions/cookies
  • Auth flow: Separating public and protected screens with Expo Router
  • Context: Sharing auth state across the app with React Context
  • Automatic refresh: Keeping users logged in without manual re-authentication

In the next chapter, you’ll implement all of this with Supabase to create a real authentication system for your app.

  1. JWT.io Introduction

  2. Expo Protected Routes