GITkit and MITM security between and Android app and a backend server - security

Is it correct to assume that the idtoken offers no more security than replacing it with a (possibly salted) SHA2 hash of itself in any follow-up communication with the backend server?
The indended flow would be the following:
The Android app obtains an idtoken from Google
The app sends the idtoken to the self-hosted backend server, where it is verified by the backend with the use of gitkitclient.VerifyGitkitToken
The backend creates a SHA2 hash of the token together with the expiry
date and the associated user id, and stores it for future reference in a lookup table
The Android app creates the same SHA2 hash of the idtoken and passes it
along in the header in any future communication with the backend, instead of using the idtoken for the follow-up communication.
Does this decrease in any way the security of the system?
If a transparent proxy with https inspection (and the according certificates installed on the device, ie legitimately in a corporate environment) would sniff the traffic, it would make no difference if the idtoken is obtained or the SHA2 hash of it, that transparent proxy would be able to act (possibly in a rouge way) on behalf of the Android app for the entire lifetime of the idtoken, right?
My issue is that calling gitkitclient.VerifyGitkitToken on every follow-up communication with the server is too expensive, and not necessary once the validity of the idtoken has been ascertained.
I also don't want the idtoken to be stored on the server for future reference, instead prefer having a hash of it. Is a SHA224 hash of the idtoken enough and is it safe to assume that it would not result in any collisions?

This requires a long discussion of what should be in an authentication cookie and what are the pros and cons of various approaches. No one solution will be fit for all and depending on the app/site security, performance, scalability requirements a solution should be carefully selected. So I really can not comment on the proposed solution without understanding a lot more details about the app, requirements and threats.
In general, the authentication cookie/token have these basic requirements
Should not be forgeable (signed by your server)
Should be easy to validate
Even if the signing secret is stolen, a hacker should not be able to create tokens for all users (e.g. can be achieved by having a per account nonce)
Should be revokable from the server (achieved by maintaining a server side state)
Optionally tied to a client to it was issued, so if stolen from a client will make it useless
I'm sure there are a lot more desirable properties.
GITKit issues the id_token for a one time authentication use and a developer should use their own cookies/token to continue to keep the session of the app/browser. We know that many developer would like us to help and we are working on a solution that would give a long lived OAuth refresh token (and short lived access token) to the app that it can continue to use with its home server.

Related

How worried should I be about opening up a JWT to an XSS vulnerability?

I am building a node.js web application with react for the the GUI and graphQL served with Apollo for the back-end connecting to a RDS (MySQL) instance on AWS.
I am authenticating users and then returning JWTs. I have it figured out on how to renew/expire tokens, but now I am being faced with the question where to save it on the client side when a user visits the site...
There are two main concepts with a third being a hybrid model. 1) Store it as localStorage with JavaScript as described on HowToGraphQL 2) Store it in a Cookie with http-only set to true as described in the afore mentioned article as a cationary reference to Randall Degges
There is another alternative to store it in memory only on the client side but then a user would have to login every time the page is refreshed as it would not be persistent anywhere.
Concept 1 is vulnerable to XSS only if there is another XSS vulnerability already exploited. But it is secure to the site only so only scripts running on the site can access it and not scripts on any site. There it a lot of security talk that it should not be stored this way even though it is the common way because a developer cannot trust EVERY JavaScript script they are running on their site and there may be one that reads the localStorage and then sends it offsite.
Concept 2 removes the XSS vulnerable by declaring the http-only to only make it accessible to the server at your site. The problem here lies in that then a separate method has to be created to use the same backend authentication for other uses such as a standard API (for native apps or other sites) where the JWT is sent in the header over https where it is stored securely on another server.
So I researched and found this hybrid method described by Ben Awad 3) use a request token and a refresh token. The request token can then act normally for the standard API but then also on our react app site we can store it only in memory and store a refresh token in a cookie to send back a request token when users refresh or close and reopen browsers.
So theoretically, the best solution is Concept 3 which solves all of the concerns, but it is of course more complicated to setup.
My question: How worried should I be about opening up a JWT to an XSS vulnerability? It is something that down the road I would do the long way when I have more time, but I am pushing for a deadline. My site will be lesser known and not something like Facebook or Sales-Force that hackers would necessarily target. My site is not storing Credit Card data or other highly sensitive data other than a basic CRM and task list. If my site was open to XSS through other code, wouldn't the entire authentication process be vulnerable through keylogging scripts or the likes without even knowing the JWT. I feel like I would be doing a lot of extra work to secure against a possible threat that if occurred, the entire system would be compromised already.
If you are comfortable with your site to not work on Internet Explorer and some older versions of the major browsers, you can take advantage of a new cookies property, called Same-Site (to be more precise, the site will work but the cookie will not be secure).
By defining a cookie as HttpOnly, you are immediately secured from XSS attacks, but you leave yourself open to CSRF attacks.
Now by defining the cookie to have the property Same-Site=Strict, the cookie will be only sent through Http calls and only if the domain matches your site's domain. So for example, if someone creates a form in another site and tries to perform a post request to your own site, the cookie will be never sent.
If you want the cookie to be passed only on GET requests, you can set the Same-Site property to Lax but as you mentioned.
You can find more info about this feature in the following link under the SameSite cookies section:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
You should also check the browser compatibility of the feature by using the following link:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Browser_compatibility
This is the issue I spent a lot of time on. How to store the authorization token securely. People have different strategies in dealing with this so I will share what works for me. Users of my apps were targeted by different attacks, all of them where unsuccessful in stealing anything so far. None used XSS.
Here is what I do
In the end I opted for storing authorization token in local storage. Applications that I work usually have WebSocket connections on top of HTTP routes and I want the token to be saved in one place and act as a single source of truth. They are all web applications running in the browser. Most of the applications I build use JWT.
Why I do it like that
First why I don't use refresh tokens. If they are saved the same way as the actual authorization token would be saved negates the reason for refresh token to exist since the attacker can use the refresh token to get the authorization one.
Storing the token in cookies gives no benefits over local storage assuming that the app is secured against attackers being able to inject JavaScript into your app, mostly through forms and api on your app. Make sure all user inputs are JS injection safe. On top of that with cookies there are issues when using WebSockets that you must go around.
There is also the point of one of the accounts being hacked and you want to invalidate that token as soon as possible. JWT by default has no mechanism of being revoked. Implementing this feature negates the scalability of JWT because checking the JWT would require a call to the database to know if that user can do the specific action. There are 2 ways you can go about this. One is just check the user data if the user is frozen from the database, it is less scalable because of the call but if you already pull the user data in a middleware it is good enough TM. Other is to pull the the "is the user frozen" data from the database just when making changes to the database or when the call from the client is important.
In summary
I would store the token in local storage. Secure the app from code injections. And make a kill switch for the accounts if they get compromised in any way.
EDIT THANKS TO THE COMMENTS BY #JerryCauser
It is more secure to keep your token in a secure http only cookie. Don't expect a storage mechanism choice to automatically save your users from being hacked. There are ways to hijack sessions and other exploits including users using web extensions and approving their request to read protected data.
For the example of the betting website below, you wouldn't require user to write their password (or approve the request via automated email) every time they place a bet, but you would every time they want to take a withdrawal for example.
I use local storage because even if it happens for the token to be stolen, or another person got to your user's laptop (like a kid for example) you should never let the account do critical tasks without approval.
There is no magic bullet of anti hack protection. Try your best to keep your users safe with common sense.
EDIT AS ANSWER TO THE COMMENT FROM THE ASKER #amaster
If you are making a trip to the database on every call, maybe JWT is not the best solution. Point of JWT is to have signed claims and the id of the user without calling the database. In this case, maybe opt in for sessions instead of JWT.
Before I proceed with my answer, you may want to check out OWASP for a set of general guidelines regarding XSS and CSRF since you've mentioned cookies.
Cedomir already covered a good deal of the points with storing JWT client side. One thing that's worth mentioning is that if you have Third-Party scripts running in your web app, they also have access to the Storage API. So if a script you had loaded were to be hijacked, they could conceivably steal the token there. As for XSS with inputs, if you make sure to escape every possible user input, then that is largely mitigated as an attack vector. But you only have to screw up once for someone to take advantage of the hole and steal the JWT at that point. (Refer to this blog post for more details)
Now, if you instead store the JWT in a Http-Only, then you largely sidestep the XSS issue as you've already noted. However, now you introduced a new problem, that being Cross Site Request Forgery. Since cookies are sent with every request, a malicious actor could set up a website to make a fraudulent request on behalf of user and execute actions without the user's consent. Now I won't cover the mitigation in detail here as OWASP and other places have done a pretty good job already, but the short of it can be summed up by installing the most popular and well-maintained Anti-CSRF package for your language :-)
As for invalidating the token as Cedomir brought up, having that mechanism can be quite useful. However, to implement it does mean you give up some of the benefits of using JWT gives you. Whether you store the current JWT assigned to user and validate that or a unique key used to sign the JWT for each user, you now have user state to keep track of, eliminating one of the reasons to use JWTs. Depending on your application, you will need to weigh that tradeoff. A much simpler way could be simply to have short-lived tokens so that any token that is stolen potentially won't have a very useful lifetime. However, as you probably recognize a short lifetime would be a potentially a very annoying user experience. You could have your website periodically poll the server for a new token while your user continues to use the website as a way to improve the experience. You can also balance your security concerns with the lifetime of the token, like a 15 minute token lifetime for a e-commerce app vs. a hour or more for a social application.
I would however advise against the use of a refresh token, at least for a Browser-Based Web App. Typically speaking, the browser is just not considered capable of securing sensitive secrets. By using a refresh token, you're just deferring the stealing of credentials to another layer as by the nature of the refresh tokens, they're 1) long-lived and 2) effectively used as credentials to obtain more JWTs. So if the refresh token were to be stolen, an attacker can just get more valid JWTs on behalf of a user. If you have a mobile or desktop app, you have mechanisms you can use to securely store refresh tokens and this advice does not apply.
...Or you could just use sessions ;-)
When logging in on server set JWT token and a random csrf token in the httpOnly cookie
Also send this csrf token in body response of login back to client
On every future request from client send this csrf token via some header (eg. X-CSRF-TOKEN)
On the backend verify if the csrf tokens coming through the cookie and x-csrf-token are the same.
Then verify your JWT token and continue with your app logic.
Putting JWT token in httpOnly cookie prevents XSS attacks, validating CSRF token prevents CSRF attacks. Double sending csrf token in both cookie and header avoids storing stuff in the backend database.
XSS check
CSRF check
Stateless auth check
Auth doesn’t have to be over complicated. If you have clients that only want to pass JWT token in some header other than cookie then it’s better to just make a separate api endpoint for those programs.
While the question is not actually about OAuth / OpenID Connect I still think you can learn a great deal by checking out this Internet-Draft: OAuth 2.0 for Browser-Based Apps (Best Current Practice)
To sum it up: there simply is no secure way to store an access token on the client. If you develop only the frontend you pretty much have to use and store a token on client side - not because it's great but because you have no other choice. However, if you do have full control over Frontend and Backend you do have that choice and should think about using the same domain for both and use a session cookie as described in the Internet Draft. Basically the React application never even sees the acesss token, because your backend is serving a http page and handling the authentication directly, with the final step being a redirect back to your frontend while setting the session-cookie.
A potential XSS attack is pretty bad as it is and you should be careful not to introduce a vulnerability. The thing is: with the JWT-approach a XSS vulnerability leads pretty much to the worst-case scenario: the attacker is able to steal the user authentication and can impersonate the user - this is basically session hijacking.
The same attack against a regular session-cookie simply does not have the same impact (as long as the cookie uses the HttpOnly Flag which is highly recommended). Even though the vulnerability enables arbitrary JavaScript Code to run on the machine (which is really bad obviously) it's still a lot harder for the attacker to do some damage. He is not able to hijack the session in this case, because he is unable to read the cookie.
Just use HTTP only + SSL only cookies to save your JWT. It will make almost impossible to stole user's jwt via a soft or any type of code injections.
Someone said here, what it is no diff between LocalStorage and Cookies. He is not correct, bcs third party libraries and chrome extensions can easily stole LocalStorage data. But they cannot stole HTTP only cookie.
It will protect against any known and most likely new types of attacks.
JWT itself is completely protected. Just don’t store something there that could compromise your architecture or something like that (do not put a hashed password for example)
Upd: Good article about best practices for JWT strategy: https://ducktypelabs.com/5-mistakes-web-developers-should-avoid-when-using-jwts-for-authentication/

