vike icon indicating copy to clipboard operation
vike copied to clipboard

Client-only guard() hook

Open tszyan opened this issue 1 year ago • 5 comments

Description

It appears that the guard() hook is not functioning correctly when used with the following configuration:

  meta: {
    guard: {
      env: {
        server: false,
        client: true,
      }
    }
  }

No additional logic is implemented within the guard, just:

throw render(404);

Upon the initial page load or reloading with F5, the page loads without the guard hook being triggered.

It's the same behavior observed with Solid and React batijs scaffolds.

tszyan avatar Apr 05 '24 12:04 tszyan

What is it you're trying to achieve?

It isn't clear to me what should happen with that configuration. Because the main purpose of the guard() hook is to protect unauthorized access, e.g. to protect an admin page from regular users. Given such use case calling guard() only the server-side is potentially a safety hazard, but maybe that's something we can warn the user about.

Closing but let's continue the conversation and let's see if the guard() can be improved.

brillout avatar Apr 06 '24 08:04 brillout

In my case, guard() is necessary to display the authentication page if the user is not authenticated (no token or it has expired).

Utilized:

  • REST API (server-side not in JavaScript)
  • Authentication using access and refresh tokens.

No server-side JavaScript logic for data retrieval, checks, etc. is planned.

In guard(), I plan the following:

  1. Reading the token from the browser's local storage.
  2. Checking the token's expiration date (JWT token stores this information).
  3. Rendering "/auth" if any of the first two steps are not successfully passed.

If the token is valid, another layout and page components are used, within which requests to the REST API are made, and server-side checks are performed to decide which response to return - whether to send requested data, prompt for re-authentication, or something else.

tszyan avatar Apr 06 '24 17:04 tszyan

Correct me if I'm wrong, but I don't think what you want makes sense. Because the very first page the user visits triggers an SSR rendering and you'll need to decide whether to redirect the user already at that point. Thus you need to have your guard() hook be called on the server-side.

brillout avatar Apr 10 '24 14:04 brillout

I apologize for not paying attention to the topic I initiated myself.

To further clarify, the issue is related to a SPA scenario, so ssr is set to false. In this context, I believe it makes perfect sense to handle the redirection on the client side.

tszyan avatar May 19 '24 18:05 tszyan

Indeed, that makes sense. Re-opening.

brillout avatar May 20 '24 05:05 brillout

@tszyan Correct me if I'm wrong, but isn't handling redirection/guarding on a SPA not Vike's job, but rather the frontend framework (client code) you're using?

For me on SolidJS, I'm personally using a combination of:

  • a custom auth.context.ts to expose functions for login, register, logout, user, and loading.
  • a custom protected-route.ts
  • Vike's navigate function.

Here's some sample code:

  • Auth Context: https://github.com/Blankeos/solid-launch/blob/main/src/stores/auth.context.tsx
  • Protected Route: https://github.com/Blankeos/solid-launch/blob/main/src/components/common/protected-route.tsx

Blankeos avatar Jun 09 '24 18:06 Blankeos

Certainly, you're right that such functionality can be implemented independently on the client side using a frontend framework. However, considering that the guard() functionality exists for these purposes, albeit currently only on the server side, it would be logical to extend its implementation to the client side within Vike. Given Vike's support for both SSR and SPA, it would enhance consistency to have the ability to implement this functionality uniformly across both models.

tszyan avatar Jun 11 '24 19:06 tszyan

I agree, this could be very useful on the client as well, since routing can be done on the client it makes sense.

I had the same concern and yesterday I opened a discussion. I'm still reading through the documentation, doing some experiments and trying to understand how the framework works though.

ignition42 avatar Jun 19 '24 11:06 ignition42

I can't see a concrete use case for this. What's your architecture that explains your wish to call guard() always and only on the client-side?

brillout avatar Jun 20 '24 13:06 brillout

https://vike.dev/guard now contains information about where and when guard() is called, and how to control this.

It may (or may not) address the issues of OP, let me know whether it does :eyes:

brillout avatar Jun 20 '24 14:06 brillout

@brillout Thank you. At the time of opening the issue, the biggest problem was that the documentation did not provide a clear understanding of the limitations of the guard() hook. I had to experimentally figure out what was what, including opening this issue. Currently, there are no such documentation problems, and possible solutions are even indicated. I believe this is a satisfactory solution for most developers.

However, I still see issues related to SPA both in the documentation and in how Vike works in this mode (according to the documentation, as I haven't personally checked yet). In particular, it is stated that both data() and guard() are executed on the server side during the initial page load (https://vike.dev/hooks#order), which is fundamentally incorrect for classic SPA applications where only static assets are hosted on the server.

Despite the popularity of SSR, the demand for SPA applications is still high. In order for SPA developers not to have to experiment with what works and how, and for the behavior of the Vike framework to be predictable in such scenarios, it is better to separate the description of configuration and how Vike works in different modes, especially SPA and SSR, in the documentation.

tszyan avatar Jun 21 '24 10:06 tszyan

@tszyan The docs were incorrect and I updated them: https://github.com/vikejs/vike/commit/b675e8139b5150bac358129a3c527a0f8a30cae8. I believe the use cases are covered by Vike's design, as well as now documented (atlhough there is room for improvement as you rightfully suggest). Let me know if you still believe something's missing from either the docs or Vike's design — supporting client-centric apps is very much a priority.

If someone's company is up for it we're looking for sponsors, as it makes a massiv difference to the project.

brillout avatar Jun 24 '24 22:06 brillout