paint-brush
Setting Up Auth0 Authentication with Expo Router: A Complete Guideby@alabomarine
New Story

Setting Up Auth0 Authentication with Expo Router: A Complete Guide

by Alabo Briggs
Alabo Briggs HackerNoon profile picture

Alabo Briggs

@alabomarine

senior software engineer and seasonal founder

March 16th, 2025
Read on Terminal Reader
Read this story in a terminal
Print this story
Read this story w/o Javascript
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Implementing a robust authentication system is crucial for mobile applications. In this guide, I'll walk you through setting up Auth0 authentication with Expo Router. I decided to write this article because I there was no feasible guide on how to do this.

Companies Mentioned

Mention Thumbnail
Before
Mention Thumbnail
Flow
featured image - Setting Up Auth0 Authentication with Expo Router: A Complete Guide
1x
Read by Dr. One voice-avatar

Listen to this story

Alabo Briggs HackerNoon profile picture
Alabo Briggs

Alabo Briggs

@alabomarine

senior software engineer and seasonal founder

Learn More
LEARN MORE ABOUT @ALABOMARINE'S
EXPERTISE AND PLACE ON THE INTERNET.
0-item
1-item
2-item

STORY’S CREDIBILITY

Guide

Guide

Walkthroughs, tutorials, guides, and tips. This story will teach you how to do something new or how to do something better.

DYOR

DYOR

The writer is smart, but don't just like, take their word for it. #DoYourOwnResearch before making any investment decisions or decisions regarding your health or security. (Do not regard any of this content as professional investment advice, or health advice)

Code License

Code License

The code in this story is for educational purposes. The readers are solely responsible for whatever they build with it.

Implementing a robust authentication system is crucial for mobile applications. In this guide, I'll walk you through setting up Auth0 authentication with Expo Router, creating a seamless and secure user experience.


Prerequisites

Before starting, ensure you have:

  • An Expo project using Expo Router
  • An Auth0 account with a configured application
  • Basic understanding of React Native and TypeScript

Step 1: Install Required Dependencies

First, install the Auth0 React Native SDK:

yarn add react-native-auth0


Step 2: Configure Auth0

Create an auth0.config.js file in your project root:

const config = {
  clientId: "YOUR_AUTH0_CLIENT_ID",
  domain: "YOUR_AUTH0_DOMAIN",
}

export default config

Replace the placeholders with your actual Auth0 credentials.


Step 3: Create an Authentication Context

The authentication context will manage the auth state throughout your app. Create a file called useAuth.tsx in your hooks directory:

import { createContext, useContext, useEffect, useState } from "react"
import { useAuth0 } from "react-native-auth0"
import { router, useSegments, useRootNavigationState } from "expo-router"

// Define the shape of our auth context
type AuthContextType = {
  signIn: () => Promise<void>
  signOut: () => Promise<void>
  isAuthenticated: boolean
  isLoading: boolean
  user: any
  error: Error | null
}

// Create the context with a default value
const AuthContext = createContext<AuthContextType | null>(null)

// Provider component that wraps the app
export function AuthProvider({ children }: { children: React.ReactNode }) {
  const { authorize, clearSession, user, error, getCredentials, isLoading } =
    useAuth0()
  const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false)
  
  const segments = useSegments()
  const navigationState = useRootNavigationState()

  // Check if the user is authenticated and redirect accordingly
  useEffect(() => {
    if (!navigationState?.key) return
    
    const inAuthGroup = segments[0] === "(auth)"
    
    if (isAuthenticated && inAuthGroup) {
      // Redirect authenticated users from auth screens to the main app
      router.replace("/(tabs)")
    } else if (!isAuthenticated && !inAuthGroup) {
      // Redirect unauthenticated users to the login screen
      router.replace("/(auth)/login")
    }
  }, [isAuthenticated, segments, navigationState?.key])

  // Update authentication state when user changes
  useEffect(() => {
    setIsAuthenticated(!!user)
  }, [user])

  // Sign in function
  const signIn = async () => {
    try {
      await authorize()
      const credentials = await getCredentials()
      console.log("Auth credentials:", credentials)
      setIsAuthenticated(true)
    } catch (e) {
      console.error("Login error:", e)
    }
  }

  // Sign out function
  const signOut = async () => {
    try {
      await clearSession()
      setIsAuthenticated(false)
    } catch (e) {
      console.error("Logout error:", e)
    }
  }

  return (
    <AuthContext.Provider
      value={{
        signIn,
        signOut,
        isAuthenticated,
        isLoading,
        user,
        error,
      }}
    >
      {children}
    </AuthContext.Provider>
  )
}

// Custom hook to use the auth context
export function useAuth() {
  const context = useContext(AuthContext)
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider")
  }
  return context
}

This context provides:

  • Authentication state management
  • Sign-in and sign-out functions
  • Automatic redirection based on authentication status
  • Access to user information and error states


Step 4: Set Up the Root Layout

Update your app/_layout.tsx file to include the Auth0Provider and AuthProvider:

import { Auth0Provider } from "react-native-auth0"
import config from "@/auth0.config"
import { AuthProvider } from "@/hooks/useAuth"
// Other imports...

export default function RootLayout() {
  // Other code...

  return (
    <Auth0Provider domain={config.domain} clientId={config.clientId}>
      <AuthProvider>
        <ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
          <Stack>
            <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
            <Stack.Screen name="(auth)" options={{ headerShown: false }} />
            <Stack.Screen name="+not-found" />
          </Stack>
          <StatusBar style={colorScheme === "dark" ? "light" : "dark"} />
        </ThemeProvider>
      </AuthProvider>
    </Auth0Provider>
  )
}


Step 5: Create the Authentication Group

