14

I have an API to secure. There will potentially be two types of consumers of this API - our own Single Page Application, and third party services that will integrate with it.

I have read that in general cookies are not favoured for REST APIs, it is better to use header fields. Perhaps this is just convention.

Secure cookies are a better place to hold the auth token in an SPA. It prevents them from being obtained by a cross-site script attack. Also, if the SPA opens a new window/tab, the sessionStorage does not flow accross, causing the user to have to log in again. You can use localStorage, but not a good idea to keep auth tokens there, as it persists.

Should I make the authentication filter on the server side accept either a cookie or a header field? Try the cookie first, and if it is not there then try the header field? Cookies would be used by SPAs, and header fields by other API consumers. Or, would it be better to go with only one way of transmitting the auth token?

user2800708
  • 261
  • 2
  • 4
  • 7
    Clarification: the `Secure` cookie flag ensures the cookie is only transmitted over HTTPS (mitigates MITM); the `HTTPOnly` cookie flag ensures that JavaScript can't access the cookie value (mitigates XSS). Transmitting auth stuff in headers can mitigate CSRF. – PlasmaSauna Apr 08 '16 at 18:28
  • @PlasmaSauna Thanks for that. With cookies, something extra must be added to the requests to prevent CSRF, for example, a sequence number in a header field. – user2800708 Apr 11 '16 at 10:45
  • (Oh! Facepalm -- you mentioned both `Secure` and `HTTPOnly` in the title of your question. Yeah, you probably know what's up with those.) – PlasmaSauna Apr 12 '16 at 07:37
  • 1
    Cookies are transferred in HTTP header fields. So *technically* there is potentially very little distinction between the two. – user Apr 12 '16 at 07:55
  • Yes, cookies are header fields. What they offer over header fields is that browsers use the 'httponly' and 'secure' flags to handle them in a more secure way. A little distinction, but an important one. – user2800708 Apr 12 '16 at 08:48
  • See also [Store Auth-Token in Cookie or Header?](https://security.stackexchange.com/questions/180357/store-auth-token-in-cookie-or-header) – Sjoerd Oct 23 '19 at 12:49

2 Answers2

6

I don't think there is a big difference in security between cookies or headers, if properly used.

Cookies are meant to maintain server state. So if you have a login call which starts a session, cookies make sense. If you use an API token that is distributed outside of the API, cookies don't make sense.

In the end, cookies are also sent in headers, so there is little distinction between how they are transmitted. The difference is in how browsers handle cookies:

  • It is possible to set cookies as HttpOnly, making them inaccessible from JavaScript;
  • Cookies are included in every request by the browser.

HttpOnly provide some protection against XSS. However, an attacker can call your API any way he wants when he gets XSS, even if he doesn't obtain the cookie.

That cookies are included in every request makes it vulnerable to cross-site request forgery (CSRF): another webpage can trigger a request to your API, and the cookies are included by default.

In a SPA, an alternative to store the token is in a JavaScript variable. This is only kept while the tab is open, and may be secure against XSS if the variable is limited in scope.

Storing tokens in localStorage keeps them there forever, since localStorage is not cleared when the application is closed. However, this isn't so bad, since you can expire tokens on the server. Even if the token is exposed after a while because it was kept in localStorage, the token won't be valid anymore.

There is also the possibility to use two tokens, one in a cookie and one in a header. You would need both tokens to successfully use the API. Since the cookie is HttpOnly, you are protected against XSS. Since the header is not sent on every request, you are protected against CSRF.

Sjoerd
  • 28,707
  • 12
  • 74
  • 102
  • "However, an attacker can call your API any way he wants when he gets XSS, even if he doesn't obtain the cookie." Isn't it a lot more difficult, though? The attacker would have to know something about the APIs to use them. Whereas with the token in hand, he could just log in and use the UI. – Patrick McElhaney Oct 23 '19 at 13:27
1

For the situation as you described, I recommend transmitting authentication information only in cookies. As you mentioned, this prevents the exfiltration of a user's authentication token from your Single-Page Application.

As an added bonus, having the authentication token as a cookie simplifies the logic in your authentication filter, since there's only one place to check.

Do note that if there is an XSS flaw in your SPA, attacker JavaScript can still issue requests impersonating the user whether you use cookies or headers for the authentication token. So, please, sanitize your output :-)

PlasmaSauna
  • 574
  • 3
  • 6
  • 1
    Why do so many APIs use header fields for the access token? Paypal, for example: https://developer.paypal.com/docs/api/auth-headers/ . I'm concerned that using cookies might be defying convention, even though it would seem to be better from a security view. – user2800708 Apr 12 '16 at 08:45
  • Is the answer that, since cookies do no prevent XSS, like you describe, they are not really more secure than using a header field? – user2800708 Apr 12 '16 at 08:52
  • 1
    Not quite. If the attacker steals the value of the authentication token, they can use it from their own computer(s) at a later date as long as the authentication token is still valid server-side. That's a good reason to prevent the theft of the authentication token. – PlasmaSauna Apr 13 '16 at 03:00
  • 1
    True, but you only make auth tokens valid for a short time. If an attacker can implicitly use the token with XSS attack, then they might as well use it straight away from their script. – user2800708 Apr 13 '16 at 09:47