Security - Don't store tokens in localStorage

Not sure which article you are referring to, as I cited a few. Some advantages of cookies are:

  1. The httpOnly setting. See, for example, https://blog.codinghorror.com/protecting-your-cookies-httponly/ (“HttpOnly cookies don’t make you immune from XSS cookie theft, but they raise the bar considerably.”)
  2. The path setting.
  3. Edited to add: expiration

Other remarks:

  • The argument that “no XSS is possible on my site” is both besides the point and utterly wrong. (I am not attributing this argument to you, just enumerating)
  • The argument that “it’s all the same once the client is compromised” is also wrong, for the numbered reasons above.
  • It seems to me that some people are arguing against the claim “Cookies are perfect”, but this is a straw man. The claim is: they are superior.
  • localStorage is simply not intended to store sensitive information, but cookies are (at least, by comparison). Why not “honor” the intention?
  • My proximate/initial motive in this thread is regarding the stance taken up top, basically opposing the customer, instead of supporting. I mean, your chances of convincing the auditor are sub-zero, and also, maybe it should give us pause to hear what paid specialists are saying, and do we want Meteor to appeal to serious, corporate customers – or not? Even if the concern didn’t make sense (it does), accommodation seems like a productive response.
1 Like

@captainn If the cookie is marked by the server with httpOnly, it’s not available via document.cookies. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Creating_cookies

A cookie is sent on every HTTP request, so it is available on the server side. To use this pattern for Meteor, the login must be treated different than now, because this is done entirely using web sockets and the login method.

1 Like

Does the definition of “anyone with local access” include XSS-attackers?

That’s right. What I meant was that Meteor can’t just use a monkey patch and switch to using httpOnly cookies in place of another client readable method (local storage or secure cookies). The client side app needs access to the auth token to send it with requests over DDP.

I wonder if a sort of half-duplex model could be constructed from various parts though. We really only require DDP requests to contain the auth token, not receipts. There are already tools to set up cookies for SSR (staringatlights:fast-render) and others to convert methods to REST. If Meteor was modified a bit, it could probably be set up to receive http requests (method/subscription requests) which would attach httpOnly cookie auth token, and then respond through a DDP connection.

1 Like

I guess I meant that, you can look up the cookie values. Browser security prevents JavaScript from accessing that information. Otherwise JavaScript loaded from a site can access localStorage or cookies.

What? Who is “you”? Browser security prevents it, but otherwise it doesn’t? [Parse Error]

If local storage has only been used due to Galaxy then we may put this on the current feature request list for Tiny, correct?

3 Likes

Hi all, thank you everyone for some robust discussion.

It would be amazing if we could get a feature request to address this - not sure what or where to request this though… @jkuester - is this something you could setup? (and throw a link to the Feature Request here?)

Is it needed to send the cookie auth on every method/sub calls? It might be possible that only the initial connection that will authenticate the cookie and then succeeding calls will be an “authenticated” ddp. Or are we talking about the same thing?

Possibly - I haven’t looked at the code that controls DDP. I’m not actually certain that the token is even transferred with every request. It actually would make sense not to. But there are recovery scenarios where I think the token would be needed, such as lost and recovered connections, changing IPs, etc.

If it’s not needed for every request, maybe just the handshake (however that works) could be done over HTTP with the httpOnly cookie.

@nickg123, feature requests for Meteor can be made here:

2 Likes

Created a new request:

Looking around, there are already a few feature requests similar that could be used for reference:

3 Likes

Hey @nickg123 the latest topics in this forum are feature requests from Tiny regarding desired Meteor and Galaxy Features:

https://forums.meteor.com/t/help-tiny-post-your-most-wanted-features-for-meteor/

https://forums.meteor.com/t/help-tiny-what-would-it-take-for-you-to-use-galaxy-very-important/

I already posted in the Galaxy topic and linked this one :wink:

1 Like

I’d like to emphasize by the way, that until we have a stable http auth system, we still have a great cookies implementation already:

which is also used in ostrio:files and they are constantly improving, especially the cordova-related headaches are currently tackled.

3 Likes

To reiterate, the package staringatlights:fast-render has a cookies based solution for SSR which works today.

1 Like

I have had some discussions with ChatGPT and I added the following on my server.

    // Sets Content Security Policy to enhance security by restricting resource loading and execution:
    // - `default-src 'self'`: Only allows resources (e.g., scripts, styles, images) from the same origin as the page.
    // - `script-src 'self' 'unsafe-inline' 'unsafe-eval'`: Allows scripts from the same origin,
    //    permits inline scripts, and allows the use of eval().
    //    - Use of 'unsafe-inline' for scripts increases the risk of XSS attacks but may be necessary for compatibility.
    //    - Use of 'unsafe-eval' allows JavaScript's eval() function and similar methods, which can execute arbitrary strings as code.
    //      This can significantly increase the risk of security vulnerabilities such as XSS and should be avoided if possible.
    // - `style-src 'self' 'unsafe-inline'`: Allows stylesheets from the same origin and permits inline styles.
    //    - 'Unsafe-inline' for styles is considered less risky than for scripts but should be minimized if possible.
    // Note: 'unsafe-inline' and 'unsafe-eval' can expose the site to cross-site scripting (XSS) vulnerabilities by allowing
    //       the execution of arbitrary code. Consider refactoring to remove inline usage and 'eval()' or implementing
    //       additional security measures like nonces or hashes to enhance protection against XSS attacks.
    res.setHeader(
        'Content-Security-Policy',
        "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
    );

This allows the client to only talk to the source (meteor) server and not to any other server. This makes it impossible to send the token stored in LocalStorage to another server.

Since we have an isomorphic app, the server could send secrets to a malicious site. Therefore, we use very strict network policies on the server.

My conclusion is: Using Local Storage can be unsafe if you have malicious code injected via some deeply nested npm dependency, using a good Content-Security-Policy can reduce the risk. You have to also make sure that the server has restricted access to the interned, else it could send secrets to a malicious site…

4 Likes

This is pretty basic, but should work. The Helmet package and the Meteor’s Browser Policy packages should handle this and more.

I highly recommend everyone to study on this and adjust it further for your apps. Lot of it will be trial and error, but if you want more secure app, then this is a must.

3 Likes

This should be addressed in the security guide!

1 Like

The documentation on atmosphere is difficult to read and there is no link to meteor/packages/browser-policy, and therefore I would not have considered the package (a package without source is suspicious to me)

https://packosphere.com/meteor/browser-policy

From packosphere