How is nuxt/auth really secure?
Asked Answered
J

2

1

Let's imagine a client opens your nuxt.js website on the index page. From there, they authenticate (you used @nuxtjs/auth-next for that purpose). Then they move to a secure page that only authenticated users can see. This secure page is a .vue file in your "pages" folder with middleware: ["auth"].

Now, how is this page really secure ?

Javanese answered 12/11, 2021 at 15:39 Comment(9)
one way to display secure data on a page is to access it using asyncData from a secure backend API where do you get this one from? Not sure to understand how is this more secure even with target: 'server' since this hook will be client sided once the hydration is done.Rehash
The asyncData hook is also client sided yes but if you use it to fetch the data on your server using an API you can check if the client is valid before sending the data.Javanese
If you want to protect only a specific subset of pages, make a conditional in your middleware. If it's a secure page (one which contains sensitive data and need a valid JWT from the backend), then the middleware will need to reach the backend for a validation. If it's a publicly accessible page, you don't even need to bother the backend. The backend of Nuxt (server-side) don't need to handle anything specific really since it will be client-side navigation anyway. At least, I don't see what a server-side middleware could achieve here.Rehash
Since we're not building a generated version of all the secure pages for 10k people here. As Facebook, we gonna fetch the actual data when the guy is connected, hence client-side only. Of course, public pages could be generated ahead of time. Also, when I was talking about backend below, I was referring to an external backend here, like Rails, PHP or Node.js. Of course, you could use your Nuxt app as a proxy, but the JWT should not be handled in the same repo but on something totally different. TDLR: forget Nuxt backend, think regular non-nuxt backend here.Rehash
Don't think about Nuxt as a really standard backend. I mean, with Nuxt Nitro (Nuxt3), you can have pretty advanced behavior mixing both client side and server side logic. But since you're struggling to understand how JWT, I do recommend taking it easy and splitting things in 2 parts to not mess-up and have a clear understanding on how this is working. Think about Nuxt as a way to improve performance and QoL in your case. Then, you'll be maybe able to setup a more advanced setup later on (if needed). PS: @kissu in your question edit is not sending me a notification btw. I am following it tho.Rehash
Sorry @Rehash for deleting my EDIT, but I thought it would be more appropriate to create a new question as this was different from the question I created here in the first place.Javanese
No issues. It's better indeed.Rehash
@kissu, I don't understand why everyone say "you have to add a middleware on the routes you want to protect". I don't understand because middleware is run once on server-side (on the first request to the Nuxt app) and then client-side when navigating to further routes. So how could I write a middleware that has access to the header JWT token in the Nuxt backend when the middleware itself is run on the client side. It makes no sense ?Javanese
As I told you, the "backend" here is not Nuxt but a regular backend like Node, Rails, PHP or alike. Don't think about Nuxt as a real backend but more as a more powerful frontend. Also, try to understand when people talk about middleware if it's for Nuxt or for the backend thanks to the "routes" keyword (backend specific).Rehash
R
3

Your application being an SPA at the end, if you want to bypass a middleware with it's security checkup, you could disable the JS on the page. But then, since no content is generated directly, you won't see anything because it's not here (as a static file).

If your app is isomorphic (basically has a ssr: true), the auth module will still disable the access to those pages (you can double check).

At the end, the critical info is received when:

  • you do have a valid JWT token (after some login)
  • you submit an HTTP query to the backend
  • the backend acknowledges it and the token is valid
  • the backend gives you the sensitive info via an HTTP response

At the end, your client side code doesn't need to be secure. If somebody somehow hacks your client side state and reaches the sensitive page, he will still not have a valid JWT token since the verification still happens on the backend.
The one that can be generated only when sending the proper credentials to the backend and having the backend validating those.