Securely pass session to browser from OAuth'd app

This is quite a conceptional question, but I'm also interested in implementation details.
Let's say I have an API written in Node.js.
Clients (primarily an iOS app) authenticate via OAuth and then use the session token to authorize each following request.
I now want to point from the app to a browser based web app and take over the authenticated session.
This should, of course, be highly secure and must not be vulnarable in a theoretic sense, but as far as possible in an implementation wise thinking.
I must, somehow, ensure that the request comes from the same device and user, etc.
I thought of generating a short valid token that the client must send, but also this does not seem quite secure when having in mind the TLS protected API.
You want to be more secure than OAuth.
From OAuth's perspective, whomever possess the token, is authorised to act on the user's behalf. You may wish to include a secondary secret or verify the IP but I doubt it will do much for you in practice:
If the platform you are on (e.g. iOS) is not compromised, than the OAuth token will be entropy enough to confirm the user's identity. If the platform IS compromised, then any secret your application can set can also be extracted by the assumed attacker.

Best practices for server-side handling of JWT tokens [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
(spawned from this thread since this is really a question of its own and not specific to NodeJS etc)
I'm implementing a REST API server with authentication, and I have successfully implemented JWT token handling so that a user can login through a /login endpoint with username/password, upon which a JWT token is generated from a server secret and returned to the client. The token is then passed from the client to the server in each authenticated API request, upon which the server secret is used to verify the token.
However, I am trying to understand the best practices for exactly how and to what extent the token should be validated, to make a truly secure system. Exactly what should be involved in "validating" the token? Is it enough that the signature can be verified using the server-secret, or should I also cross-check the token and/or token payload against some data stored in the server?
A token based authentication system will only be as safe as passing username/password in each request provided that it's equally or more difficult to obtain a token than to obtain a user's password. However, in the examples I've seen, the only information required to produce a token is the username and the server-side secret. Doesn't this mean that assuming for a minute that a malicious user gains knowledge of the server secret, he can now produce tokens on behalf of any user, thereby having access not only to one given user as would be the fact if a password was obtained, but in fact to all user accounts?
This brings me to the questions:
1) Should JWT token validation be limited to verifying the signature of the token itself, relying on the integrity of the server secret alone, or accompanied by a separate validation mechanism?
In some cases I've seen the combined use of tokens and server sessions where upon successful login through the /login endpoint a session is established. API requests validate the token, and also compare the decoded data found in the token with some data stored in the session. However, using sessions means using cookies, and in some sense it defeats the purpose of using a token based approach. It also may cause problems for certain clients.
One could imagine the server keeping all tokens currently in use in a memcache or similar, to ensure that even if the server secret is compromised so that an attacker may produce "valid" tokens, only the exact tokens that were generated through the /login endpoint would be accepted. Is this reasonable or just redundant/overkill?
2) If JWT signature verification is the only means of validating tokens, meaning the integrity of the server secret is the breaking point, how should server secrets be managed? Read from an environment variable and created (randomized?) once per deployed stack? Re-newed or rotated periodically (and if so, how to handle existing valid tokens that were created before rotation but needs to be validated after rotation, perhaps it's enough if the server holds on to the current and the previous secret at any given time)? Something else?
Maybe I'm simply being overly paranoid when it comes to the risk of the server secret being compromised, which is of course a more general problem that needs to be addressed in all cryptographic situations...
I've been playing with tokens for my application as well. While I'm not an expert by any means, I can share some of my experiences and thoughts on the matter.
The point of JWTs is essentially integrity. It provides a mechanism for your server verify that the token that was provided to it is genuine and was supplied by your server. The signature generated via your secret is what provides for this. So, yes, if your secret is leaked somehow, that individual can generate tokens that your server would think are its own. A token based system would still be more secure than your username/password system simply because of the signature verification. And in this case, if someone has your secret anyway, your system has other security issues to deal with than someone making fake tokens (and even then, just changing the secret ensures that any tokens made with the old secret are now invalid).
As for payload, the signature will only tell you that the token provided to you was exactly as it was when your server sent it out. verifying the that the payloads contents are valid or appropriate for your application is obviously up to you.
For your questions:
1.) In my limited experience, it's definitely better to verify your tokens with a second system. Simply validating the signature just means that the token was generated with your secret. Storing any created tokens in some sort of DB (redis, memcache/sql/mongo, or some other storage) is a fantastic way of assuring that you only accept tokens that your server has created. In this scenario, even if your secret is leaked, it won't matter too much as any generated tokens won't be valid anyway. This is the approach I'm taking with my system - all generated tokens are stored in a DB (redis) and on each request, I verify that the token is in my DB before I accept it. This way tokens can be revoked for any reason, such as tokens that were released into the wild somehow, user logout, password changes, secret changes, etc.
2.) This is something I don't have much experience in and is something I'm still actively researching as I'm not a security professional. If you find any resources, feel free to post them here! Currently, I'm just using a private key that I load from disk, but obviously that is far from the best or most secure solution.
Here are some things to consider when implementing JWT's in your application:
Keep your JWT lifetime relatively short, and have it's lifetime managed at the server. If you don't, and later on need to require more information in your JWTs, you'll have to either support 2 versions, or wait until your older JWTs have expired before you can implement your change. You can easily manage it on the server if you only look at the iat field in the jwt, and ignore the exp field.
Consider including the url of the request in your JWT. For example, if you want your JWT to be used at endpoint /my/test/path, include a field like 'url':'/my/test/path' in your JWT, to ensure it's only ever used at this path. If you don't, you may find that people start using your JWTs at other endpoints, even ones they weren't created for. You could also consider including an md5(url) instead, as having a big url in the JWT will end up making the JWT that much bigger, and they can get quite big.
JWT expiry should be configurable by each use case if JWTs are being implemented in an API. For example, if you have 10 endpoints for 10 different use cases for JWT's, make sure you can make each endpoint accept JWTs that expire at different times. This allows you to lock down some endpoints more than others, if for example, the data served by one endpoint is very sensitive.
Instead of simply expiring JWTs after a certain time, consider implementing JWTs that support both:
N usages - can only be used N times before they expire and
expire after certain amount of time (if you have a one use only token, you don't want it living forever if not used, do you?)
All JWT authentication failures should generate an "error" response header that states why the JWT authentication failed. e.g. "expired", "no usages left", "revoked", etc. This helps implementers know why their JWT is failing.
Consider ignoring the "header" of your JWTs as they leak information and give a measure of control to hackers. This is mostly concerning the alg field in the header - ignore this and just assume that the header is what you want to support, as this avoids hackers trying to use the None algorithm, which removes the signature security check.
JWT's should include an identifier detailing which app generated the token. For example if your JWT's are being created by 2 different clients, mychat, and myclassifiedsapp, then each should include it's project name or something similar in the "iss" field in the JWT e.g. "iss":"mychat"
JWT's should not be logged in log files. The contents of a JWT can be logged, but not the JWT itself. This ensures devs or others can't grab JWT's from log files and do things to other users accounts.
Ensure your JWT implementation doesn't allow the "None" algorithm, to avoid hackers creating tokens without signing them. This class of errors can be avoided entirely by ignoring the "header" of your JWT.
Strongly consider using iat (issued at) instead of exp (expiry) in your JWTs. Why? Since iat basically means when was the JWT created, this allows you to adjust on the server when the JWT expires, based on the creation date. If someone passes in an exp that's 20 years in the future, the JWT basically lives forever! Note that you automatically expire JWTs if their iat is in the future, but allow for a little bit of wiggle room (e.g 10 seconds), in case the client's time is slightly out of sync with the servers time.
Consider implementing an endpoint for creating JWTs from a json payload, and force all your implementing clients to use this endpoint to create their JWTs. This ensures that you can address any security issues you want with how JWTs are created in one place, easily. We didn't do this straight off in our app, and now have to slowly trickle out JWT server side security updates because our 5 different clients need time to implement. Also, make your create endpoint accept an array of json payloads for JWTs to create, and this will decrease the # of http requests coming in to this endpoint for your clients.
If your JWT's will be used at endpoints that also support use by session, ensure you don't put anything in your JWT that's required to satisfy the request. You can easily do this if you ensure your endpoint works with a session, when no JWT is supplied.
So JWT's generally speaking end up containing a userId or groupId of some sort, and allow access to part of your system based on this information. Make sure you're not allowing users in one area of your app to impersonate other users, especially if this provides access to sensitive data. Why? Well even if your JWT generation process is only accessible to "internal" services, devs or other internal teams could generate JWTs to access data for any user, e.g. the CEO of some random client's company. For example, if your app provides access to financial records for clients, then by generating a JWT, a dev could grab the financial records of any company at all! And if a hacker gets into your internal network in anyway, they could do the same.
If you are are going to allow any url that contains a JWT to be cached in any way, ensure that the permissions for different users are included in the url, and not the JWT. Why? Because users may end up getting data they shouldn't. For example, say a super user logs into your app, and requests the following url: /mysite/userInfo?jwt=XXX, and that this url gets cached. They logout and a couple of minutes later, a regular user logs into your app. They'll get the cached content - with info about a super user! This tends to happen less on the client, and more on the server, especially in cases where you're using a CDN like Akamai, and you're letting some files live longer. This can be fixed by including the relevant user info in the url, and validating this on the server, even for cached requests, for example /mysite/userInfo?id=52&jwt=XXX
If your jwt is intended to be used like a session cookie, and should only work on the same machine the jwt was created for, you should consider adding a jti field to your jwt. This is basically a CSRF token, that ensures your JWT can't be passed from one users's browser to anothers.
I don't think I'm an expert but I'd like to share some thoughs about Jwt.
1: As Akshay said, it's better to have a second system to validate your token.
a.: The way I handle it : I store the hash generated into a session storage with the expiricy time. To validate a token, it needs to have been issued by the server.
b.:There is at least one thing that must be checked the signature method used. eg :
header :
{
"alg": "none",
"typ": "JWT"
}
Some libraries validating JWT would accept this one without checking the hash. That means that without knowing your salt used to sign the token, a hacker could grant himself some rights. Always make sure this can't happen.
https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
c.: Using a cookie with a session Id would not be useful to validate your token. If someone wants to hijack the session of a lambda user, he would just have to use a sniffer (eg : wireshark). This hacker would have both information at the same time.
2: It is the same for every secret. There is always a way to know it.
The way I handle it is linked to the point 1.a. : I have a secret mixed with a random variable. The secret is unique for every token.
However, I am trying to understand the best practices for exactly how
and to what extent the token should be validated, to make a truly
secure system.
If you want the best security possible, you should not blindly follow best practices. The best way is to understand what you're doing (I think it's ok when I see your question), and then evaluate the security you need. And if the Mossad want to have access to your confidential data, they 'll always find a way. (I like this blog post : https://www.schneier.com/blog/archives/2015/08/mickens_on_secu.html )
Lots of good answers here. I'll integrate some of the answers I think are most relevant and add some more suggestions.
1) Should JWT token validation be limited to verifying the signature of the token itself, relying on the integrity of the server secret alone, or accompanied by a separate validation mechanism?
No, because of reasons unrelated to the compromise of a token secret. Each time a user logs in via a username and password, the authorization server should store either the token that was generated, or metadata about the token that was generated. Think of this metadata as an authorization record. A given user and application pair should only have one valid token, or authorization, at any given time. Useful metadata is the user id associated with the access token, the app id, and the time when the access token was issued (which allows for the revocation of existing access tokens and the issuing of a new access token). On every API request, validate that the token contains the proper metadata. You need to persist information about when each access tokens was issued, so that a user can revoke existing access tokens if their account credentials are compromised, and log in again and start using a new access token. That will update the database with the time when the access token was issued (the authorization time created). On every API request, check that the issue time of the access token is after the authorization time created.
Other security measures included not logging JWTs and requiring a secure signing algorithm like SHA256.
2) If JWT signature verification is the only means of validating tokens, meaning the integrity of the server secret is the breaking point, how should server secrets be managed?
The compromise of server secrets would allow an attacker to issue access tokens for any user, and storing access token data in step 1 would not necessarily prevent the server from accepting those access tokens. For example, say that a user has been issued an access token, and then later on, an attacker generates an access token for that user. The authorization time of the access token would be valid.
Like Akshay Dhalwala says, if your server-side secret is compromised, then you have bigger problems to deal with because that means that an attacker has compromised your internal network, your source code repository, or both.
However, a system to mitigate the damage of a compromised server secret and avoid storing secrets in source code involves token secret rotation using a coordination service like https://zookeeper.apache.org. Use a cron job to generate an app secret every few hours or so (however long your access tokens are valid for), and push the updated secret to Zookeeper. In each application server that needs to know the token secret, configure a ZK client that is updated whenever the ZK node value changes. Store a primary and a secondary secret, and each time the token secret is changed, set the new token secret to the primary and the old token secret to the secondary. That way, existing valid tokens will still be valid because they will be validated against the secondary secret. By the time the secondary secret is replaced with the old primary secret, all of the access tokens issued with the secondary secret would be expired anyways.
IETF have a RFC in progress in the oAuth Working Group see : https://tools.ietf.org/id/draft-ietf-oauth-jwt-bcp-05.html

