Cookies === Bad && JWT === Good
I just finished writing this as a Lesson Learned for a project in school and thought I'd share it with the world. Because I'm not a blogger, I'll post it here :-)
Another issue I came across while building the mobile application was I realized that servers cannot set cross-domain cookies.
This posed a problem because of the way that authentication works for many websites (mine included at the time):
1. A user hits the login endpoint with a username and password
2. The server will set a cookie on the user’s browser which is an ID for the session.
3. All cookies are sent to the server with every request
4. When a request arrives, server identifies the user by their session ID in that cookie.
Well, because servers cannot set cookies on browsers coming from another domain, this caused an issue when I was hitting authentication only BucketStreams endpoints. There was no cookie present because the server could not set it. So the server could also not identify a user’s request as being associated with an authenticated user.
The solution (which incidentally came from the same guy who helped me with my code sharing issues on IRC) was to use JSON Web
Tokens. The way it works is like this:
1. The user authenticates
2. The server creates a JSON object with important information about that user (for example UserID)
3. The server encrypts that JSON object using a secret key. This encrypted JSON object is called a Json Web Token (JWT)
4. The server sends that JWT as a response to the authenticating client.
5. The client stores that JWT somewhere (I stored it in localStorage because it made sense for my app, but you could store it in sessionStorage or a cookie).
6. Then (because I was using AngularJS), I used an $httpInterceptor to intercept all http requests and add an authentication header which included the JWT.
7. The server checks for the JWT on every request, if it exists, it decrypts it and sets it as a user property on the request object which the request handlers can work with.
This solved my problem wonderfully. However I did have trouble when authenticating to third parties. This is because of the way OAuth works, which I wont describe, but you might think of it similarly to how JWTs work except instead of a header, normally it’s a query parameter. A big difference, however, is that instead of hitting an endpoint to login, you actually send the user to a page hosted by the third party and they login and authorize your app to use their data. Then the third party sends them back to a url that you specify with a query parameter that represents the token.