I'm developing an API service and I would like to allow the users to restrict access of their tokens by domain, so an API key can only be used from one site/domain/host (it could be a server calling the API, not necessarily a browser), like Google Maps API allows you to do.
Now my question is, how do I check which host/domain the request comes from - in PHP (Laravel) - so I can compare it to the allowed domain(s) or pattern?
Is $_SERVER['REMOTE_HOST'] the right variable to check? Or should I look at a request header? Like $_SERVER['HTTP_ORIGIN'] though that seems to be browser related and, if I'm not mistaken, another client (a server or Postman for instance) would not necessarily have the Origin header, while $_SERVER['HTTP_HOST'] is not required and can be faked.
Edit: just to be more specific, I don't think this additional check on the requesting domain is supposed to replace the access token for auth, but it is an additional layer of protection and helps with token management and misuse - a user might have multiple tokens for different clients/apps calling your API so this way you can discriminate the traffic.
If Google can do it I assume there is a way for implementing it. Could it be not possible in PHP? I don't know, but I was hoping somebody here could suggest a way to implement this check/restriction, maybe underlying the limitations of the proposed solution. Even if the solution is not 100% reliable (again it is not suppose to authenticate the client) it would still help improving protection - in fact Google considers it best practice to "protect" the API keys this way.
Related
I have built a simple read-only API for our database, so that users can retrieve data from our database.
For example, the URL "http://xxxxx/getAllProfiles" will return a JSON result containing all profiles stored in the database.
The API is read-only, it is only implemented with some 'select' SQL queries. Thus the user cannot modify any of the data in the database via the API.
My company worries the API will be exploited by some random bots online, and has been asking me to build a security mechanism for this API. (It is worried if there is no key or something that prevents anyone from accessing the URL, our server would be visited too much. It is a small server.)
What would be the simplest secure mechanism that I can implement, using PHP? (We are also using Slim for the API, Amazon EC2 server with Ubuntu and Apache running on it, if this helps.) Preferably it can be implemented without the use of any database on server or client side.
If there's anything not clear, please let me know, I'll clarify.
Thanks.
Add:
Thanks for the comments.
Is there a way to NOT use a database? Like a smart way to generate a key or something... I'm thinking I'll provide a page so that user can input the domain, and an algorithm will convert this domain to a key. Then, for each request, the user should include this key. The server will grab the domain from the request header and use the same algorithm to calculate again. If the two calculated key matches, the request is accepted. I think this, at a minimum level, ensures that at the beginning there must be someone to input the domain and get the key, thus filtering some random bots out?
I am not sure if this is secure (at all)? But it sounds to me like it can filter out something.
I posted this question when I know very little about web development.
There are many ways to secure a REST API, e.g. JWT, Cookie, Basic Auth, etc.
Back from the Symfony Live 2012 in Paris, where I luckily participate to "Designing HTTP Interfaces and RESTful Web Services" conference, I'v much questions on how to build a RESTful API while keeping it private and member only.
Currently I used to generate an API key to make my API private (I mean available to third-party application on my own but end-users).
To make sure signed up users can use the API (through mobile app) I use Cookie, well, I used SESSION.
But afaik, it is not the correct way to do, according to the talk (and other resources I read over the web).
My needs are the following:
Provides a private API which only my mobile app can use
Allows member (of different roles) to do different actions (ie: a Member can post a comment, while an Administrator can edit them all)
As REST constraints are Stateless (amongst others) I can't use Cookie/Session as they need to be initiated by the client and will result in some non-idempotent result.
I read here and there that a way to keep my API RESTful is to provide on each request the credential.
Currently, to authenticate my API key (to keep it private) I use a custom HTTP Authorization scheme, something like Authorization: MyApp SoMeToKeNV3RYPR!V4T3 and then authenticate my member (login) with a POST method (as I would do in any browser web application).
How would you implement such cases? Is it acceptable to use such private scheme and keep using sessions?
After some reading I may think that working with some Signature over each requests can help to solve such problems.
The signature may be generated using the user credential provided in the third-party client while encrypting it with a public/private key (to keep the API private).
On each request, the signature will be checked against a CRC (or something like that) while the credential will be against a database (it doesn't seem worth than checking for a session, does it?)
Any help/advices would be appreciated.
PS: What about OAuth? I don't know much about it, but may it be a solution to such problem?
You're definitely going to want to use OAuth. This will allow you to securely authenticate that your users are who they say they are. No messing with CRCs or anything is needed on your end, once a user is authenticated they have an access token they can use to sign future requests.
You would just need to handle the authentication scheme and handshake and then securely store the access tokens once they have been given out. However, if it were me I would not trust myself to handle all of the secure cases when designing such a system. There are a couple of third party PaaS companies that will do this type of thing for you. I know of the following companies which have some API management tools that will probably help you, and afaik they handle OAuth implementations as well:
Apigee
Layer 7
Ping Identity
If you are so concerned about security though that you don't trust a third party to handle it for you you are going to want to follow the OAuth protocol.
I wrote a Web Application and I would like to allow other developers to get the information from it.
The server Im working on is not that awsome and cant handle that many request, so the idea is to generate and assign api keys to everyone that wants to query our information. With Api keys I can limit the daily requests and perhaps collect some statistics to see what information is really useful for the other developers.
The thing is, Im concerned about the security aspect of it. Since the Api key is going to be sent to our server (via GET/POST etc), someone could sniff the request with wireshark and get the developers API key without much effort, right?
I thought about generating a secret key and an API key. I could then instruct the other developers to concatenate them and send a hash of it to our API. I would then validate that the hash is valid and allow the request... But then the same problem would persist. A hacker could still sniff that hash and make requests on behalf of the other developer's app.
So my questions are
How can I avoid this problem?
Or better yet, Is my concern even valid? Is that a real problem?
Is there a better and secure way to allow access to my information without making it too complicated for the other developers?
What do you guys think?
I think you're trying to solve a bunch of different questions here.
If your objective is to limit the number of requests to your server, you should create a throttling mechanism. This is non-trivial, but I'd base it on IP address rather than a license key - a single licensed user might swamp your system with lots of requests. You can throttle by IP address without implementing a license mechanism.
If you want to create a licensing scheme, you need to understand cryptography etc. - it's a non-trivial problem. For instance, how do you stop a legitimate user sharing their license key with all their friends? How do you stop a hacker from stealing your key and sharing it with all of his friends?
There are a number of solutions to this - they all impose some degree of pain on your users. For instance, you can run your service on HTTPS; this stops snooping, but reduces performance. You can issue "tokens" for your service which expire after a certain number of uses; getting new tokens requires a cryptographic exchange (which might check your IP address). You might require a "challenge/response" type of logic (including an IP address validation). All these steps make life harder for your users; they probably won't thank you much for the extra work they have to do.
With respect to sniff, your problem can be solved with HTTPS on your server.
it definitely makes sense to put some authentication on the API if you want to limit access + potential some usage rate limits. If you use an API key and want to avoid sniffing then HTTPS is definitely the way to go. If that's not an option then you can also use a hash-style auth like oAuth 1.0 (http://oauth.net/core/1.0/) or Amazon AWS authentication. These work by issuing your API users with an ID and a Secret. They use the secret on the client side by inserting it into the message body, computing a hash and including the hash (not the secret) in the request. On the incoming side you compare the hash with the same operation done on the message content with their specific secret included.
This means that you can verify the sender without having to send the secret over the wire (note that the content still isn't secure - but you avoid passing the key over the wire with every request). The downside is that it's complex for developers to implement. Even if you use the oAuth 1.0 pattern which there are libraries for it's a bit of an overhead.
I work at 3scale and some of our tools might be helpful also - our systems provide API Keys, oAuth Secret sharing and also API rate limits out of the box (http://www.3scale.net and the PHP libraries are here: https://github.com/3scale/3scale_ws_api_for_php).
I want to build an API for users to build applications that easily interact with a site, and I was wondering what the best way to authenticate users would be.
Taking a look at other API's a lot of them have the user send the username and password as a GET parameter over a HTTPS connection. Is this the best way to go about it? Or are there other methods that I should look into or consider?
I've seen OAuth been tossed around and it looks like a good solution, but just for a simple API is it overkill?
You can use API key's. Generate a unique hash tied to an account upon request. Then check that the key is a valid key. As long as the API doesn't have any major security issues with someone using someone else's key then Authorization isn't needed. If there is a problem with someone using someone else's key then Authentication would be justified.
This is usually achieved with cookies.
The client sends their username and password with a POST request to your API (do not use GET, that's insecure). If the credentials are acceptable, then generate a random, unique session key, store it on your side and send it in a cookie back to the client (see setcookie()).
When the client now makes further requests, they send the session key cookie with the request. Check $_COOKIE for the session key if it matches a stored key on your side; if yes, that means the user authenticated.
Take note that this minimal example is vulnerable to brute-force attacks trying to guess valid session keys. You need to log invalid keys that clients send in their cookies and block their IP address for some period of time to prevent this.
Username / password in a GET isn't a great way to do this because you're potentially exposing the whole user account for hijacking even if the API has more limited functionality than logging into the site. So it's good practice to separate concerns between Web-site login and API access.
I'm not sure which case you're in but:
If the users are business customers of somekind who are embedding some type of widget or code in another website then it's probably best to use an API key which is scoped to the referrer domain (much like Google Maps does).
If they are end-users who won't know anything about the API but are going to be using Apps built by third parties then oAuth is likely to be your best bet, otherwise your users might literally be giving their usernames/passwords to unknown third parties. It's more complex but likely to be worth it in the long run.
To get a bunch of this stuff out of the box you can use something like 3scale (http://www.3scale.net) and it'll handle most of it for you (disclaimer, I work there so adjust for bias!) or there are open source libraries for oAuth in most languages (in PHP Zend-OAuth component might do the job for you).
I want to make nice and clean api; I'm making site and I want to offer the ability to mobile apps use web API of my site.
I don't want to use oAuth, becouse the mobile and embedded applications that are facing the biggest hurdle, as they may not be able to bring up and/or control the web browser. Also its a little complicate.
I know, that HTTP basic authorisation is not safe, but it's so simple... I want to use it in my api.
I have somee users logins and their passwords (md5-encoded) in mysql base, but how to use those data in this HTTP basic authorisation?
Generate a random unique string for each user in your database and make that string available to the end users. When they access the api ask them to enter that unique string that you supplied--this is their 'key'. Each time a users app accesses the api they pass the key which links directly to a unique account and that is how you authorize them. It is essentially user name and password all in one.
While the above example is generic you should also take things like security into account--for example, when possible, pass the device ID from the mobile along and use that during authentication, or use their current password hash during their API key generation so if they change their password the key will stop working and they have to get a new one--this way they can control access if their key is lost.
It doesn't have to be complicated, it just has to be safe. =)
The PHP manual has an example
Jus google your question "PHP HTTP basic" and here you are
http://php.net/manual/en/features.http-auth.php
it is as simple as sending a few HTTP headers.
Also note that digest authorization considered to be more safe but less compatible with clients.