SPA best practices for authentication and session management

When building SPA style applications using frameworks like Angular, Ember, React, etc. what do people believe to be some best practices for authentication and session management? I can think of a couple of ways of considering approaching the problem.
Treat it no differently than authentication with a regular web application assuming the API and and UI have the same origin domain.
This would likely involve having a session cookie, server side session storage and probably some session API endpoint that the authenticated web UI can hit to get current user information to help with personalization or possibly even determining roles/abilities on the client side. The server would still enforce rules protecting access to data of course, the UI would just use this information to customize the experience.
Treat it like any third-party client using a public API and authenticate with some sort of token system similar to OAuth. This token mechanism would used by the client UI to authenticate each and every request made to the server API.
I'm not really much of an expert here but #1 seems to be completely sufficient for the vast majority of cases, but I'd really like to hear some more experienced opinions.
This question has been addressed, in a slightly different form, at length, here:
RESTful Authentication
But this addresses it from the server-side. Let's look at this from the client-side. Before we do that, though, there's an important prelude:
Javascript Crypto is Hopeless
Matasano's article on this is famous, but the lessons contained therein are pretty important:
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
To summarize:
A man-in-the-middle attack can trivially replace your crypto code with <script> function hash_algorithm(password){ lol_nope_send_it_to_me_instead(password); }</script>
A man-in-the-middle attack is trivial against a page that serves any resource over a non-SSL connection.
Once you have SSL, you're using real crypto anyways.
And to add a corollary of my own:
A successful XSS attack can result in an attacker executing code on your client's browser, even if you're using SSL - so even if you've got every hatch battened down, your browser crypto can still fail if your attacker finds a way to execute any javascript code on someone else's browser.
This renders a lot of RESTful authentication schemes impossible or silly if you're intending to use a JavaScript client. Let's look!
HTTP Basic Auth
First and foremost, HTTP Basic Auth. The simplest of schemes: simply pass a name and password with every request.
This, of course, absolutely requires SSL, because you're passing a Base64 (reversibly) encoded name and password with every request. Anybody listening on the line could extract username and password trivially. Most of the "Basic Auth is insecure" arguments come from a place of "Basic Auth over HTTP" which is an awful idea.
The browser provides baked-in HTTP Basic Auth support, but it is ugly as sin and you probably shouldn't use it for your app. The alternative, though, is to stash username and password in JavaScript.
This is the most RESTful solution. The server requires no knowledge of state whatsoever and authenticates every individual interaction with the user. Some REST enthusiasts (mostly strawmen) insist that maintaining any sort of state is heresy and will froth at the mouth if you think of any other authentication method. There are theoretical benefits to this sort of standards-compliance - it's supported by Apache out of the box - you could store your objects as files in folders protected by .htaccess files if your heart desired!
The problem? You are caching on the client-side a username and password. This gives evil.ru a better crack at it - even the most basic of XSS vulnerabilities could result in the client beaming his username and password to an evil server. You could try to alleviate this risk by hashing and salting the password, but remember: JavaScript Crypto is Hopeless. You could alleviate this risk by leaving it up to the Browser's Basic Auth support, but.. ugly as sin, as mentioned earlier.
HTTP Digest Auth
Is Digest authentication possible with jQuery?
A more "secure" auth, this is a request/response hash challenge. Except JavaScript Crypto is Hopeless, so it only works over SSL and you still have to cache the username and password on the client side, making it more complicated than HTTP Basic Auth but no more secure.
Query Authentication with Additional Signature Parameters.
Another more "secure" auth, where you encrypt your parameters with nonce and timing data (to protect against repeat and timing attacks) and send the. One of the best examples of this is the OAuth 1.0 protocol, which is, as far as I know, a pretty stonking way to implement authentication on a REST server.
https://www.rfc-editor.org/rfc/rfc5849
Oh, but there aren't any OAuth 1.0 clients for JavaScript. Why?
JavaScript Crypto is Hopeless, remember. JavaScript can't participate in OAuth 1.0 without SSL, and you still have to store the client's username and password locally - which puts this in the same category as Digest Auth - it's more complicated than HTTP Basic Auth but it's no more secure.
Token
The user sends a username and password, and in exchange gets a token that can be used to authenticate requests.
This is marginally more secure than HTTP Basic Auth, because as soon as the username/password transaction is complete you can discard the sensitive data. It's also less RESTful, as tokens constitute "state" and make the server implementation more complicated.
SSL Still
The rub though, is that you still have to send that initial username and password to get a token. Sensitive information still touches your compromisable JavaScript.
To protect your user's credentials, you still need to keep attackers out of your JavaScript, and you still need to send a username and password over the wire. SSL Required.
Token Expiry
It's common to enforce token policies like "hey, when this token has been around too long, discard it and make the user authenticate again." or "I'm pretty sure that the only IP address allowed to use this token is XXX.XXX.XXX.XXX". Many of these policies are pretty good ideas.
Firesheeping
However, using a token Without SSL is still vulnerable to an attack called 'sidejacking': http://codebutler.github.io/firesheep/
The attacker doesn't get your user's credentials, but they can still pretend to be your user, which can be pretty bad.
tl;dr: Sending unencrypted tokens over the wire means that attackers can easily nab those tokens and pretend to be your user. FireSheep is a program that makes this very easy.
A Separate, More Secure Zone
The larger the application that you're running, the harder it is to absolutely ensure that they won't be able to inject some code that changes how you process sensitive data. Do you absolutely trust your CDN? Your advertisers? Your own code base?
Common for credit card details and less common for username and password - some implementers keep 'sensitive data entry' on a separate page from the rest of their application, a page that can be tightly controlled and locked down as best as possible, preferably one that is difficult to phish users with.
Cookie (just means Token)
It is possible (and common) to put the authentication token in a cookie. This doesn't change any of the properties of auth with the token, it's more of a convenience thing. All of the previous arguments still apply.
Session (still just means Token)
Session Auth is just Token authentication, but with a few differences that make it seem like a slightly different thing:
Users start with an unauthenticated token.
The backend maintains a 'state' object that is tied to a user's token.
The token is provided in a cookie.
The application environment abstracts the details away from you.
Aside from that, though, it's no different from Token Auth, really.
This wanders even further from a RESTful implementation - with state objects you're going further and further down the path of plain ol' RPC on a stateful server.
OAuth 2.0
OAuth 2.0 looks at the problem of "How does Software A give Software B access to User X's data without Software B having access to User X's login credentials."
The implementation is very much just a standard way for a user to get a token, and then for a third party service to go "yep, this user and this token match, and you can get some of their data from us now."
Fundamentally, though, OAuth 2.0 is just a token protocol. It exhibits the same properties as other token protocols - you still need SSL to protect those tokens - it just changes up how those tokens are generated.
There are two ways that OAuth 2.0 can help you:
Providing Authentication/Information to Others
Getting Authentication/Information from Others
But when it comes down to it, you're just... using tokens.
Back to your question
So, the question that you're asking is "should I store my token in a cookie and have my environment's automatic session management take care of the details, or should I store my token in Javascript and handle those details myself?"
And the answer is: do whatever makes you happy.
The thing about automatic session management, though, is that there's a lot of magic happening behind the scenes for you. Often it's nicer to be in control of those details yourself.
I am 21 so SSL is yes
The other answer is: Use https for everything or brigands will steal your users' passwords and tokens.
You can increase security in authentication process by using JWT (JSON Web Tokens) and SSL/HTTPS.
The Basic Auth / Session ID can be stolen via:
MITM attack (Man-In-The-Middle) - without SSL/HTTPS
An intruder gaining access to a user's computer
XSS
By using JWT you're encrypting the user's authentication details and storing in the client, and sending it along with every request to the API, where the server/API validates the token. It can't be decrypted/read without the private key (which the server/API stores secretly) Read update.
The new (more secure) flow would be:
Login
User logs in and sends login credentials to API (over SSL/HTTPS)
API receives login credentials
If valid:
Register a new session in the database Read update
Encrypt User ID, Session ID, IP address, timestamp, etc. in a JWT with a private key.
API sends the JWT token back to the client (over SSL/HTTPS)
Client receives the JWT token and stores in localStorage/cookie
Every request to API
User sends a HTTP request to API (over SSL/HTTPS) with the stored JWT token in the HTTP header
API reads HTTP header and decrypts JWT token with its private key
API validates the JWT token, matches the IP address from the HTTP request with the one in the JWT token and checks if session has expired
If valid:
Return response with requested content
If invalid:
Throw exception (403 / 401)
Flag intrusion in the system
Send a warning email to the user.
Updated 30.07.15:
JWT payload/claims can actually be read without the private key (secret) and it's not secure to store it in localStorage. I'm sorry about these false statements. However they seem to be working on a JWE standard (JSON Web Encryption).
I implemented this by storing claims (userID, exp) in a JWT, signed it with a private key (secret) the API/backend only knows about and stored it as a secure HttpOnly cookie on the client. That way it cannot be read via XSS and cannot be manipulated, otherwise the JWT fails signature verification. Also by using a secure HttpOnly cookie, you're making sure that the cookie is sent only via HTTP requests (not accessible to script) and only sent via secure connection (HTTPS).
Updated 17.07.16:
JWTs are by nature stateless. That means they invalidate/expire themselves. By adding the SessionID in the token's claims you're making it stateful, because its validity doesn't now only depend on signature verification and expiry date, it also depends on the session state on the server. However the upside is you can invalidate tokens/sessions easily, which you couldn't before with stateless JWTs.
I would go for the second, the token system.
Did you know about ember-auth or ember-simple-auth? They both use the token based system, like ember-simple-auth states:
A lightweight and unobtrusive library for implementing token based
authentication in Ember.js applications.
http://ember-simple-auth.simplabs.com
They have session management, and are easy to plug into existing projects too.
There is also an Ember App Kit example version of ember-simple-auth: Working example of ember-app-kit using ember-simple-auth for OAuth2 authentication.

