Is this a good way to keep my API safe?

4

My application consists of a nodejs API in the backend but I'm also creating the Referencing implementation of a JavaScript client, which is a SPA in done with Backbone.

First, the API only accepts HTTPS requests, in case an HTTP HTTP arrives on the server it ignores it completely and optionally can invalidate the password used in that request .

My server does not save state (no session / cookies) and I only use basic HTTP authentication in , where I provide two ways to authenticate a request :

1- Submit credentials in header : Authentication: base64('Basic ' + nomeDeUsuario:senha)
2- Send a request authenticated with method 1 to GET /usuarios/atual that returns a token, which is an encrypted string * containing: nomeDeUsuario + '|' + dataDeExpiracaoDoToken . The client then sends the header Authentication: 'Token ' + base64(nomeDeUsuario:token) .

* Encryption made with OpenSSL's aes-256-ctr algorithm. The private key is the hash of the user's password.

The method 1 can be used for server-to-server communication, so it is not suitable for the JavaScript client, because for all requests the user would have to enter their credentials unless such credentials were stored in the browser memory, which I do not know if it is safe enough . In addition, storing the credentials in the local storage would keep the user logged in indefinitely.

Method 2 The JavaScript client sends only an authenticated request with basic authentication and immediately discards this sensitive login information, storing only the token in the local storage. After a certain time this token will expire and a revalidation will be needed, almost emulating a session on the server.

On the server side I check the authenticity of a request made with method 2 simply by getting the hash of the user's password and trying to decrypt the token, so I check tokenDescriptografado.split('|')[0] === username .

Is this a safe approach? Is there a point I'm not taking into account? Given this approach, what kind of attacks would I be subject to?

* This is a # of a question I asked in Information Security

    
asked by anonymous 09.12.2014 / 00:56

1 answer

4

There is a problem with your method 2: Suppose an attacker obtains a copy of your BD. Usually this would not be a catastrophe, since user passwords are hassled, but by method 2 the attacker could authenticate only with the hash:

  • Create a new token nomeDeUsuario + '|' + dataDeExpiracaoDoToken , with a recent expiration date;
  • Use this user's hash to encrypt the token, and send it. The server will accept authentication!
  • A safer method of generating tokens on the server without saving state is through a signature (or rather, an HMAC): save as safely as you can (eg a restricted access settings file, or a hardware module) a secret key known only to the server. Do not put this key in the DB. When a user accesses /usuarios/atual , create a token as it was doing (user name and expiration date), but instead of encrypting it with the hash of the user's password, sign it using this secret:

    HMAC(segredo, token)
    

    And send both to the user (the plain text token, and the token signature). When the user passes this data to the server, make sure the signature is intact (the user could change the user name or expiration date in the plain text token, but he could not falsify the signature without the server secret). Thus, an attacker with only access to the hash of the user's password could not authenticate using method 1, nor forge a token to be used in method 2.

    This would make your system more secure in a scenario like this, where the attacker has a copy of his BD but not his system as a whole (eg, a leak via SQL Injection, a copy of the database is obtained , but the configuration / hardware module files are still intact). And if these tokens have a short duration, it can be interesting to use a persistent secret, but to generate a random key in memory, only valid until the server is restarted (if there are multiple servers, load balancing for example, this may be less feasible).

        
    04.03.2015 / 02:31