Rehash answered 12/11, 2021 at 15:49 Comment(16)
I know that you can perform any kind of checks you want on the client first page load / reload with using serverMiddleware. But when a client has the app already loaded on another page, with a valid JWT token, and they request for a secure page, can you check the JWT validity on the server before sending the page .js file to the client ? To my knowledge you can't, and this check is made client side. But am I missing something there ?Javanese
@Javanese actually, a JWT's purpose is exactly to provide a check on the client side with some backend (our use case here). And all of your calls should be wrapped with it. If it's invalid or missing, you should logout the user (the module does it for you if I remember properly). The backend will throw you an error from the first call that do come with an invalid JWT.Rehash
And how practically can you do those checks on the server ?Javanese
@Javanese when the frontend will reach the backend with it's token on a route, the backend will check the validity of the JWT with some database and give you a true/false.Rehash
Okay, I understand what to do, but where do you implement this in Nuxt ?Javanese
@kay you'll need an endpoint on the backend and to set the URL in your Nuxt app. This is the related page of the documentation: auth.nuxtjs.org/schemes/local The videos on the homepage of the module or some Google search may probably give you more info. Otherwise, a quick search here or in the Github issues (even maybe Reddit?) could be places to find a how-to guide.Rehash
Thanks but the url explains how to implement the login itself in Nuxt/auth but not how to check the validity of a connected user before to send them the requested page chunks. I don’t need to know what method to use, but where exactly in Nuxt to insert it if I wanted to do this by myself without any module.Javanese
@kay not sure to understand. The module handles the biggest part for you, set the variables and then use loggedInS state to check if you're properly authenticated. If you want to do it yourself, I guess you can do it pretty anywhere you would like. A generic middleware or maybe an axios interceptor, it's up to your app and the way you want to implement it. If you want to implement it yourself without the auth module, Google on how it works and make your own implementation.Rehash
Sorry, I know I can be confusing sometimes. Let's imagine this scenario : - Your client first loads your site on the index page (/index); - They login and get a valid JWT token with nuxt/auth; - They navigate to a secure page that only authenticated users should be able to see; In this last step, the client gets the secure page chunks (a .js file) from the server by requesting it with a valid JWT token. Now my question is : Is there some kind of validation happening before providing the secure page chunks on the server ?Javanese
And if YES, let's say I had to implement this validation myself (without the auth module), where should I place it ? I mean where or in which option exactly in Nuxt ? Don't say middleware please because these are run client side or server side but only on first page load. So to me, anything client side is not safe and can be tampered with by an experienced user.Javanese
@Javanese answer to the first comment: if somebody goes to a protected page, the actual protected sensitive stuff should actually be on the server. So accessing a protected page is not really a concern because there will be no data on it (if the JWT token is invalid). Also, the client will make an HTTP request. So, the response will not be a .js file but some JSON response from the backend. So no, there is not additional validation, there is only your backend checking your JWT which is fine by itself, because of it's asymmetric nature like SSH (the server keeps the important part in a database).Rehash
@Javanese second comment: so yeah, this needs to happen on middleware because it will be a check that you need to do. Mainly, the only thing that your frontend needs to handle is: 1. if no token, ask for credentials 2. when the JWT will expire, the backend will send you a 401 status code, ask for a refresh token or redirect and ask again for credentials in Nuxt 3. pass it alongside all of your axios sensitive calls. Again, it's totally safe on client side, because your part of the token is public and the private key is hidden on the server. Some documentation: jwt.io/introductionRehash
Thanks for the response and the documentation link. I read everything I could on JWT tokens. What I still don't understand though is how to make the backend aware that it has to check the JWT in the header before providing the JSON of the secure page to the client.Javanese
I've been looking for an answer for days now but I still can't seem to put my finger on it. It's making me crazy.Javanese
@Javanese not a backend expert on this one, but I'd say that you need to have a middleware on some specific endpoints of the router. If somebody hits a protected route, he needs to provide a JWT (coming from Nuxt), you then double-check that the token is a valid one with a function on your backend (+ database), then if it's valid, you can call the related controller to go get the data and send it back to Nuxt. You can have a lot of approaches here, but there is 100% a backend package to handle all the refresh, generation, validation, revokation etc... TLDR: it's a thing to be done on both stacks.Rehash
Ok thanks a lot @Rehash for your time. For those interested in the last question, maybe I will get a precise answer here.Javanese
D
0

Now, how is this page really secure ?

The protected content is served from a request if a valid access token has been provided by the client. The protected content is provided at runtime.

Because the "security" in this scenario is only implemented on the client side right ?

The security is not only implemented on the client side. The premise is: The access token has been obtained securely through an authentication flow with an auth-server. I recommend to read more about auth flows if this sounds unclear. Auth0 has some good documentation on different flows. https://auth0.com/docs/authorization/flows

Then, what is the best way to show a complex page to authenticated users only ?

The content is provided at run-time. Server-side or client-side. There are some setup guides here for Nuxt. Here is the first (Auth0) I found from the list. https://auth.nuxtjs.org/providers/auth0

I don't know how updated those guides are, but the auth service providers tend to have updated guides themselves.

Detestation answered 12/11, 2021 at 16:55 Comment(5)
As I commented in the other response : let me try to rephrase my question. Let's imagine this scenario : - Your client first loads your site on the index page (/index); - They login and get a valid JWT token with nuxt/auth; - They navigate to a secure page that only authenticated users should be able to see. In this last step, the client gets the secure page chunks (a .js file) from the server by requesting it with a valid JWT token. Now my question is : Is there some kind of validation happening before providing the secure page chunks on the server ?Javanese
And if YES, let's say I had to implement this validation myself (without the auth module), where should I place it ? I mean where or in which option exactly in Nuxt ? Don't say middleware please because these are run client side or server side but only on first page load. So to me, anything client side is not safe and can be tampered with by an experienced user.Javanese
@Javanese is basically the go-to for "how to handle secure calls between a backend and a frontend SPA" so yeah, don't worry it's not hacky and insecure in any way. Otherwise, it wouldn't be one of the most used authentication method as of today SPA's usage. The only thing, is maybe that you'll need to wait for the token to expire if you want to remove the access to somebody. But this is not a big issue, if you fix the access_token to 5min or so. And if your token is revoked, the backend can also invalidate it on your next client side navigation too. Read some documentation for the main concepts.Rehash
"Is there some kind of validation happening before providing the secure page chunks on the server" This sounds like a static compiled JS file? then I would say no without being 100% sure. Protected content happens at runtime. If an anonymous user navigates to a secure page, then we throw the user to the login page or something. If the user is authenticated. Then the protected content is requested at runtime.Detestation
I don't see Nuxt preventing access to "privileged" route source files at all. I'm able to download js chunks from a Nuxt server without being authenticated, given I know (or guess) the hash filename.Salvatoresalvay

© 2022 - 2024 — McMap. All rights reserved.