Token Authentication vs. Cookies
For Googlers:
- DO NOT mix statefulness with state transfer mechanisms
STATEFULNESS
- Stateful = save authorization info on server side, this is the traditional way
- Stateless = save authorization info on client side, along with a signature to ensure integrity
MECHANISMS
- Cookie = a special header with special treatment (access, storage, expiration, security, auto-transfer) by browsers
- Custom Headers = e.g.
Authorization
, are just headers without any special treatment, client has to manage all aspects of the transfer - Other. Other transfer mechanisms may be utilized, e.g. query string was a choice to transfer auth ID for a while but was abandoned for its insecurity
STATEFULNESS COMPARISON
- "Stateful authorization" means the server stores and maintains user authorization info on server, making authorizations part of the application state
- This means client only need to keep an "auth ID" and the server can read auth detail from its database
- This implies that server keeps a pool of active auths (users that are logged in) and will query this info for every request
- "Stateless authorization" means the server does not store and maintain user auth info, it simply does not know which users are signed in, and rely on the client to produce auth info
- Client will store complete auth info like who you are (user ID), and possibly permissions, expiration time, etc., this is more than just auth ID, so it is given a new name token
- Obviously client cannot be trusted, so auth data is stored along with a signature generated from
hash(data + secret key)
, where secret key is only known to server, so the integrity of token data can be verified - Note that token mechanism merely ensures integrity, but not confidentiality, client has to implement that
- This also means for every request client has to submit a complete token, which incurs extra bandwidth
MECHANISM COMPARISON
- "Cookie" is just a header, but with some preloaded operations on browsers
- Cookie can be set by server and auto-saved by client, and will auto-send for same domain
- Cookie can be marked as
httpOnly
thus prevent client JavaScript access - Preloaded operations may not be available on platforms other than browsers (e.g. mobile), which may lead to extra efforts
- "Custom headers" are just custom headers without preloaded operations
- Client is responsible to receive, store, secure, submit and update the custom header section for each requests, this may help prevent some simple malicious URL embedding
SUM-UP
- There is no magic, auth state has to be stored somewhere, either at server or client
- You may implement stateful/stateless with either cookie or other custom headers
- When people talk about those things their default mindset is mostly: stateless = token + custom header, stateful = auth ID + cookie; these are NOT the only possible options
- They have pros and cons, but even for encrypted tokens you should not store sensitive info
HTTP is stateless. In order to authorize you, you have to "sign" every single request you're sending to server.
Token authentication
A request to the server is signed by a "token" - usually it means setting specific HTTP headers, however, they can be sent in any part of the HTTP request (POST body, etc.)
Pros:
You can authorize only the requests you wish to authorize. (Cookies - even the authorization cookie are sent for every single request.)
Immune to XSRF (Short example of XSRF - I'll send you a link in email that will look like
<img src="http://bank.example?withdraw=1000&to=myself" />
, and if you're logged in via cookie authentication tobank.example
, andbank.example
doesn't have any means of XSRF protection, I'll withdraw money from your account simply by the fact that your browser will trigger an authorized GET request to that url.) Note there are anti forgery measure you can do with cookie-based authentication - but you have to implement those.Cookies are bound to a single domain. A cookie created on the domain
foo.example
can't be read by the domainbar.example
, while you can send tokens to any domain you like. This is especially useful for single page applications that are consuming multiple services that are requiring authorization - so I can have a web app on the domainmyapp.example
that can make authorized client-side requests tomyservice1.example
and tomyservice2.example
.Cons:
- You have to store the token somewhere; while cookies are stored "out of the box". The locations that comes to mind are localStorage (con: the token is persisted even after you close browser window), sessionStorage (pro: the token is discarded after you close browser window, con: opening a link in a new tab will render that tab anonymous) and cookies (Pro: the token is discarded after you close the browser window. If you use a session cookie you will be authenticated when opening a link in a new tab, and you're immune to XSRF since you're ignoring the cookie for authentication, you're just using it as token storage. Con: cookies are sent out for every single request. If this cookie is not marked as https only, you're open to man in the middle attacks.)
It is slightly easier to do XSS attack against token based authentication (i.e. if I'm able to run an injected script on your site, I can steal your token; however, cookie based authentication is not a silver bullet either - while cookies marked as http-only can't be read by the client, the client can still make requests on your behalf that will automatically include the authorization cookie.)
Requests to download a file, which is supposed to work only for authorized users, requires you to use File API. The same request works out of the box for cookie-based authentication.
Cookie authentication
- A request to the server is always signed in by authorization cookie.
- Pros:
- Cookies can be marked as "http-only" which makes them impossible to be read on the client side. This is better for XSS-attack protection.
- Comes out of the box - you don't have to implement any code on the client side.
- Cons:
- Bound to a single domain. (So if you have a single page application that makes requests to multiple services, you can end up doing crazy stuff like a reverse proxy.)
- Vulnerable to XSRF. You have to implement extra measures to make your site protected against cross site request forgery.
- Are sent out for every single request, (even for requests that don't require authentication).
Overall, I'd say tokens give you better flexibility, (since you're not bound to single domain). The downside is you have to do quite some coding by yourself.