1---
2title: Authentication in Expo Router
3sidebar_title: Authentication
4description: How to protect routes with Expo Router.
5hideTOC: true
6---
7
8import { FileTree } from '~/ui/components/FileTree';
9
10It's common to restrict certain routes to users who are not authenticated. This can be achieved in a very organized way by using React Context and Route Groups.
11
12Consider the following project:
13
14<FileTree files={['app/_layout.js', 'app/index.js', 'app/(auth)/sign-in.js']} />
15
16First, we'll setup a [React Context provider](https://react.dev/reference/react/createContext) that we can use to protect routes. This provider will use a mock implementation, you can replace it with your own [authentication provider](/guides/authentication/).
17
18```jsx context/auth.js
19import { router, useSegments } from 'expo-router';
20import React from 'react';
21
22const AuthContext = React.createContext(null);
23
24// This hook can be used to access the user info.
25export function useAuth() {
26  return React.useContext(AuthContext);
27}
28
29// This hook will protect the route access based on user authentication.
30function useProtectedRoute(user) {
31  const segments = useSegments();
32
33  React.useEffect(() => {
34    const inAuthGroup = segments[0] === '(auth)';
35
36    if (
37      // If the user is not signed in and the initial segment is not anything in the auth group.
38      !user &&
39      !inAuthGroup
40    ) {
41      // Redirect to the sign-in page.
42      router.replace('/sign-in');
43    } else if (user && inAuthGroup) {
44      // Redirect away from the sign-in page.
45      router.replace('/');
46    }
47  }, [user, segments]);
48}
49
50export function Provider(props) {
51  const [user, setAuth] = React.useState(null);
52
53  useProtectedRoute(user);
54
55  return (
56    <AuthContext.Provider
57      value={{
58        signIn: () => setAuth({}),
59        signOut: () => setAuth(null),
60        user,
61      }}>
62      {props.children}
63    </AuthContext.Provider>
64  );
65}
66```
67
68Now we can use this context to control the access to the routes, we'll do this by using a Layout Route that wraps all the screens which require authentication.
69
70```jsx app/_layout.js
71import { Slot } from 'expo-router';
72import { Provider } from '../context/auth';
73
74export default function Root() {
75  return (
76    // Setup the auth context and render our layout inside of it.
77    <Provider>
78      <Slot />
79    </Provider>
80  );
81}
82```
83
84Now we can create our `(auth)` group which is unprotected, this screen can toggle the authentication using `signIn()`.
85
86```jsx app/(auth)/sign-in.js
87import { Text, View } from 'react-native';
88import { useAuth } from '../../context/auth';
89
90export default function SignIn() {
91  const { signIn } = useAuth();
92  return (
93    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
94      <Text onPress={() => signIn()}>Sign In</Text>
95    </View>
96  );
97}
98```
99
100And finally we'll implement an authenticated screen which can sign out.
101
102```jsx app/index.js
103import { Text, View } from 'react-native';
104
105import { useAuth } from '../context/auth';
106
107export default function Index() {
108  const { signOut } = useAuth();
109  return (
110    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
111      <Text onPress={() => signOut()}>Sign Out</Text>
112    </View>
113  );
114}
115```
116
117Now if the authentication state changes globally, the user will be redirected to the appropriate route.
118
119{/* TODO: Guide on using redirects and per-screen behavior */}
120