Since Next 13.4 we are able to do the following
- Set a cookie with HTTP-ONLY flag
- Using Server Action in a client component to fetch a HTTP-ONLY cookie. Basically I can have a button that when you click it, it will return the value of the HTTP-ONLY cookie, we attach it to the request headers
Is this secure? The biggest compromise of jwt token storage is to either expose yourself to XSS or CSRF against our jwt
With Nextjs, we're able to use Bearer Auth, and store the cookie in http-only, and attach it to headers, thus reducing both XSS and CSRF attack vectors.
Is there a vulnerability to this?
There should not be a vulnerability to this, as long as the fetched HTTP-only cookie is not exposed to client-side JavaScript. The use of HTTP-only cookies is a security measure to prevent client-side scripts from accessing the cookie data, which helps mitigate cross-site scripting (XSS) attacks.
I suppose, as long as everything is done on the server-side, through a server action. It does not matter if it is through:
The button mentioned in your question is likely intended to trigger a server-side action. The button would be part of a client-side component, and when clicked, it would send a request to the server action.
The reason for the button would be to initiate an interaction that requires server-side processing involving HTTP-ONLY cookies, such as refreshing a session, fetching user-specific data, or performing an action that requires authentication. By using server-side logic to handle the cookie, you would keep the token secure by never exposing it to the client-side environment, thus reducing the risk of XSS and CSRF attacks.
A typical workflow would be:
The user interacts with the client-side by clicking a button, and the click event triggers a request to a server-side endpoint in the Next.js application.
The server-side code reads the HTTP-only cookie from the request headers (cookies are automatically sent by the browser with the request). It then attaches this cookie to the Authorization header (as a bearer token) for an outgoing request to an external API. This action is performed server-side and the cookie value is never exposed to the client.
The Next.js server makes (for instance) the authenticated request to the external API. Once the external API responds, the Next.js server processes the response. It may return some data to the client-side, but the HTTP-only cookie value itself is not included in this response, ensuring that it's not exposed to client-side JavaScript.
As a good illustration of this issue, consider
vercel/next.jsdiscussion 59303:The discussion touches on the need for a method to access cookies securely during SSR without exposing them to the client, which is precisely your concern regarding the secure handling of JWTs and other sensitive information stored in cookies.
So this is an area where Next.js might need further development to make sure security best practices can be easily and reliably implemented.
If you have the following workflow:
Then the application has a security flaw, if the client code is able to receive the value of an HTTP-only cookie: HTTP-only cookies should be strictly handled by the server, and any action that requires those cookies should involve a server-side process that does not reveal the cookie's value to the client.
To maintain the security of HTTP-only cookies, the correct approach would be:
In this secure workflow, at no point does the client-side JavaScript have access to the HTTP-only cookie value.
In other words, how these attacks (XSS -- Cross-Site Scripting) can exploit vulnerabilities in web applications to execute malicious scripts in the context of a user's session.
The key point about HTTP-only cookies is that they are designed to be inaccessible to JavaScript running in the browser. That means that even if an XSS attack occurs, the attack script should not be able to read or steal HTTP-only cookies directly because the browser will not allow JavaScript to access these cookies.
However, your scenario involves moving part of the authentication process to the client-side, specifically fetching a token via server actions and then attaching it to request headers on the client-side.
But: If an HTTP-only cookie can be "fetched" and manipulated by client-side JavaScript (as in, the JavaScript can read the value and attach it to headers), it contradicts the HTTP-only flag's purpose. By definition, an HTTP-only cookie cannot be accessed through JavaScript running in the client's browser.
The concern about XSS in the context you mentioned only comes true if the token (stored in an HTTP-only cookie) is somehow made accessible to client-side scripts. That would usually not be possible without server-side assistance due to the HTTP-only restriction.
If an application design allows sensitive information from HTTP-only cookies to be exposed to the client-side (even if indirectly), it could indeed become vulnerable to XSS, where malicious scripts read and exfiltrate these tokens.
The primary way an XSS attack could "get the cookie" is if the application logic inadvertently exposes the cookie's value to the client-side, allowing JavaScript to read it.
That might happen if:
In secure design, HTTP-only cookies are strictly handled by the server, and any client-side operations requiring authentication should be designed not to expose sensitive token values.
Properly used, HTTP-only cookies offer robust protection against XSS concerning cookie theft, but application logic must also make sure no sensitive data is exposed through other means to the client-side.
HTTP-only cookies are a security feature intended to mitigate the risk of client-side script access to the protected cookie. If a cookie is marked as HTTP-only, it is not accessible through JavaScript APIs such as
document.cookie. That restriction is enforced by web browsers to prevent the cookie from being accessed by unauthorized scripts, particularly in the event of an XSS attack.In your scenario:
But: when a server sets an HTTP-only cookie, the browser automatically enforces the HTTP-only policy. That means that no JavaScript running in the browser can read or manipulate this cookie.
So the scenario where client-side JavaScript fetches an HTTP-only cookie, and then manually adds it to the headers of a subsequent request contradicts the enforced behavior of HTTP-only cookies.
Authentication tokens and sensitive information stored in HTTP-only cookies are meant to be handled server-side. The server can read the HTTP-only cookies and include them in request headers when communicating server-to-server or responding to server-side requests. That process is invisible and inaccessible to client-side JavaScript.
Allowing client-side scripts to directly access and manipulate HTTP-only cookies would significantly increase the risk of security vulnerabilities, including XSS attacks. It would enable malicious scripts to steal or manipulate authentication tokens, leading to unauthorized access.
In any secure web application architecture, operations that require access to sensitive cookies, especially those marked as HTTP-only, must be handled by server-side logic.
The client-side code can trigger these operations via requests to the server, but the actual access and manipulation of the cookies should remain within the server's domain.