Mobile

Authenticated navigation in React Native: routes, roles and session state

Protected routes are part of app architecture. Define session states, profile rules and fallback screens before the navigation tree becomes hard to reason about.

Reading guide

What this article covers

Use this as a navigation checklist before adding more modules to a React Native app with login, profiles and role-based access.

  1. 011. Navigation is part of authorization
  2. 022. Model session states before implementing screens
  3. 033. Roles and profiles need a single source of truth
  4. 044. Protected routes should fail safely
  5. 055. Token refresh changes navigation behavior
  6. 066. Deep links and push notifications must respect session state
  7. 077. Implementation checklist

Login is often treated as the first screen of a mobile app. In practice, it is the entrance to a session model. Once the app has roles, protected modules, push notifications, token refresh and deep links, navigation becomes part of system behavior.

The goal is not to make navigation complex. The goal is to name the states that already exist so the app can handle them consistently.

In a corporate React Native app, navigation is not only a UI concern. It decides which screens are visible, which actions are possible and how the user moves after login, logout, token refresh or profile changes.

If the team treats navigation as a set of isolated buttons, the app starts to leak complexity. Screens appear for the wrong profile, back navigation returns to protected places and session expiration becomes a surprise in the middle of a flow.

  • Define public, authenticated and role-specific route groups.
  • Decide what happens when a user loses access while the app is open.
  • Avoid hiding authorization decisions only inside individual screens.
  • Keep navigation behavior aligned with backend permissions.

2. Model session states before implementing screens

A stable app usually has more than two states. It is not only logged in or logged out. There is loading the stored session, refreshing token, authenticated, unauthenticated, forbidden, onboarding required and sometimes app update required.

When those states are explicit, the app can show predictable fallback screens. When they are implicit, every screen starts checking tokens and the same bug appears in different places.

  • Bootstrapping: the app is checking local session data.
  • Anonymous: the user can only access public screens.
  • Authenticated: the user has a valid session and profile.
  • Refreshing: requests are waiting for a session recovery attempt.
  • Forbidden: the session exists, but the profile cannot access the route.
  • Expired: the session cannot be recovered and the user must log in again.

3. Roles and profiles need a single source of truth

Role-based navigation becomes fragile when the app invents rules that the backend does not know. The safest approach is to expose a current user endpoint that returns the profile, permissions and feature availability needed by the mobile shell.

The mobile app should not need to guess whether a user can open a module. It should receive stable permission signals and use them to build the navigation tree, show empty states or redirect to a safe screen.

  • Expose a current user endpoint with roles and feature flags.
  • Prefer permission codes over hardcoded profile names in the app.
  • Handle missing permission with a useful screen, not only a silent redirect.
  • Keep server-side authorization even if the app hides a route.
{
  "id": "u_123",
  "name": "Maria",
  "roles": ["MANAGER"],
  "permissions": ["tasks.read", "tasks.approve"],
  "features": { "offlineTasks": true, "reports": false }
}

4. Protected routes should fail safely

A protected route must know how to behave while the session is loading, when the user is authenticated, when permission is missing and when the session is no longer valid. This logic should be centralized enough to avoid repeated checks in every screen.

Failing safely means the app does not flash protected content, does not keep stale screens after logout and does not send the user into a navigation loop.

  • Show a loading boundary while the session is being restored.
  • Redirect unauthenticated users to login with clear context.
  • Use a forbidden screen when the user is logged in but lacks permission.
  • Clear sensitive navigation history after logout.
  • Avoid nested navigators with inconsistent session assumptions.

5. Token refresh changes navigation behavior

Token refresh is not only an HTTP interceptor. It affects what the user sees. If refresh succeeds, the app should continue with minimal friction. If refresh fails, the app must stop protected actions and guide the user back to authentication.

The dangerous scenario is a half-authenticated app: some requests use an old token, one screen thinks the user is logged in and another screen already redirected to login. A shared session controller reduces this mismatch.

  • Queue or pause protected requests while refresh is running.
  • Refresh only once when multiple requests fail together.
  • Return to the intended screen only when the session is safely recovered.
  • Make refresh failure visible to navigation and cache layers.
  • Avoid infinite refresh loops.

Deep links and push notifications are common sources of broken navigation. A notification may point to a task detail while the user is logged out, using another profile or running an old app version.

The app should treat external entry points as intents. First validate session, then validate permission, then validate whether the target still exists. Only after that should it navigate to the final screen.

  • Store the intended destination while authentication is resolved.
  • Validate role and resource access before opening the detail screen.
  • Handle deleted or unavailable resources with a friendly fallback.
  • Include app version compatibility in push/deep link decisions.
  • Log safe evidence when an external entry point fails.

7. Implementation checklist

The best time to organize navigation is before the app has many screens. The second-best time is before adding the next sensitive module. A small navigation contract can prevent weeks of profile-related regressions.

Keep the checklist close to the app repository and review it when permissions, roles, modules or authentication rules change.

  • List public, authenticated and role-specific routes.
  • Define the session state machine.
  • Implement a current user endpoint contract.
  • Centralize protected route behavior.
  • Define forbidden, expired and loading states.
  • Test logout, token expiration and profile changes.
  • Validate deep links and push notifications through the same rules.
FAQ

Questions that usually appear when roles enter the app.

Should route protection live only in the backend?

No. The backend must enforce authorization, but the app also needs route protection to avoid confusing screens and to guide users before a forbidden request happens.

Should the app store roles locally?

The app can cache the current user profile for experience, but it should refresh it when the session starts and after relevant profile changes. The backend remains the source of truth.

What should happen after logout?

The app should clear sensitive local data, reset protected navigation history and return to a public route such as login or a welcome screen.

WhatsApp(12) 98855-9188