1

i'm building a stateless authentication system for a Dart application (Dart gets compiled to JavaScript, so the whole application is an index.html file which loads JavaScript and runs in the browser) and have discovered that it's quite tricky to build a stateless authentication system that's actually secure.

The stack is as follow: Dart application that does JSON POSTs to a Spring MVC (Java) backend using Jackson to convert back and forth between JSON and Java objects. Everything will be behind SSL when it goes into production.

Scenario 1: User logs in, I keep a session on the Java side - this is not stateless and will cause problems when load balancing the backend.

Scenario 2: Upon hitting the login button, a POST is done by Dart to the Authentication controller which verifies the credentials and passes back a token (which could be a bunch of UUIDs concatenated together). The token comes back to the frontend - This token combined with the username will then have to be passed along with each request. The dart application now needs to store this token somewhere, since a Dart application compiles to JavaScript, cookies seems to be not an option (can JavaScript access cookies?). HTML5 localstorage comes to mind, but from what I've read, it's pretty easy to hijack that token if any form of XSS vulnerability is available (and I'm guessing browser plugins and toolbars that inject JavaScript into the page can also access this token?).

Scenario 3: Just like in scenario 2, I get passed back a token from the Spring MVC backend, but instead of storing it in HTML5 localstorage, I keep in a JavaScript variable and pass it on if a new window is opened. The same problem applies here, since it's inside a javascript variable, any kind of XSS vulnerability or browser plugin can nab that token and hijack the session.

To prevent against brute-force attacks, any request that is being sent, if the username-token combination is incorrect, the token for that username will be invalidated and the user will need to login again. Tokens also expire after 15 minutes.

Is this a secure way to maintain state? IF not, how would I either make this stateless-with-token implementation secure or what would be a better implementation?

Update, a diagram of the stack:

enter image description here

2
  • Tell me I've read that wrong and you're not doing security conscious stuff on the front end with JavaScript...
    – ArtOfCode
    Commented Mar 30, 2015 at 21:42
  • I was partially (tokens were being stored in local storage instead of cookies) and it looked dodgy, hence the reason I came here for help to make it work without Javascript Commented Mar 30, 2015 at 22:19

1 Answer 1

2

Any mechanism you come up with, that does not involve the user entering a secret for every request will be vulnerable to XSS. The solution is to try and eliminate XSS from your domain, not to have a solution that is secure in the presence of XSS vulnerabilities. A strong CSP policy will help you in browsers that support it.

Javascript can access cookies, as long as you don't mark them HttpOnly, but you don't need it to as the cookies will be sent automatically with every request. So cookies are going to be more secure then LocalStorage as long as you mark them Secure and HttpOnly.

So I would go for Scenario 2, using cookies. If it needs to be stateless the cookie should be a signed and HMAC'ed token with a time expiry in addition to the cookie timeout, such that the servers stop accepting these tokens after the timeout. It will be hard to securely implement the logout functionality without storing state on the server, you can instruct the client to throw away the token, but without a blacklist or whitelist maintained on the server-side you will be vulnerable to the token being used after the user has logged out.


Response to Comments

CSP, is it something I need to implement on the load balancer in front of A? A is just static html and javascript files.

CSP will need to be served on the top level page (The url the user sees in the address bar), this is A in your case. You should be able to configure you static web server to add headers to every response. Doco. You could also do it at the load balancer but that seems more complex then is required.

If I add CSP on requests going between A and B, ...

CSP is added between A and the browser, not between A and B. In the CSP policy you can configure the browser to be able to communicate with B.

somebody could easily modify the javascript to send different headers.

They could only do this if your html/javascript is being sent over HTTP, not over a secure link e.g. HTTPS. If your top level URL is HTTP all scenarios will be susceptible to man-in-the-middle attacks. The communication between A and the browser and B and the browser need to be over HTTPS to have any security.

A and B are running on different domains, B adds a CORS filter to only allow JSON POST requests from a specific domain for A, should the CSP also be added alongside the CORS headers?

You will need both CORS headers, sent from B to allow communication from A. And CSP headers sent from A to restrict javascript execution as a mitigation strategy for any XSS vulnerabilities in your site.

Since the authentication token is generated, validated and invalidated in the Authentication Service, would HMAC really be needed

In most situations a HMAC makes tokens more secure. If you need to remain stateless you will need a HMAC. If you Authentication Service is state-full, that is it has a list of valid, current tokens, then HMACs are less important as long as your token id's are not guessable. If this is the case consider GUID's for your tokens.

The cookie should obviously be created at A as that is what the browser is interacting with.

My understanding is the browser is also interacting with B, via AJAX, hence the need for the CORS policy. As it is B that is managing the login state and requiring the authentication token the cookie should be set by B. Also as A is just serving static content it would be more elegant if A did not require to set cookies, a dynamic process.

Seeing as it's completely HTML and JavaScript, I'm guessing it's impossible to access data inside the cookie if HttpOnly and Secure is turned on?

Yes with HttpOnly turned on javascript on the browser will be unable to access the cookie. In your case it would be best if the cookie was set by B, with HttpOnly and Secure set, this should happen on a successful login call. Then all subsequent calls to B will automatically have the cookie added to them, and the javascript will not be able to access the cookies.


Timeline - As I would see it.

  1. User navigates to https://a/index.html
  2. A responds with a HTML page including CSP headers, the HTML includes a <script src="https://a/code.js"> tag.
  3. The browser fetches https://a/code.js
  4. code.js puts up a login box, user enters username and password and instructs the browser to send an AJAX POST request to https://b/login
  5. The browser sends a HEAD request to https://b/login to ensure it can make posts.
  6. B responds with the CORS headers allowing POSTs from https://a
  7. The browser sends a POST request to https://b/login containing the username and password
  8. B checks the password and if successful returns a success message and sets a cookie which is HttpOnly and Secure. This cookie contains a token such as a random GUID. This token is stored in B's state.
  9. The user clicks a button
  10. A request is sent to https://b/customer/5/update containing the cookie
  11. B validates the cookie value and proceeds to do the action requested e.g. updates the customer.
  12. The user click logout
  13. The browser sends an AJAX request to https://b/logout
  14. B invalidates the token contained in the cookie in it's state, and send a message back to the client clearing the cookie there also.
2
  • I've added a diagram to make discussion easier. CSP, is it something I need to implement on the load balancer in front of A? A is just static html and javascript files. If I add CSP on requests going between A and B, somebody could easily modify the javascript to send different headers. A and B are running on different domains, B adds a CORS filter to only allow JSON POST requests from a specific domain for A, should the CSP also be added alongside the CORS headers? Since the authentication token is generated, validated and invalidated in the Authentication Service, would HMAC eally be needed? Commented Mar 30, 2015 at 8:40
  • The cookie should obviously be created at A as that is what the browser is interacting with. Seeing as it's completely HTML and JavaScript, I'm guessing it's impossible to access data inside the cookie if HttpOnly and Secure is turned on? Commented Mar 30, 2015 at 8:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .