nuxt: Route middleware not working correctly when defined on a client side plugin

Environment

Nuxt CLI v3.0.0-rc.6 RootDir: /Users/thomas/Documents/tests/nuxt-middleware-bug Nuxt project info:


  • Operating System: Darwin
  • Node Version: v16.16.0
  • Nuxt Version: 3.0.0-rc.6
  • Package Manager: npm@8.11.0
  • Builder: vite
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Reproduction

Please, see a complete reproduction here (with Stackblitz link in README): https://github.com/CodoPixel/nuxtjs-issue-report

Describe the bug

As you can see, on the reproduction, everything seems to be working fine if you’re starting your app on index.vue. However, if you go to page2.vue and reload the page, it will raise a 500 error at the middle of the page.:

500
Unknown route middleware: 'named-test'. Valid middleware: .

And a scary error in the terminal of VSC:

[Vue Router warn]: uncaught error during route navigation:
Error: Unknown route middleware: 'named-test'. Valid middleware: .
    at eval (file:///home/projects/github-55ybba/.nuxt/dist/server/server.mjs:2544:17)
[h3] [unhandled] H3Error: Unknown route middleware: 'named-test'. Valid middleware: .
    at createError (file:///home/projects/github-55ybba/node_modules/h3/dist/index.mjs:254:15)
    at Server.nodeHandler (file:///home/projects/github-55ybba/node_modules/h3/dist/index.mjs:444:21) {
  statusCode: 500,
  fatal: false,
  unhandled: true,
  statusMessage: 'Internal Server Error'
}
[nuxt] [request error] Unknown route middleware: 'named-test'. Valid middleware: .
  at createError (./node_modules/h3/dist/index.mjs:254:15)  
  at Server.nodeHandler (./node_modules/h3/dist/index.mjs:444:21)
[Vue Router warn]: uncaught error during route navigation:
Error: Unknown route middleware: 'named-test'. Valid middleware: .
    at eval (file:///home/projects/github-55ybba/.nuxt/dist/server/server.mjs:2544:17)
[Vue Router warn]: uncaught error during route navigation:
Error: Unknown route middleware: 'named-test'. Valid middleware: .
    at eval (file:///home/projects/github-55ybba/.nuxt/dist/server/server.mjs:2544:17)
[h3] [unhandled] H3Error: Unknown route middleware: 'named-test'. Valid middleware: .
    at createError (file:///home/projects/github-55ybba/node_modules/h3/dist/index.mjs:254:15)
    at Server.nodeHandler (file:///home/projects/github-55ybba/node_modules/h3/dist/index.mjs:444:21) {
  statusCode: 500,
  fatal: false,
  unhandled: true,
  statusMessage: 'Internal Server Error'
}
[nuxt] [request error] Unknown route middleware: 'named-test'. Valid middleware: .
  at createError (./node_modules/h3/dist/index.mjs:254:15)  
  at Server.nodeHandler (./node_modules/h3/dist/index.mjs:444:21)
[Vue Router warn]: uncaught error during route navigation:
Error: Unknown route middleware: 'named-test'. Valid middleware: .
    at eval (file:///home/projects/github-55ybba/.nuxt/dist/server/server.mjs:2544:17)

According to my tests, the problem comes from the fact that I am using addRouteMiddleware inside a client side plugin test.client.ts. The problem goes away when I remove .client from the file name.

Therefore, as the documentation doesn’t say anything about a difference between client side and server side plugin, I guess it’s an issue.

You’re probably wondering why I’m not using middleware directory instead as a work-around, well, see this question on stackoverflow and you’ll understand my despair.

Additional context

I’m trying to use Firebase with NuxtJS 3. Authentication seems to be working fine… but if I want to prevent users from accessing a specific part of the website with a middleware (which would abort the navigation if the user is not admin or if he’s not authenticated) it doesn’t work. More details on stackoverflow.

I hope you’ll help me find a work-around for my project I’d like to finish before September. A work around I had found is to use await navigateTo('/') in setup script on secret pages but it doesn’t work when accessing the page via the URL, as you can see on this other stackoverflow question.

If the behaviour I described is indeed an issue you didn’t know, then I’m glad I could help.

Logs

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 15 (6 by maintainers)

Most upvoted comments

Ah, yes, that certainly is true. We will be adding a spa route rule that allows you to mark all paths matching a certain pattern as client-only. (And that is likely the best solution in your case too.)

@szulcus Yes. You can use definePageMeta only in a page, not in app.vue or a layout. For use cases, you can use global route middleware or register middleware in a plugin.

I believe the issue boils down to requiring Firebase Authentication to execute safely on the client’s side while communicating to the server and Firebase that the user’s login credentials are valid. To do this while still allowing the use of SSR, Firebase provides admin controls that can validate auth tokens passed via cookies. Firebase admin can also perform privileged actions on behalf of the user as long as this is done server-side with protected APIs; this can be more flexible than rule sets so it might be worth considering.

A complete implementation can be found here nuxt-firebase-auth-starter sans actually reading or writing data. In general, Firebase is for the client while Firebase admin is for the server.

Though heads up, this requires the experimental vite-node to be enabled, so proceed with caution as things might be bumpy with that on.

Yes, I would expect doing this to throw an error if you are defining it on server also. You could conceivably only use the middleware on client though:

definePageMeta({
  middleware: process.client ? 'named-test' : undefined
})

Or you could also add a server-only version of the middleware without the full functionality of the client-side one.

I would expect you would want this middleware defined on server side. Is there a reason you are defining it in a client-only plugin?

@danielroe Indeed, I overlooked it in the documentation. Everything works now. Thank you very much for your answer.

No. Global middleware you simply create in ~/middleware/auth.global.ts and it is automatically registered.