I've got an external_api implemented that I can currently hit the standard way;
http://localhost/webservice/rest/server.php?wstoken=foo&wsfunction=local_test_function&moodlewsrestformat=json
and it returns:
https://google.com/?q=test
The thing I can not figure out is, how can I make this return an HTTP/302? I'm trying to work around the fact that atto won't run JS code, and I thought I could just do an iFrame that has it's src set to my webservice, but all I can seem to do is return a string.
You cannot, Moodle web service API is very much designed around a typical RPC API. You make a call, and you get an answer. There aren't any implementation of HTTP verbs, nor respond codes apart from 500, and 403, when an exception is raised, or permissions are lacking.
I'm actually uncertain why you would want to do this anyway. The external_api is meant to interact with Moodle, not to redirect elsewhere, especially if you end-up passing a user's token to an iframe.
Related
I want to fetch the response from adobe analytics which I get in network panel of browser and display in it the page. This there any way to read the response through php. I don't have access to core files. i work as third party implementation team.
The short answer is you can't. php is server-side. Assuming you did the standard javascript Adobe Analytics implementation; well that's client-side. Your server can't see that stuff.
The longer answer is redeploying Adobe Analytics through a server-side implementation. Basically you setup the code but have it point to your server and then you forward it to adobe (proxying), and so now it is exposed to you server-side.
The alternative answer is depending on what it is you are actually trying to accomplish, you can make use of Adobe Analytics' s.registerPostTrackCallback function. Basically it lets you register a callback function to be called after every s.t or s.tl call, and it gives you the full/final request URL sent to the AA collection server. You can then make an AJAX request to pass it to your server and do whatever with it. Or since you mentioned displaying it on page, maybe consider using javascript to render it on the page? But if you're looking for actual response stuff (headers, content) well you're out of luck on this option.
The other other alternative answer is.. this almost sounds like you are looking to make some kind of browser plugin? If so, then on a plugin/extension level, the request/response stuff (including header stuff) is exposed on that level. But again, ultimately this is really a client-side solution..
But first step back and more clearly define what it is you are trying to do. Or if you've done that already, then try (more clearly) to convey that here.
It's rare, but I have to pay MS a compliment: the ASP.NET WebMethod (AJAX) authorization is a dream, regarding my desire for security and laziness.
Encosia's ASP.NET page methods are only as secure as you make them absolutely fits those needs. ASP.NET is actually workable for me now. Free at last! (From the noble but disastrous AJAXControlToolkit).
Anyways, the problem is, that's for work. I'm not buying the MS architecture when LAMP's out there for free. I'm new to AJAX, and I can't seem to find a clear answer on how to authorize AJAX calls to PHP in the same way as Encosia above.
Can anyone suggest the PHP equivalent of what Encosia does in the link above?
Thanks in advance!
More Details
OK, let me be more specific. Encosia's solution above gives 401 denied to anyone not logged in trying to access a webmethod. Neat, clean, easy. Before, I tried to user session data to give access, but it, unknowingly to me, forced synchronous mode. Nono.
I need both, for my site. I need to be able to give 401 denieds on certain pages if a user isn't logged in. I need to be able to allow anyone to call other phps via ajax regardless of login.
Clarity
Bottom line: I don't want anyone accessing certain AJAX PHPs unless if they are logged in. I don't care what the response or any other details as long as its' still AJAX. How to?
Not really clear from the question, but if you want to only allow access to your AJAX server side listening scripts (maybe XML or JSON output) to users that have either authed or are on the related page,then how about adding a session identifier to your JS AJAX requests? In the server side script you can check that identifier against maybe a DB table holding your current sessions.
For extra security, you could check against IP, a cookie etc. These are all values that you can set when the session is started.
The main thing you need to ask yourself is this:
If a user is either logged in or browsing, what kind of access to the database do you really want / need to give? Each application will have its own needs. If you are going to have AJAX listeners on your server, then all that's needed is a quick look at Firebug (example) to see where your scripts are and the format of the requests. This could allow a potential security hole to be found. Make sure all your incoming requests are correctly treated so as to remove the possibility of injection attacks.
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.
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.
I am working with Open Id, just playing around making a class to interact / auth Open Id's on my site (in PHP). I know there are a few other Libraries (like RPX), but I want to use my own (its good to keep help better understand the protocol and whether its right for me).
The question I have relates to the Open Id discovery sequence. Basically I have reached the point where I am looking at using the XRDS doc to get the local identity (openid.identity) from the claimed identity (openid.claimed_id).
My question is, do I have to make a cURL request to get the XRDS Location (X-XRDS-location) and then make another cURL request to get the actual XRDS doc??
It seems like with a DUMB request I only make one cURL request and get the Open Id Server, but have to make two to use the XRDS Smart method. Just doesn't seem right, can anyone else give me some info.
To be complete, yes, your RP must HTTP GET on the URL the user gives you, and then search for an XRDS document reference and if found do another HTTP GET from there. Keep in mind that the XRDS may be hosted on a different server, so don't code up anything that would require the connection to be the same between the two requests since it might not be the same connection.
If in your initial HTTP GET request you include the HTTP header:
Accept: application/xrds+xml
Then the page MAY respond immediately with the XRDS document rather than an HTML document that you have to parse for an XRDS link. You'll be able to detect that this has occurred by checking the HTTP response header for application/xrds+xml in its Content-Type header. This is an optimization so that RPs don't typically have to make that second HTTP GET call -- but you can't rely on it happening.
The best advice I can give you, is to try to abstract your HTTP requesting a little bit, and then just go through the entire process of doing an HTTP request twice.
You can keep your curl instances around if you want to speed things up using persistent connections, but that may or may not be want you want.
I hope this helps, and good luck.. OpenID is one of the most bulky and convoluted web standards I've come across since WebDAV =)
Evert
I know I'm late to the game here, but I think you should also check out the webfinger protocol. It takes the standard "email as userid" pattern and lets you do a lookup from there to discover openid etc.