Setting up a RESTful web service - php

I'm just getting into using REST and have started building my first app following this design model. From what I can gather the idea is to build your service like an api which your website itself is a consumer of.
This makes sense for me since my web app does a lot of AJAX calls, however it seems a little wasteful to authenticate each request to avoid using sessions. Is this just something I have to accept as part of the REST design process?
Also, making ajax calls works fine, but say, I need to just show a view of the users profile, does this now mean I also need to make a curl call to my api to pull this data. At this point I know I'm working internally so is authentication even required?

Some remarks:
While you could set up your whole application to have a REST interface, you should set it up to still be able to call it internally. Calling it from HTTP, and getting results back by HTTP is only input-processing, and output-rendering. So, if you seperate those concerns you get a flow: input-processing -> method call -> data return -> data rendering. Shaving of the first & last bit, what do you have left? A function call that returns data, which you can just use in your code. Seperate functionality to translate an 'outside' function call into an 'internal' one, and render 'internal' data into 'external' (xml, json, html, whatever you desire), makes your app efficient, and still fully REST capable.
Authentication is needed if you allow outside calls, even if you don't 'tell' other users data can be retrieved a certain way, it is still easily discoverable. I don't know why you wouldn't want to use sessions for this authentication (which most likely happens in forementioned translation from an 'outside' call to an internal one. I would not make 'not using sessions' a requirement, but there is no reason you couldn't allow several methods of authentication (session, re-authentication on every request, tokens, etc.).

Typically I prefer to produce an interface which can be called using standard PHP and then add an interface to this which adds authentication and RESTful access. So you can access for example:
http://example/api/fetchAllFromUsers?auth-key=XXXXX
Which translates to:
$internalInterface = new Api();
$internalInterface->fetchAllFromUsers();

Instead of authenticating each time, save a chunk of state (in, eg, a cookie) that identifies your session, and use that. It then becomes either a parameter to a GET (using the ?name-value syntax) or can be a part of the URI itself, eg
http://example.com/application/account/ACCTNO/TOKEN
where ACCTNO and TOKEN identify the account and the authentic session respectively.
This may seem a little flaky at first, but it means that your application, as it grows larger, never needs complicated load-balancing with session state and so on -- a simple proxy scheme works fine. This reduces the architeccture complexity by great staggering amounts.

Related

laravel, vuejs and 3rd party api's

I am writing an small web page at the moment that will consume a 3rd party API and process the data and display the return processed data in a table, a user will be able to change the data query based via a form input.
A couple of questions I have,
1) PHP seems like a redundant language here I can do ajax requests in vuejs?
1a) However I would like to be able to cache the 3rd party data, so if user selects the same query twice I don't need to go off an fetch it again, this seems like good practice?
1b) Or would it be better to cache the results page, and show that when a repeat request is made?
I am also using this excercise to start writing test for my PHP is is possible to write tests for 3rd party APIs?
The answer depends on wether you need caching or not. Keep in mind that ajax requests are sent by the browser and therefore don't cost you any server resources. Caching is only really necessary if the third party api you are using can't handle a huge amount of requests.
If you've decided you need caching, you'll have to access the api via your backend, in your case that means using php. Of course you could also write your own api dispatcher / cache in something like NodeJS and use this as a microservice, but that sounds overly complicated for a small project.
In my opinion you are best off to just access the api via ajax in vue, it'll save resources and will be the easiest way to go, everything else seems just redundant.
Testing a third party api can be tricky and in your case is probably redundant. What you rather want to test is how your application integrates with the api. You also probably want to write a mock for that api so that you can run your tests without depending on the api.

HTTP overhead in API-centric PHP application

I am reorganizing an existing PHP application to separate data access (private API calls) from the application itself.
The purpose of doing this is to allow for another application on the intranet to access the same data without duplicating the code to run the queries and such. I am also planning to make it easier for developers to write code for the current web application, while only a few team members would be adding features to the API.
Currently the application has a structure like this (this is only one of many pages):
GET /notes.php - gets the page for the user to view notes (main UI page)
GET /notes.php?page=view&id=6 - get the contents of note 6
POST /notes.php?page=create - create a note
POST /notes.php?page=delete - delete a note
POST /notes.php?page=append - append to a note
The reorganized application will have a structure like this:
GET /notes.php
Internal GET /api/notes/6
Internal POST /api/notes
Internal DELETE /api/notes/6
Internal PUT /api/notes (or perhaps PATCH, depending on whether a full representation will be sent)
In the web application I was thinking of doing HTTP requests to URLs on https://localhost/api/ but that seems really expensive. Here is some code to elaborate on what I mean:
// GET notes.php
switch ($_GET['page']) {
case 'view':
$data = \Requests::get(
"https://localhost/api/notes/{$_GET['id']}",
array(),
array('auth' => ... )
);
// do things with $data if necessary and send back to browser
break;
case 'create':
$response = \Requests::post( ... );
if ($response->status_code === 201) {
// things
}
break;
// etc...
}
I read this discussion and one of the members posted:
Too much overhead, do not use the network for internal communications. Instead use much more readily available means of communications between different process or what have you. This depends on the system its running on of course...Now you can mimic REST if you like but do not use HTTP or the network for internal stuff. Thats like throwing a whale into a mini toilet.
Can someone explain how I can achieve this? Both the web application and API are on the same server (at least for now).
Or is the HTTP overhead aspect just something of negligible concern?
Making HTTP requests directly from the JavaScript/browser to the API is not an option at the moment due to security restrictions.
I've also looked at the two answers in this question but it would be nice for someone to elaborate on that.
The HTTP overhead will be significant, as you have to go through the full page rendering cycle. This will include HTTP server overhead, separate process PHP execution, OS networking layer, etc. Whether it is negligible or not really depends on the type of your application, traffic, infrastructure, response time requirements, etc.
In order to provide you with better solution, you need to present your reasoning for considering this approach in the first place. Factors to consider also include current application architecture, requirements, frameworks used, etc.
If security is your primary concern, this is not necessarily a good way to go in the first place, as you will need to now store some session related data in yet another layer.
Also, despite the additional overhead, final application could potentially perform faster given the right caching mechanisms. It really depends on your final solution.
I am doing the same application framework. Had the same problem. So I decided to do following design:
For processes that are located remotely (on a different machine) then I user crul or other calls to a remote resource. If I store user on a different server to get user status I do this API->Execute(https://remote.com/user/currentStatus/getid/6) it will return status.
For local calls, say Events will require Alerts (these are 2 separate package with their own data model but on the same machine) - I make a local API like call. something like this:
API->Execute(array('Alerts', Param1, Param2).
API->Execute then knows that's a local object. Will get the object local physical path. Initialize it, pass the data and return the results into context. No remote execution with protocols overhead.
For example if you want to keep an encryption service with keys and what not away from the rest of the applications - you can send data securely and get back the encrypted value; then that service is always called over a remote api (https://encryptionservice.com/encrypt/this/value)

Control PHP session in ASP.NET application

I maintain an online application that use most of the pages in PHP, but some pages uses for a good reason ASP.NET. Users can login in the PHP part. Is there any option to control or a certain PHP session is active inside the ASP.NET page? Both pages are hosted on one server.
You could build a web service on the PHP side that would allow to perform that check.
You would then call that webservice from the ASP.NET application.
You have to be very very careful however. A service like that would have to be highly secured, because this could provide a way to session hi-jacking, since it provides a way to validate if a certain session exists or not.
You could secure it by only restricting allowed IP(s) or using a form of authentication.
There are different ways you can build webservice.
You could write it a simple page that just does whatever logic you want and then returns a result in JSON or XML (that's the lazy and ugly way of doing it). If you are using a particular framework, you could look to leverage that framework in order to add that service. All major frameworks have ways to do that (Symfony, Silex, Laravel, Yii, Zend, etc.). Zend Framework offers something called Apigility that makes building Restful webservices very easy.
Your ASP.net application, will also need to have a token coming from the PHP side, so it can be used to identify the session.
On the PHP side, you would need to store somewhere that the user is logged in.
This also can be done in different ways and depends on what you want to achieve.
For example, you could store in a database a timestamp along with a token indicating when was the last time you detected an activity from the user. Then, your webservice would check against that db for the token and see if the lastActivity timestamp has an adequate value (you would have to define what adequate means, e.g. not older than 30 minutes).

Vanity urls + REST + Web crawler

I have an app that uses data from several applications APISs (Facebook,Twitter,Instagram etc..), accessing them from REST endpoints in PHP.
I am building a vanity URL for my app users, say http://www.myapp.com/username.
If i had a database, i could fetch user data from database to display in the user page.
With REST services, each time i go into the URL, there is a call to the API that fetches information from the main websites.
The problem is getting big since the app is going to receive a lot of traffic from search engine crawlers (i would not lower the crawling rate)
1st problem: Since the API offers limited access (2000 query per hours), there is a way to skip the api call (for example, using memcache) ?
2nd problem: I want to make a vanity url, so each time i call http://www.myapp.com/username i have to call the api to get the userid and then the username, i wonder if this is the correct way to do this, most websites do it with url rewrite, but how to deal with it when you have external data and not your internal database?
Thanks for the reading, any help is needed!
About using memcache, the big problem you will encounter is validating and expiring the cache data.
Let's say you implement it like this:
function getSomeData() {
if (Memcache::has('key-for-data')) {
return Memcache::get('key-for-data');
} else {
$data = RestApi::getData();
Memcache::put('key-for-data', $data);
return $data;
}
}
This seems sensible enough but then, what happens if the REST API is accessed through any other means? (Like another third party app POSTing data to the same API). Then, the cached data can be invalid and you will not know about it.
From your application's perspective, changes to the underlying data store are completely random and furthermore, totally opaque and unknowable, and therefore it is not a good target for caching.
If on the other hand you can get some kind of "push" notification from the service whenever data is updated (i.e. a subscription service), you could use this as a trigger to invalidate the relevant cache entries. However this is additional complexity and would need to be supported at both ends.
Sorry this isn't really an answer but it is a partial answer and it was too long for a comment :-)
Try using some kind of framework. It should make the routing much simpler.
The url rewriting would happen vi .htaccess so the user would never see a rewrite for the url.
Two ways that I can think of are:
Rewrite in the .htaccess such that all your defined routes are left untouched and in all other cases(that is http://www.example.com/username) the user controller method is injected in between the username and the url.
Define routes so that all your known routes are handled and have the defualt route take care of figuring out the user id and doing everything that is necessary.
For caching use memcache/redis to cache your queries/user objects/anything else accessed frequently.

How do I restrict JSON access?

I have a web application that pulls data from my newly created JSON API.
My static HTML pages dynamically calls the JSON API via JavaScript from the static HTML page.
How do I restrict access to my JSON API so that only I (my website) can call from it?
In case it helps, my API is something like: http://example.com/json/?var1=x&var2=y&var3=z... which generates the appropriate JSON based on the query.
I'm using PHP to generate my JSON results ... can restricting access to the JSON API be as simple as checking the $_SERVER['HTTP_REFERER'] to ensure that the API is only being called from my domain and not a remote user?
I think you might be misunderstanding the part where the JSON request is initiated from the user's browser rather than from your own server. The static HTML page is delivered to the user's browser, then it turns around and executes the Javascript code on the page. This code opens a new connection back to your server to obtain the JSON data. From your PHP script's point of view, the JSON request comes from somewhere in the outside world.
Given the above mechanism, there isn't much you can do to prevent anybody from calling the JSON API outside the context of your HTML page.
The usual method for restricting access to your domain is prepend the content with something that runs infinitely.
For example:
while(1);{"json": "here"} // google uses this method
for (;;);{"json": "here"} // facebook uses this method
So when you fetch this via XMLHttpRequest or any other method that is restricted solely to your domain, you know that you need to parse out the infinite loop. But if it is fetched via script node:
<script src="http://some.server/secret_api?..."></script>
It will fail because the script will never get beyond the first statement.
In my opinion, you can't restrict the access, only make it harder. It's a bit like access-restriction by obscurity. Referrers can be easily forged, and even with the short-lived key a script can get the responses by constantly refreshing the key.
So, what can we do?
Identify the weakness here:
http://www.example.com/json/getUserInfo.php?id=443
The attacker now can easily request all user info from 1 to 1.000.000 in a loop. The weak point of auto_increment IDs is their linearity and that they're easy to guess.
Solution: use non-numeric unique identifiers for your data.
http://www.example.com/json/getUserInfo.php?userid=XijjP4ow
You can't loop over those. True, you can still parse the HTML pages for keys for all kinds of keys, but this type of attack is different (and more easily avoidable) problem.
Downside: of course you can't use this method to restrict queries that aren't key-dependent, e.g. search.
Any solution here is going to be imperfect if your static pages that use the API need to be on the public Internet. Since you need to be able to have the client's browser send the request and have it be honored, it's possibly for just about anyone to see exactly how you are forming that URL.
You can have the app behind your API check the http referrer, but that is easy to fake if somebody wants to.
If it's not a requirement for the pages to be static, you could try something where you have a short-lived "key" generated by the API and included in the HTML response of the first page which gets passed along as a parameter back to the API. This would add overhead to your API though as you would have to have the server on that end maintain a list of "keys" that are valid, how long they are valid for, etc.
So, you can take some steps which won't cost a lot but aren't hard to get around if someone really wants to, or you can spend more time to make it a tiny bit harder, but there is no perfect way to do this if your API has to be publically-accessible.
The short answer is: anyone who can access the pages of your website will also be able to access your API.
You can attempt to make using your API more difficult by encrypting it in various ways, but since you'll have to include JavaScript code for decrypting the output of your API, you're just going to be setting yourself up for an arms race with anyone who decides they want to use your API through other means. Even if you use short-lived keys, a determined "attacker" could always just scrape your HTML (along with the current key) just before using the API.
If all you want to do is prevent other websites from using your API on their web pages then you could use Referrer headers but keep in mind that not all browsers send Referrers (and some proxies strip them too!). This means you'd want to allow all requests missing a referrer, and this would only give you partial protection. Also, Referrers can be easily forged, so if some other website really wants to use your API they can always just spoof a browser and access your API from their servers.
Are you, or can you use a cookie based authentication? My experience is based on ASP.NET forms authentication, but the same approach should be viable with PHP with a little code.
The basic idea is, when the user authenticates through the web app, a cookie that has an encrypted value is returned to the client browser. The json api would then use that cookie to validate the identity of the caller.
This approach obviously requires the use of cookies, so that may or may not be a problem for you.
Sorry, maybe I'm wrong but... can it be made using HTTPS?
You can (?) have your API accessible via https://example.com/json/?var1=x&var2=y, thus only authenticated consumer can get your data...
Sorry, there's no DRM on the web :-)
You can not treat HTML as a trusted client. It's a plain text script interpreted on other people's computers as they see fit. Whatever you allow your "own" JavaScript code do you allow anyone. You can't even define how long it's "yours" with Greasemonkey and Firebug in the wild.
You must duplicate all access control and business logic restrictions in the server as if none of it were present in your JavaScript client.
Include the service in your SSO, restrict the URLs each user has access to, design the service keeping wget as the client in mind, not your well behaved JavaScript code.

Categories