How to restrict access to HTTP API for mobile applications?

I'm currently developing an API for an online service.
I would like to give access for mobile and web developers to create their applications.
Developers will have the usual number reqs/minute limits for their applications.
What are the best practices for authenticating applications?
For web applications it's easy. We provide token, token is valid for a domain so even if somebody will try to use anywhere else it will fail.
How to do that for mobile applications?
We can provide token. Such token needs to be distributed with application on the device
and means that somebody will sniff that token he can write another application that will use the same token. This will mean that original user will have to revoke old token, create a new one and release new version (that his users will have to download again).
Do you know any solution for that?
I'm not sure that your developers would be able to securely do this without having some form of communication with their own host and some form of user account on their system. As you said, if you included a long-lived token in an app, no matter what obfuscation is done it could eventually be discovered by reverse engineering techniques.
There are 2 options that I can see:
1. Short lived token
In this scheme the mobile application contacts the developer's system to receive an short auth token.
During enrollment and periodically thereafter, developers generate a public-private keypair and give you the public key.
Each auth token would need to include an unencrypted "developer key ID" of some sort and an encrypted bit of data including the token's issue data and a salt of pseudo-random data. The developer's host would encrypt the data using a private key in a public-private keypair. This keeps the secret in a controlled and secure space. The encrypted data needs to include the salt in order to prevent known-plaintext attacks on your developers' keys.
The app sends the token to you, you can determine it's legitimacy by:
Use the unencrypted developer key ID to determine which key to use in decrypting the encrypted string.
Has the developer key ID been revoked or expired? (due to key compromise, dev API subscription expiration or abuse, etc). If it was revoked, deny access.
Does the encrypted data in the token decrypt correctly? If not, deny access.
Has the token expired? (based on the encrypted token date) If so, tell the client to get a new token from the dev server. Their software should do this before contacting your API, but you have to check just in case. I'd suggest that tokens be allowed to live for a relatively short time since copying a token between apps is a weakness.
Allow access
You could also use symmetric encryption instead of public-private key encryption, but then you and the dev both know the secret. It'd be more secure if only the dev knows it.
2. Pass API calls through dev host
It'd be possible for mobile applications to talk to their developer's host instead of your host for calls to the API. When the dev host receives one of the calls, it simply passes the call through to your API and adds their secret token.

Resources