Expo Router uses directory-based routing. Create an (auth) directory in your app folder with a layout file:

// app/(auth)/_layout.tsx
import { Stack } from "expo-router"

export default function AuthLayout() {
  return (
    <Stack screenOptions={{ headerShown: false }}>
      <Stack.Screen name="login" />
    </Stack>
  )
}


Step 6: Create the Login Screen

Create a login screen in app/(auth)/login.tsx:

import { ThemedText } from "@/components/ThemedText"
import { useAuth } from "@/hooks/useAuth"
import {
  StyleSheet,
  View,
  TouchableOpacity,
  ActivityIndicator,
} from "react-native"

export default function LoginScreen() {
  const { signIn, isLoading, error } = useAuth()

  return (
    <View style={styles.container}>
      <View style={styles.content}>
        <ThemedText style={styles.title}>Welcome to Your App</ThemedText>
        <ThemedText style={styles.subtitle}>Sign in to continue</ThemedText>

        <TouchableOpacity
          style={styles.button}
          onPress={signIn}
          disabled={isLoading}
        >
          {isLoading ? (
            <ActivityIndicator color="#fff" />
          ) : (
            <ThemedText style={styles.buttonText}>Sign In</ThemedText>
          )}
        </TouchableOpacity>

        {error && (
          <ThemedText style={styles.errorText}>{error.message}</ThemedText>
        )}
      </View>
    </View>
  )
}

// Styles...


Step 7: Create a Profile Screen

Add a profile screen to display user information and provide a logout option:

// app/(tabs)/profile.tsx
import { ThemedText } from "@/components/ThemedText"
import { useAuth } from "@/hooks/useAuth"
import {
  StyleSheet,
  View,
  TouchableOpacity,
  Image,
  ScrollView,
} from "react-native"

export default function ProfileScreen() {
  const { user, signOut, isLoading } = useAuth()

  return (
    <ScrollView style={styles.container}>
      <View style={styles.header}>
        {user?.picture ? (
          <Image source={{ uri: user.picture }} style={styles.avatar} />
        ) : (
          <View style={styles.avatarPlaceholder}>
            <ThemedText style={styles.avatarText}>
              {user?.name?.charAt(0) || user?.email?.charAt(0) || "?"}
            </ThemedText>
          </View>
        )}

        <ThemedText style={styles.name}>{user?.name || "User"}</ThemedText>
        <ThemedText style={styles.email}>{user?.email || ""}</ThemedText>
      </View>

      {/* User information display */}
      
      <View style={styles.actions}>
        <TouchableOpacity
          style={styles.logoutButton}
          onPress={signOut}
          disabled={isLoading}
        >
          <ThemedText style={styles.logoutText}>Sign Out</ThemedText>
        </TouchableOpacity>
      </View>
    </ScrollView>
  )
}

// Styles...


Step 8: Update the Tabs Layout

Ensure your tabs layout includes the profile tab and checks authentication:

// app/(tabs)/_layout.tsx
import { useAuth } from "@/hooks/useAuth"
// Other imports...

export default function TabLayout() {
  const { isAuthenticated } = useAuth()

  // Redirect to login if not authenticated
  React.useEffect(() => {
    if (!isAuthenticated) {
      // The AuthProvider will handle the redirect
    }
  }, [isAuthenticated])

  return (
    <Tabs
      screenOptions={{
        // Tab options...
      }}
    >
      {/* Other tabs */}
      <Tabs.Screen
        name="profile"
        options={{
          title: "Profile",
          tabBarIcon: ({ color }) => (
            <IconSymbol size={28} name="person.fill" color={color} />
          ),
        }}
      />
    </Tabs>
  )
}


Step 9: Create a Root Redirect

Finally, create a root index file to handle initial routing:

// app/index.tsx
import { Redirect } from "expo-router"
import { useAuth } from "@/hooks/useAuth"

export default function Index() {
  const { isAuthenticated, isLoading } = useAuth()
  
  // While checking authentication status, don't redirect yet
  if (isLoading) {
    return null
  }
  
  // Redirect based on authentication status
  return isAuthenticated ? (
    <Redirect href="/(tabs)" />
  ) : (
    <Redirect href="/(auth)/login" />
  )
}


How It Works

  1. Initial Load: When the app starts, it checks the authentication status.
  2. Authentication Flow:
    • Unauthenticated users are directed to the login screen
    • After successful login, users are redirected to the main app
    • The profile screen displays user information and provides logout functionality
  3. Protected Routes: The AuthProvider automatically protects routes by redirecting unauthenticated users to the login screen.


Benefits of This Approach

  • Clean Separation: Authentication logic is isolated in a dedicated context
  • Route Protection: Automatic redirection based on authentication status
  • Reusable Authentication: The useAuth hook can be used throughout the app
  • Seamless UX: Users are directed to the appropriate screens based on their authentication status


Conclusion

Setting up Auth0 with Expo Router provides a robust authentication system for your mobile application. This approach leverages Expo Router's group-based routing to create a clean separation between authenticated and unauthenticated content, while the authentication context manages the state and provides a consistent interface for authentication operations.

By following this guide, you've implemented a complete authentication flow that handles login, logout, and protected routes in a maintainable and scalable way.

L O A D I N G
. . . comments & more!

About Author

Alabo Briggs HackerNoon profile picture
Alabo Briggs@alabomarine
senior software engineer and seasonal founder

TOPICS

THIS ARTICLE WAS FEATURED IN...

Arweave
Read on Terminal Reader
Read this story in a terminal
 Terminal
Read this story w/o Javascript
Read this story w/o Javascript
 Lite
Hackernoon
X
Threads
Bsky

Mentioned in this story

companies
X REMOVE AD