Reputation: 784
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 :
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
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
Reputation: 5864
Neither of the solutions has any benefit to security.
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?
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.
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.
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
Reputation: 1636
First some observations
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.
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
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
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