Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSRF and SSR #417

Closed
levino opened this issue Jul 10, 2020 · 5 comments
Closed

CSRF and SSR #417

levino opened this issue Jul 10, 2020 · 5 comments
Labels
question Ask how to do something or how something works

Comments

@levino
Copy link

levino commented Jul 10, 2020

I do not understand how SSR could work with (secure) authentication. With the initial GET request, I cannot use authentication headers because they wont be sent if I do not query from Javascript so I have to use cookies. But using cookies is insecure as long as I do not have CSRF-protection via a CSRF-token which is not stored as a cookie, but has to be set and send via Javascript. So how can I securely return user specific content on the initial GET request?

So my expectation is that first just some JS ist returned which then fetches the private data from the client. Everything else looks insecure to me. Maybe I am missing something but if not the full html is returned on the initial request, what is the point of using next.js in the first place instead of cra?

@levino levino added the question Ask how to do something or how something works label Jul 10, 2020
@iaincollins
Copy link
Member

I do not understand how SSR could work with (secure) authentication.

Historically, most websites have exclusively used server side rendering with authentication.

Session Tokens are typically stored in cookies. To best protect against session hijacking (e.g. from third party JavaScript in advertising, tracking, browser extensions, XSS) these should be server only readable cookies that are not accessible directly from JavaScript. This is the model NextAuth.js uses.

So how can I securely return user specific content on the initial GET request?

If a user is signed in, any request from the client will have a secure, sever only readable cookie set that can be used to either look up a session in a database (if it is a database session token) or decoded and verified (if it is a JSON Web Token) to identify the user.

But using cookies is insecure as long as I do not have CSRF-protection via a CSRF-token which is not stored as a cookie, but has to be set and send via Javascript.

Using server readable only cookies is secure without a CSRF token.

The double submit cookie method for cookies used by NextAuth.js is documented by OWASP, and includes protections such as a cookie prefix and cookie signature to ensure it has not been forged.

It might be helpful to give an example of a flow you think is "insecure", and to stick to the question template (which is tended to help us help you) to understand what you are trying to do and give context.

Maybe I am missing something but if not the full html is returned on the initial request, what is the point of using next.js in the first place instead of cra?

Are you asking what is the point of server side rendering in general, or the point of Next.js over Create React App, or is this specific question in relation to authentication?

@levino
Copy link
Author

levino commented Jul 10, 2020

Thank you for taking the time to answer my question in such detail. I have been thinking and considering SSR for a while and always came to the conclusion, that it is fundamentally insecure. It looks like it is only "a little insecure". So GET requests can be forged (by using a special image tag) and will retrieve user specific data from the user. However the attacker cannot use this data as it is not available to the javascript on the attackers website. If the GET request would execute any kind of transaction, the attack would be possible. See also owasp on this. Correct CORS headers will prevent forged POST requests, so these can be used for transactions safely.

It is important to note that SSR is only secure if:

  • GET requests never trigger a transaction
  • CORS headers are correctly set or completely missing*

Further:
Using CSRF-tokens (which would be added to the headers from JS) cannot be used with SSR and offer not protection. So relying on the CORS headers for POST endpoints is the only way of protection.

For me personally this feels like juggling with jigsaws. Especially in the context that a lot of users of next.js etc. are pretty newby and are possibly tempted to accept some query params in the GET routes to trigger a transaction "for convenience" (I mean their basic entrypoint for any kind of example is a "page" which is only accessible via GET). I will potentially also in the future use client side rendering with JWTs in local storage because this approach is dead simple. Even if one triggers transactions with GET one is safe against CSRF.

Thank you again @iaincollins for coming back on this and I think this issue can be closed as "something mildly interesting for people to read in the future".

*How often have I seen the advice to set CORS-Headers to allow "*" to be able to develop locally, etc.

@levino
Copy link
Author

levino commented Jul 10, 2020

And just to spare some time: I know that malicious javascript on my site can steal the JWT from the local storage. But if one has malicious javascript on a website, the attacker can do everything with or without the JWT (for example execute arbitrary authenticated requests) no matter what authentication method is used.

@levino levino closed this as completed Jul 10, 2020
@levino
Copy link
Author

levino commented Jul 10, 2020

And one little joke, if you do not mind:

Historically, most websites have exclusively used server side rendering with authentication.

Historically, most websites have been insecure...

@iaincollins
Copy link
Member

It sounds like you are unfamiliar with some of the established conventions for HTTP (how GET is used vs POST/PUT/DELETE), how cookies are used in authentication flows (httpOnly, cookie prefixes), what CSRF tokens are for (and how they should be used) and what the pitfalls of client side session state are (e.g. session hijacking via XSS / domain attacks).

It is absolutely not true that server side authentication is less secure than client side authentication - particularly with regard to protection against session hijacking (e.g. from XSS, third party trackers, advertising code, etc).

I just want to be very clear and set the record straight on that to avoid any contention in future.

@nextauthjs nextauthjs locked as off-topic and limited conversation to collaborators Jul 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question Ask how to do something or how something works
Projects
None yet
Development

No branches or pull requests

2 participants