This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
Authentication in Expo Router using redirects
Edit page
How to implement authentication and protect routes with Expo Router.
SDK 53 introduced Protected routes, a more powerful method of handling authentication. Please follow this guide if you are using SDK 52 and earlier.

Learn how to implement an auth flow in your Expo Router project.
With Expo Router, all routes are always defined and accessible. You can use runtime logic to redirect users away from specific screens depending on whether they are authenticated. There are two different techniques for authenticating users within routes. This guide provides an example that demonstrates the functionality of standard native apps.
Using React Context and Route Groups
It's common to restrict specific routes to users who are not authenticated. This is achievable in an organized way by using React Context and Route Groups. Consider the following project structure that has a /sign-in route that is always accessible and a (app) group that requires authentication:
app_layout.tsxsign-in.tsxAlways accessible (app)_layout.tsxProtects child routesindex.tsxRequires authorization 1
To follow the above example, set up a React Context provider that can expose an authentication session to the entire app. You can implement your custom authentication session provider or use the one from the Example authentication context below.
Example authentication context
This provider uses a mock implementation. You can replace it with your own authentication provider.
The following code snippet is a basic hook that persists tokens securely on native with expo-secure-store and in local storage on web.
2
Use the SessionProvider in the root layout to provide the authentication context to the entire app. It's imperative that the <Slot /> is mounted before any navigation events are triggered. Otherwise, a runtime error will be thrown.
3
Create a nested layout route that checks whether users are authenticated before rendering the child route components. This layout route redirects users to the sign-in screen if they are not authenticated.
4
Create the /sign-in screen. It can toggle the authentication using signIn(). Since this screen is outside the (app) group, the group's layout and authentication check do not run when rendering this screen. This lets logged-out users see this screen.
5
Implement an authenticated screen that lets users sign out.
You now have an app that can present a loading state while it checks the initial authentication state and redirects to the sign-in screen if the user is not authenticated. If a user visits a deep link to any routes with the authentication check, they'll be redirected to the sign-in screen.
Alternative loading states
With Expo Router, something must be rendered to the screen while loading the initial auth state. In the example above, the app layout renders a loading message. Alternatively, you can make the index route a loading state and move the initial route to something such as /home, which is similar to how X works.
Modals and per-route authentication
Another common pattern is to render a sign-in modal over the top of the app. This enables you to dismiss and partially preserve deep links when the authentication is complete. However, this pattern requires routes to be rendered in the background as these routes require handling data loading without authentication.
app_layout.tsxDeclares global session context(app)_layout.tsxsign-in.tsxModal presented over the root(root)_layout.tsxProtects child routesindex.tsxRequires authorization Navigating without navigation
You may encounter the following error when the app attempts to perform navigation without a navigator mounted in the root layout.
Error: Attempted to navigate before mounting the Root Layout component. Ensure the Root Layout component is rendering a Slot, or other navigator on the first render.
To fix this, add a group and move conditional logic down a level.
Before
app_layout.tsxabout.tsxAfter
app_layout.tsx(app)_layout.tsxMove conditional logic down a levelabout.tsxMiddleware
Traditionally, websites may leverage some form of server-side redirection to protect routes. Expo Router on the web currently only supports build-time static generation and has no support for custom middleware or serving. This can be added in the future to provide a more optimal web experience. In the meantime, authentication can be implemented by using client-side redirects and a loading state.