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.
Related
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.
After building a fairly simple API, I started looking into authentication where the basic HTTP authentication over SSL with just a username/password combination may appear weak for someone using it, although various discussions on here suggest it should be fine.
As this is the case, I looked into the API's from similar solutions which provide their users with a user ID and an API Key instead. The problem is I don't see how this is any stronger at all. I assume the Key is still saved just the same as a password, where from my perspective it just looks like they are calling a password a key.
Example:
https://github.com/Arie/serveme/blob/master/spec/fixtures/vcr/HiperzServer/_restart/visits_the_Hiperz_restart_URL.yml
How does the &api_key=hiperz_api_key&gs_id=3873 args offer any further security than just a username password? I would definitely like to implement something stronger than just user/pass over basic HTTP authentication and provide the end user with some type of token/key to use for access, but I am failing to see the additional strength from such approaches.
Well, there is always 2 step authentication which can be done(either by sending a message to their phone .. or maybe giving each user a randomly generated code to fill). Also, you can create your own encryption mechanism and add it to the functionality of your webpages. For example, you can encrypt the data using your own made up encryption key and then when it reaches where you want it you only know the key so you can de-crypt it.
Basic authentication is not recommended to protect APIs as I tried to explain in my answer here.
You are correct that using a client id and client secret is very similar to username and password authentication. The difference is that in the latter case you authenticate the user (a person), where in the former you authenticate the client (an application).
Whether you want to secure your API with a client id and secret depends on whether you can trust the client to keep them secret.
Either way, whether you have a trusted client, like a web application (living on a secured server) or an untrusted client like a JavaScript application or mobile application (living in the user's realm), token based authentication schemes (like OAuth2) provide a more secure way to protect your API than basic authentication. See my answer here for more information on the different ways to get tokens using OAuth 2.0
I am learning API's at the moment as well. My understanding is that by using an API key you can have more control over what permissions the user has. Also the API key can be reinvoked at any time as well. Also it will save the customer time from inputing log in details on each use of the API. I am not sure if that answered your question or not.
im not sure of which way to take with a REST API im currently developing using CakePHP, i haven't implemented authentication and until now that im almost done with it i'm reading about it,
but i'm not sure of what should i do, this API would be exposed so that a webpage and a mobile app can consume it, but i dont think Basic auth or Digest auth (which come as default options in CakePHP) are the option,
i only know that i need it to check username and password from the database, and grant permission according to an ACL that is already set up, i was reading something about HMAC but dont understand it completely, should i make an authentication method on my own that does something like check a token? is this article correct? : http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/
and if so, how do i implement those principles to the CakePHP auth method? is there a plugin for this auth method using HMAC?
should i use OAuth 2.0? does it make sense to use OAuth 2.0 for a username & password login? am i too lost? if im not so lost, could you please describe how to implement OAuth with username and password in cakephp?
someone, please, anyone surfing this interweb forum, HELP ME. if you could provide examples or workflows, anything, everything will be greatly appreciated.
How much security do you need? As an API is usually accessed from a client app which has the keys, it's usually OK to send the credentials along with every (https) request (as POST parameters, so they'll be encrypted). At least, this is by far the easiest solution: You just check the credentials with every request, without any sessions, tokens and the like. If the credentials are valid, you check whether that now authenticated 'user' is authorized to access the requested resource(s).
Remember that more advanced authentication/authorization methods quickly become complex in development and management. If you don't have any experience in implementing such systems, it's rather likely you're obsoleting the possible security gain with implementation bugs/issues.
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.