I’m building an API to power a site as well as making an app available, though this is my first API and I’m finding a few problem areas and would like some advice/tips where possible.
I plan on making the external API use a username/password and API key for authentication, however, I don’t really want the internal API to have either of these. This is because I would like to possibly distribute the scripts in future and don’t want someone to find any access codes that are used to access the internal API, where they could instead use these access codes to access the external API (of any site using the script).
Ideally I would like to put both APIs together to make managing them easier.
For securing direct access to the API so that no one can try to include it directly (in .htaccess):
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^.*$ - [R=401,L]
I gather for accessing the external API, one would need to do the following (in PHP):
$url = "http://www.mydomain.com/script/api.php";
$username = "username";
$password = "password";
$apikey = "12345678901234567890";
$postfields = array();
$postfields["username"] = $username;
$postfields["password"] = md5($password);
$postfields["apikey"] = md5($apikey);
$postfields["action"] = "getclients";
$postfields["format"] = "json";
$query_string = "";
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$jsondata = curl_exec($ch);
if (curl_error($ch)) die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
curl_close($ch);
$array_out = json_decode($jsondata);
However, I’m unsure (exactly) on the best way to include the internal API within my backend – I had thought that perhaps I could do the following (in PHP):
$postfields = array();
$postfields["action"] = "getclients";
$postfields["format"] = "json";
ob_start();
include("script/api.php");
$array_out = json_decode(ob_get_contents());
ob_end_flush();
However, since I’m sending the header header ("content-type: text/json charset=utf-8"); within the API, Firefox just wants me to save the output rather than pass it through. I’ve tried not sending the header, but then all the API variables get passed through the page where it has been included – which I don’t want.
My questions are:
- Is there a better way of getting the JSON output within PHP (internal access)?
- Is the .htaccess file adequate to protect the API from being included by 3rd party sites?
- Is the authentication for the external side adequate?
- Is access to the internal API the right way to do it, if I plan on distributing the scripts?
Many thanks in advance!
In your
.htaccess,[OR]doesn’t work the way I think your using it. AllRewriteCondapply to the nextRewriteRule, so there’s no need for an ‘or’. Secondly, you also need rules to push API requests to some kind of dispatcher file, something like:I don’t think it makes sense to call your API functions internally through cURL etc — especially because you’d have to go through authentication etc. In my opinion it would make more sense to have a collection of (object oriented) ‘APIs’ internally that you can call directly, like
API::getClients(). Then build a dispatcher script which you push all incoming Ajax requests to. That script would do the following:Hope you catch my drift 🙂