Skip to content

feat: add route guard functionality for access control#557

Open
ice-rider wants to merge 2 commits intosolidjs:mainfrom
ice-rider:main
Open

feat: add route guard functionality for access control#557
ice-rider wants to merge 2 commits intosolidjs:mainfrom
ice-rider:main

Conversation

@ice-rider
Copy link

This PR introduces route guards to the Solid Router, allowing developers to control access to routes based on custom conditions such as authentication, authorization, feature flags, or any asynchronous logic. It provides a familiar API similar to other popular routers while staying true to Solid's reactive and performant principles.

Motivation

Many applications require protecting certain routes from unauthorized access or redirecting users based on their state. Previously, this had to be implemented manually inside route components or with wrapper components, leading to boilerplate and inconsistent behavior. By integrating guards directly into the router, we enable a declarative and centralized way to manage route protection.

Key Features

  • Guard per route: Add a guard prop to route definitions (both in <Route> component and route objects) that accepts a boolean, a synchronous function, or an asynchronous function returning a RouteGuardResult.
  • Flexible return types: Guards can return true (allow), false (deny, staying on current route), or a string (redirect path). Also supports { allowed: boolean; redirect?: string } for more complex cases.
  • Automatic redirect handling: When a guard returns a redirect path, the router automatically navigates to that path with replace: true (avoiding history stack pollution).
  • Preload integration: During route preloading, guards are evaluated (synchronously when possible) to avoid preloading protected routes unnecessarily.
  • Hook for component-level access: New useRouteGuard hook allows components to reactively access guard status and pending state.
  • Utility functions: Exported evaluateRouteGuard and normalizeGuardResult for custom implementations.

Implementation Details

  • Added guard field to RouteDefinition and RouteDescription types.
  • Extended RouterContext with checkRouteGuard method that iterates through route matches (from root to leaf) and stops at the first failing guard.
  • Integrated guard checks into the route matching flow in components.tsx to conditionally render route content.
  • Modified preload logic in routing.ts to respect guards.

Example Usage

import { Router, Route } from "@solidjs/router";

const authGuard = ({ location, intent }) => {
  const isAuthenticated = checkAuth(); // some reactive check
  if (!isAuthenticated) {
    return "/login"; // redirect to login
  }
  return true;
};

const adminGuard = async ({ params }) => {
  const user = await fetchCurrentUser();
  return user.role === "admin" ? true : "/unauthorized";
};

function App() {
  return (
    <Router>
      <Route path="/" component={Home} />
      <Route path="/dashboard" component={Dashboard} guard={authGuard} />
      <Route path="/admin" component={AdminPanel} guard={adminGuard} />
      <Route path="/login" component={Login} />
      <Route path="/unauthorized" component={Unauthorized} />
    </Router>
  );
}

Testing

  • Unit tests for evaluateRouteGuard and normalizeGuardResult.
  • Integration tests for navigation with guards (sync/async, redirects).
  • Tests for preload behavior with guarded routes.
  • Manual testing in a sample app with different guard scenarios.

Potential Impact

This change is backward-compatible: existing routes without a guard prop behave exactly as before. No breaking changes are introduced.


Let me know if any adjustments are needed. Thank you for considering this contribution!

Implements route guards to control navigation access based on custom conditions, similar to other popular routers. Guards can be defined per route and support both synchronous and asynchronous checks with redirect capabilities.

- Add `guard` prop to RouteDefinition and Route components accepting boolean or async function
- Implement `checkRouteGuard` in router context to evaluate all guards in a match chain
- Create `useRouteGuard` hook for component-level guard access with pending state
- Export `evaluateRouteGuard` and `normalizeGuardResult` utilities for custom implementations
- Integrate guard checks with route matching to prevent rendering unauthorized routes
- Add guard evaluation during preload to skip loading protected routes
- Support redirect responses by automatically navigating when guard returns a string path

This maintains Solid's reactive patterns while providing familiar protection mechanisms for
authentication flows, feature flags, and role-based access control.
@changeset-bot
Copy link

changeset-bot bot commented Mar 7, 2026

🦋 Changeset detected

Latest commit: 0cc6e4c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@solidjs/router Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant