You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently the proposed way to identify a certain client/session is to include an identifier in the subject. Something like foo.bar.{sessionid}. This pattern works well technically but when used in a web browser this makes the code vulnerable to cross site scripting (XSS) attacks. The way XSS works is that any value available to javascript in the browser can be stolen by an XSS attack. The NATS websocket client in the browser needs to have access to sessionid in order to publish on the subject foo.bar.{sessionid}. By making the sessionId value available to the browser code calling NATS it is also made available for theft by XSS attacks.
In HTTP you can fully block XSS attacks by using a httpOnly cookie. The way it works is that the server after authentication sets a httpOnly cookie with a session identifier. The browser stores this cookie but does not make it available to the javascript running in the browser. So there is no way for malicious actors to steal this cookie value by injecting javascript. The browser will pass this cookie to the server on each request so the server can identify the session. So with httpOnly cookies, the server can set a cookie value that it gets back on every request but no javascript in the browser can see this cookie value, making it fully resistent to XSS attacks.
This is a proposal to include something similar to the HTTP solution in NATS websocket rpc calls by using this flow:
The HTTP server issues a httpOnly cookie containing a sessionId
The NATS websocket server is configured with token_cookie to capture this cookie value and pass it to the auth callout service.
The auth callout service issues a JWT that is associated with the client. This JWT is stored on the NATS server.
The issued JWT can contain a specification of headers that should be added to all calls made by the associated client. For example the callout service can add headers: {session: xxxx, foo: bar} claim to the JWT.
When the client makes a call the NATS server not only validates subjects against the JWT associated with the client, it also appends the headers that are specified in the associated JWT.
Later when a NATS service is called from the web browser, the browser client itself does not add a header with the sessionId. Instead the NATS server adds it, and so the NATS service being called can read the headers and get the sessionId.
The sessionId is never exposed to the client since it stays at the NATS server, and thus there can be no XSS attacks to capture the sessionId in the browser.
The headers that are set by the callout service in 4 does not have to be a session id. Eg. it could be another JWT obtained from an OpenID provider that can then be validated by the NATS services being called. This would be very similar to the bearer token flow commonly used in HTTP where the JWT is passed in the authorization header of each HTTP request.
The only way that a service can know if a client can or cannot use it is through permissions in the subject - this means that you must clamp your permissions using subjects and operate within that constraint, as I have explained. NATS server by design doesn't track or telegraph client source. if you are worried about cross site scripting then your cors policy is not quite right. - As I suggested in the discussion, you can always implement access to the services from within the HTTP server. This way the HTTP application on the server-side can proxy the request for the client. This simplifies your client as well and allows it to run in a wider range of environments.
The only way that a service can know if a client can or cannot use it is through permissions in the subject - this means that you must clamp your permissions using subjects and operate within that constraint, as I have explained.
Yes, but even if we do this there is no full flow that keeps things things secure (as I explained in the discussion).
NATS server by design doesn't track or telegraph client source.
Yes, currently it does not, which is the problem. Hence the proposal above to make it possible :-)
if you are worried about cross site scripting then your cors policy is not quite right.
"CORS is unrelated to XSS because any attacker who can place an evil piece of JavaScript into a website can also set up a server that sends correct CORS headers. CORS cannot prevent malicious JavaScript from sending session ids and permlogin cookies back to the attacker. "
In #4920 it is mentioned that NATS will add the header "Nats-Request-Info" if imports are being used. This header will provide details about the connected client. I think this proposal is similar but instead of triggering headers being added by import, they are triggered by specifying an option to add them in the issued JWT.
Proposed change
Currently the proposed way to identify a certain client/session is to include an identifier in the subject. Something like
foo.bar.{sessionid}
. This pattern works well technically but when used in a web browser this makes the code vulnerable to cross site scripting (XSS) attacks. The way XSS works is that any value available to javascript in the browser can be stolen by an XSS attack. The NATS websocket client in the browser needs to have access tosessionid
in order to publish on the subjectfoo.bar.{sessionid}
. By making thesessionId
value available to the browser code calling NATS it is also made available for theft by XSS attacks.In HTTP you can fully block XSS attacks by using a httpOnly cookie. The way it works is that the server after authentication sets a httpOnly cookie with a session identifier. The browser stores this cookie but does not make it available to the javascript running in the browser. So there is no way for malicious actors to steal this cookie value by injecting javascript. The browser will pass this cookie to the server on each request so the server can identify the session. So with httpOnly cookies, the server can set a cookie value that it gets back on every request but no javascript in the browser can see this cookie value, making it fully resistent to XSS attacks.
This is a proposal to include something similar to the HTTP solution in NATS websocket rpc calls by using this flow:
token_cookie
to capture this cookie value and pass it to the auth callout service.headers: {session: xxxx, foo: bar}
claim to the JWT.sessionId
.sessionId
is never exposed to the client since it stays at the NATS server, and thus there can be no XSS attacks to capture thesessionId
in the browser.The headers that are set by the callout service in 4 does not have to be a session id. Eg. it could be another JWT obtained from an OpenID provider that can then be validated by the NATS services being called. This would be very similar to the bearer token flow commonly used in HTTP where the JWT is passed in the authorization header of each HTTP request.
Related to:
#1173
#4920
#5143
Use case
Web browser client wanting to make NATS rpc calls in a secure way that is not exposed to XSS attacks.
Contribution
No response
The text was updated successfully, but these errors were encountered: