I am looking to improve the security of an existing REST API accessed over SSL. The web service is multi-tenant, such that each tenant has an assigned TenantId.
The problem I facing can be summarized as:
- How can I determine the tenant?
- How can I determine the client is legitimate?
- Is HTTP cookie based security suitable for the task, or should I consider token based?
Currently
Currently we manually issue (i.e. out of process - over the telephone, etc) an API key to each client, which they include as an HTTP Header in each request. This API key maps to a TenantId. When the client sends a login request to the REST API, we then determine the TenantId, which in turn allows us to check the username/password in the correct tenant database. Once that is successful we issue a time-limited HTTP cookie. That cookie is then used on subsequent REST requests. Internally, that cookie is linked to a session and the session contains user profile information to reduce db load.
We are aware that this has some inherent security risks. The API key could be easily extracted from disassembled client source code. We also intend to build our own client as a SPA in JavaScript which is readable to anyone. Although we can revoke/change keys I'm looking for a more secure standardized implementation.
Alternative
As I understand it I could use a token based alternative to cookies. HMAC is a common authentication mechanism for web applications, but this requires the storage of a shared secret in the client and server. This secret appears to have the same problem as the API key above; in that it can be leaked.
I've also read a little about JWT, which seem to extend the HMAC concept in that the server can persist user "session" data in the token, reducing the number of database calls for user/profile information. The JWT token is used as a result of a successful username/password login. Thus there is no shared secret problem here correct?
I've also read a bit about OAuth2, specifically the Resource Owner Password Credentials Grant. I'm not even sure though whether OAuth2 solves my problem.
Determining the tenant
The first step is determining the tenant. Rather than using the API key to map to a TenantId, I could either:
- Ask for the TenantId as part of the login request
- Use a subdomain mapping to map to the TenantId
Validating the application caller
I secondly need to determine whether or not a given client application is allowed to access the REST API. On this part, I am well and truly out of bright ideas. Is that where OAuth2 comes to the rescue?
The only way I can think to resolve this is to issue the calling application with a temporary expiring API key after the user has logged in. Whilst it doesn't guarantee that the application isn't rogue, it does reduce the risk to an attacker who has also gained access to a user's credentials.
Is my current HTTP cookie solution acceptable? Do I need to move to a token based authentication mechanism instead?
I welcome any advice you might have. I'm wading through masses of information and trying to get my head around this all. Any guidance would be happily received!