REST API authentication with query string encryption - api

I am building a web application that provides an API as it's primary function. I have been looking into methods for authentication but have been struggling to make a decision on what to use.
Since this will be a paid service and the API is the service, I need to make it as easy to use as possible so as not to put people off but obviously I want it to be secure. I have considered using HTTP basic authentication over SSL but would like to avoid the costs/overheads/hassle of SSL if possible early on and maybe provide it as an option later.
I like the AWS style API authentication (see here) but the problem is I can't have users sending the query string as plain text along with a signature because the parameters may contain things like phone numbers which I think customers would rather not expose. I have thought about providing a secret key to encrypt the string which is sent along with an api key to identify the user.
What do you think the best option is to also encrypt the query string along with the request while maintaining simplicity?

Use HTTPS. It's simple, supported by almost all client libraries, trusted, secure, and it protects the URL and payload.

Related

Authenticating Requests From A Single Server

I'm working on a project which contains data belonging to multiple clients, and I'm trying to find a secure way to notify their servers of certain sensitive changes to their data.
The issue is that the most secure method I found for this is OAuth, but since my server will be pushing the updates to them, that would mean that each client would have to implement an OAuth provider solely to authenticate my server, and it feels like a bit of an overkill.
My question is: Keeping in mind that not all clients will use HTTPS, would it be enough to simply use a shared secret, a timestamp, and some form of encryption for their servers to safely receive and validate my updates or will that leave them vulnerable to attacks?
Yes, that would be secure. For simple messages I think JTW would be a very good choice. You could use it for just authentication or the actual notification itself. A few reasons you might want to use it:
It's signed, so you know the message hasn't been tampered with.
You can encrypt with public/private key pairs.
You can add any data you like.
It's very simple to implement and doesn't require back-and forth exchange between servers like OAuth often does.

How to restrict API endpoint access to certain clients?

I'm building an API using the Django Rest Framework.
I've looked at a whole bunch of documentation, however I can't seem to answer this:
How can I restrict my API such that only my iOS client can register users / log them in?
I understand that I can use OAuth2 or Token Authentication for additional endpoints. But for unauthenticated requests, is there any way of restricting them?
There's no truly secure way to guarantee requests are coming from a specific device. Checking headers seems like the best way, as mentioned by #dukebody, but should be considered as a "good enough" solution for most users.
I'd also question why you want to do this. APIs generally shouldn't be restricted to certain devices because it makes them less extensible. Moreover, REST/HTTP services should return the same result regardless of the client device; otherwise, you will cause headaches when dealing with caches and proxies between clients and your service.
If you are trying to format content specifically for iOS, you'd be better off adding a specific parameter like ?format=ios without checking headers, then just make sure your iOS client uses that param. That would be more in the spirit of REST and make things easier to cache as well as test.
I also encounter this issue.I would like to provide some of my thought.
My team would need to support some APIs with heavy operation and it would be open to unauthenticated users which is design by business logic.
That's why we need to restrict api requests to our app clients.
The API call is stateless and irrelative with caching and proxies.
In the other hand, some malicious attack like CSRF, you should also provide some additional protection on you API to prevent request sending from untrusted way.
There are several mechanism we considered.
Using HTTP header
This is untrusted and very easy to crack.
Use one static random generated API Key
Very common and easy-implementation way. Server generated one static random string as key and client must carry when sending request.
If you have to support web, this would be leak by web console.But if you only support app client and restrict your API connection with HTTPs. This should be safe enough.
Dynamic change API key with AES crypto algorithm
To prevent MITM or static API key is leak, I proposed to use AES crypto algorithm and encrypt current timestamp.
When server receive, decrypt and check whether the request is valid or not.
You can also append some string as salt to make the mechanism harder to brute force attack.
You can do as much effort to make it harder to crack, but it would never be absolutely 100% safe.
Hackers can still reverse engineer your app to see how the encryption works.
All you can do is making it harder.
This is my propose and hope it could inspire you.
If you have any other better solutions or find some bug in my proposal, please let me know.
Restrict the views to the user agent of the iOS client, checking the headers. See https://stackoverflow.com/a/4617648/356729

Using GET method in RESTful API where authentication is required

I am building an API following RESTful principles as much as possible. The request in discussion is to allow a user to check his/her credits available in a system. At the point of request, the system verifies the user by comparing the provided username and password already in the system. Please note that changing the authentication method (to OAuth or the like) is not an option at the moment.
As this is a "Read" request, GET method is used. So, I would have the following:
GET http://mydomain.com/credit?username=XYZ&password=123
By following the RESTful principle and using the verb properly I fear that the username and password is easily readable / accessible. In a non-API scenario I would have just used a normal form POST with SSL...
Am I wrong to assume the risk mentioned above?
You are quite correct that exposing the username and password in plain text in the query string is a bad idea. Like worse than the last three Star Wars movies.
You should be fine though if the same request is made over SSL (assuming a trusted certificate).
REST also has a host of other mechanisms for security like the DOSETA specifications for digital signatures, JSON Web Signature and Encryption, and so on. But you seemed to hint those kinds of things aren't an option.
The Http Authentication header is designed to store information such as username and password. You should use that.

How exactly to implement challenge-response for REST API authentication?

I want my REST API server to be able to communicate only with my iOS app. The user base is going to be no more than 1000 people, and the market is pretty small and unpopular in general. That's why I think anything beyond a simple challenge-response authentication (HTTP, OAuth 2.0, SSL) would be an overkill. But I'm not sure exactly how this auth should flow. Here is what I have in mind:
Client app (user) sends a request: api.example.com/auth?username=john
Server responds with a randomly generated string: "somerandomlygeneratedstring"
Client takes the string, appends it to the username and then appends a secret string, hard coded in the app and uses MD5 to hash the entire string.
Client passes the string to the server: api.example.com/auth?username=john&response=thenewMD5hashstring
Server generates the same MD5 hash string and if they match, marks this user as authenticated in the database and all API requests from this user will be handled from now on.
Do I have the right idea? Or am I totally wrong? Please have in mind, I want basic security, anything too fancy would be an overkill for such a small project.
Also, I'm not keeping any sensitive data on my database like personal information.
You should simply use HTTP Basic auth for every request, through the Authorization header, and have all your interactions over SSL. If you want basic security, there's no need to go beyond that.
There are several problems with the scheme you have in mind.
Your last step is essentially a server-side session, which isn't acceptable in REST.
MD5 is effectively broken and shouldn't be used for anything but integrity checking.
In REST, you should use the standardized authentication method provided by the protocol if it fits your needs. Reinventing it to use URI parameters like you have in mind is unnecessary.
The hashing scheme you have in mind only makes sense when you want to sign the request, guaranteeing it wasn't tampered with.

Clarification on HMAC authentication with WCF

I have been following a couple of articles regarding RESTful web services with WCF and more specifically, how to go about authentication in these. The main article I have been referencing is Aaron Skonnard's RESTful Web Services with WCF 3.5. Another one that specifically deals with HMAC authentication is Itai Goldstiens article which is based on Skonnards article.
I am confused about the "User Key" that is referenced to in both articles. I have a client application that is going to require a user to have both a user name and password.
Does this then mean that the key I use to initialise the
System.Security.Cryptography.HMACMD5 class is simply the users
password?
Given the method used to create the Mac in Itai's article
(shown below), am I right is thinking that key is the users
password and text is the string we are using confirm that the
details are in fact correct?
public static string EncodeText(byte[] key, string text, Encoding encoding)
{
HMACMD5 hmacMD5 = new HMACMD5(key);
byte[] textBytes = encoding.GetBytes(text);
byte[] encodedTextBytes =
hmacMD5.ComputeHash(textBytes);
string encodedText =
Convert.ToBase64String(encodedTextBytes);
return encodedText;
}
In my example, the text parameter would be a combination of request uri, a shared secret and timestamp (which will be available as a request header and used to prevent replay attacks).
Is this form of authentication decent? I've come across another thread here that suggests that the method defined in the articles above is "..a (sic) ugly hack." The author doesn't suggest why, but it is discouraging given that I've spent a few hours reading about this and getting it working. However, it's worth noting that the accepted answer on this question talks about a custom HMAC authorisation scheme so it is possible the ugly hack reference is simply the implementation of it rather than the use of HMAC algorithms themselves.
The diagram below if from the wikipedia article on Message Authentication Code. I feel like this should be a secure way to go, but I just want to make sure I understand it's use correctly and also make sure this isn't simply some dated mechanism that has been surpassed by something much better.
The key can be the user's password, but you absolutely should not do this.
First - the key has an optimal length equal to the size of the output hash, and a user's password will rarely be equal to that.
Second, there will never be enough randomness (entropy to use the technical term) in those bytes to be an adequate key.
Third, although you're preventing replay attacks, you're allowing anyone potentially to sign any kind of request, assuming they can also get hold of the shared secret (is that broadcast by the server at some point or is it derived only on the client and server? If broadcast, a man-in-the-middle attack can easily grab and store that - height of paranoia, yes, but I think you should think about it) unless the user changes their password.
Fourth - stop using HMACMD5 - use HMAC-SHA-256 as a minimum.
This key should at the very least be a series of bytes that are generated from the user's password - typically using something like PBKDF2 - however you should also include something transitory that is session-based and which, ideally, can't be known by an attacker.
That said, a lot of people might tell you that I'm being far too paranoid.
Personally I know I'm not an expert in authentication - it's a very delicate balancing act - so I rely on peer-reviewed and proven technologies. SSL (in this case authentication via client certificates), for example, might have it's weaknesses, but most people use it and if one of my systems gets exploited because of an SSL weakness, it's not going to be my fault. However if an exploit occurs because of some weakness that I wasn't clever enough to identify? I'd kick myself out of the front door.
Indidentally, for my rest services I now use SCRAM for authentication, using SHA512 and 512 bits of random salt for the stretching operation (many people will say that's excessive, but I won't have to change it for a while!), and then use a secure token (signed with an HMAC and encrypted with AES) derived from the authentication and other server-only-known information to persist an authenticated session. The token is stateless in the same way that Asp.Net forms authentication cookies are.
The password exchange works very well indeed, is secure even without SSL (in protecting the password) and has the added advantage of authenticating both client and server. The session persistence can be tuned based on the site and client - the token carries its own expiry and absolute expiry values within it, and these can be tuned easily. By encrypting client ID information into that token as well, it's possible to prevent duplication on to another machine by simply comparing the decrypted values from the client-supplied values. Only thing about that is watching out for IP address information, yes it can be spoofed but, primarily, you have to consider legitimate users on roaming networks.