schultek / jaspr

Modern web framework for building websites in Dart. Supports SPAs and SSR.
https://jasprpad.schultek.de
MIT License
996 stars 59 forks source link

feat: Implementation of Route Guards #201

Closed carmas123 closed 3 weeks ago

carmas123 commented 3 months ago

I am proposing the addition of route guards to the Jaspr framework, a feature that seems to be missing or is not clearly documented in the current version. Route guards are essential for a modern web application, allowing developers to set conditions that must be met before a route can be activated or navigated to. This feature is particularly useful for checking authentication status, permissions, and other prerequisites before rendering a component or page.

Use Case: A common scenario where route guards are invaluable is in handling user authentication. For example, certain parts of an application should only be accessible to authenticated users. Without a route guard, developers have to implement manual checks within each component or page, leading to repetitive code and potential security loopholes.

Suggested Implementation: Route guards in Jaspr could be implemented as functions or objects that can be associated with routes. These guards should be able to:

Example:

GuardedRoute(
  path: '/dashboard',
  guard: checkAuthentication,
  component: DashboardComponent,
  onRedirect: '/login',
)

Future<bool> checkAuthentication(RouteContext context) async {
  // Assume authService can asynchronously check if a user is logged in
  return await authService.isLoggedIn();
}

Benefits:

Conclusion: Integrating route guards into Jaspr could significantly enhance the framework's capabilities, making it more secure and convenient for both developers and users. This feature would align Jaspr with modern web development practices, where security and user experience are paramount.


This feature request should provide a clear overview of what you're looking for and how it can benefit the Jaspr project. Adjust the technical details as necessary to fit your specific requirements or the project's context.

walsha2 commented 3 months ago

I am proposing the addition of route guards to the Jaspr framework

One place that has done this really well IMO is the autoroute package, where you can pass in a List of guard functions that are evaluated. Here are the docs:

https://autoroute.vercel.app/advanced/route_guards

In jaspr it may look something like this and not disrupt the existing API:

Route(
  path: '/home',
  name: 'home',
  guards: [checkAuth,checkSomethingElse]
  builder: (context, state) => HomeScreen(),
)

Without a route guard, developers have to implement manual checks within each component or page...

@carmas123 Not quite. A way to get around this right now is to use jaspr_router in conjunction with some sort of shared state service, like jaspr_riverpod, and listen for auth changes. You can then use the redirect callback to perform your route guard logic. Something like this:

final routerProvider = Provider<Router>(
  ((ref) {
    final isAuthenticated = ref.watch(authProvider).status;
    return Router(
      routes: [],
      redirect: (context, state) {
        if (!isAuthenticated) {
          return '/auth/login';
        }
        return null;
      },
    );
  }),
);

I have implemented something similar to this and it works well.

schultek commented 3 months ago

There is a redirect property on each Route that is intended for these cases. Does that work for you or are you looking for something different?

carmas123 commented 3 months ago

When I use redirect I got always an exception. Server mode doesn't support routing.

schultek commented 3 months ago

It should, can you open a bug ticket then

schultek commented 1 month ago

@carmas123 Can you re-evaluate if Route redirects fit your use-case now that the bug is fixed?

carmas123 commented 1 month ago

Hi @schultek, unfortunately, I haven't had much time to check. I will update to the latest version of Jaspr and run some tests.

However, I believe that having something "dedicated" to managing authorizations in the context of routing would be preferable. Not that it can't be done with redirect, but it might simply be more intuitive for future developments.

schultek commented 1 month ago

This is just a matter of api design, not functionality.

These guards should be able to:

  • Asynchronously evaluate conditions (e.g., check if a user is logged in).
  • Redirect users to alternative routes based on the evaluation (e.g., redirecting unauthenticated users to a login page).
  • Have access to route parameters and the current application state to make dynamic decisions.

Redirects fit this 100%. Its kinda just a different naming.

carmas123 commented 1 month ago

Ok, as you prefer.