SAFAD
SAFAD

Reputation: 784

Secure API Authentication method

We are working on a new project, we are two lead developers and got on a cross road on how to use a token to secure the communication between the server and the client :

First Suggestion :

Step one) the client requests a primary token, by sending the username and password and the current_time (this variable will be saved in the server's database and the client side too) to the api, the server interprets the input, and renders a hashed token (e.g. : 58f52c075aca5d3e07869598c4d66648) saves it in the database and returns it to the client.

Step Two) The client now saves the primary token, and creates new hashed token using the primary token + the current_time variable sent in the authentication request (lets call this new token, main_token) also the server does the same and create the same token using the same algorithm.

Step Three) Each time the client queries the server API, it sends the main_token to the server, now the server compares the token generated in it, with the main_token sent by the client, if it matches, it means the user is real

Second Suggestion :

Step One) The client generates two random keys ($key1 = rand(10000,90000); $key2 = rand(10000,90000);) On each request on the API, the client creates a hash using the query type, and the two keys with a complex algorithm, and sends these two keys + the hash to the server

Step Two) The server, using the same Algorithm used in the client, creates a hash, and compares is to the one sent by the client, if it matches, the server proceeds to deal with the query


Now, the question is, Which one is the most logical, and secure way to use for securing the api requests

Best Regards

Upvotes: 16

Views: 9738

Answers (4)

Jonathan
Jonathan

Reputation: 5864

Neither of the solutions has any benefit to security.

First suggestion

Once I have main_token, I can compute any hash(main_token + timestamp). All I need to access the API is the main_token, so why bother with the timestamp business?

Second suggestion

If you send the two random numbers with each request and the query type, then what is stopping me from doing the same and using your APIs? The algorithm? The rule with cryptography algorithms is if you roll your own, someone will crack it. Second rule is security by obscurity doesn't work.

If your authentication process is more secure than your api, you could protect the calls a different way:

Authentication phase (SSL)

  1. client sends user/password and gets a 'Secret_token' which is a random string.
  2. Secret_token is stored client side and server side.
  3. Secret_token is never transferred over the wire again.

API Request Phase

  1. client creates a request
  2. client normalizes request
  3. client calculates a signature* of the normalized request using Secret_token
  4. client sends the request + signature to server
  5. server normalizes request
  6. server calculates a signature of the normalized request using the Secret_token
  7. if signatures match, server proceeds with request

Calculate a signature

First, normalize the request. This might mean extracting the important parameters including method (post,get,action,timestamp) and putting them in order. Then running that string through HMAC algorithm which takes the Secret_token as a parameter.

Analysis

The Secret_token is only transferred over the wire one time when the authentication happens. It's assumed the authentication process is very secure (as the password is transferred during this process, it's a safe assumption).

Note: still not safe to send over plaintext, use SSL.

HMAC is a well known solution. See:

Upvotes: 12

anfab
anfab

Reputation: 1636

First some observations

  1. In the first approach, the token essentially becomes a long living password. It is reused with every request. So, if this token is compromised, you are done. Not to say that is discouraged, since OAuth 2 does exactly that, but SSL is absolutely mandatory here. Also if you go with this you'll have to ensure that the tokens have an expiry date and a mechanism to ensure swift revoking of tokens in case there is a compromise.

  2. The second option you describe is similar to what AWS uses but without a secret key. The advantage here is that since it generates a hash using the query the hash will change with every request. So if one token is compromised, you don't have to worry since it won't work with any other request. Additionally, you can always detect man in the middle attacks with this approach since the algorithm will generate a mismatching hash if the content is modified.

Both of the approaches are valid and widely used. So, if you don't want SSL then 2 is the way to go. If you are fine with SSL then OAuth is another option. What I'd recommend is actually going with the established techniques in either of them. If you are using 1) then look at Oauth2, if you're going with 2) then stick with AWS scheme (strictly speaking, this is not a standard but its widely documented).

Some links I think might be helpful

http://www.wolfe.id.au/2012/10/20/what-is-hmac-and-why-is-it-useful/

http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/

http://blog.cloudfoundry.com/2012/10/09/securing-restful-web-services-with-oauth2/

Upvotes: 5

James Holderness
James Holderness

Reputation: 23001

Why don't you use standard HTTP Auth on every request, so you are passing through the username and password every time. Then the server is just validating against that username/password combination rather than a token.

Given that you are using SSL/TLS for your connections, there's no risk of the username/password being exposed. And there's also no possibility of a replay attack on SSL so there is no need for expiring anything.

I'd recommend keeping it simple and using the existing protocols that have already been developed. When it comes to security, you probably shouldn't be trying to reinvent the wheel unless you have really compelling reason to do so.

Upvotes: 7

aet
aet

Reputation: 7292

Since the client has all of the info it needs to compute your second token in the First Suggestion, the second token is no better (safer, more secure) than the first token. The Second Suggestion seems to be some variation of pre-shared keys. Either of these could be adequate security measures. Personally, I would prefer an approach more like the first one, and use SSL all the time. Think of the token like a substitute for the username and password, would you send the token cleartext with every request? (Many sites do exactly this.)

Upvotes: 0

Related Questions