FaceBook loads HTTPS hosted iframe apps via HTTP POST (S3 & CloudFront errors) - facebook

I have been trying to write a bucket policy that will allow (X-HTTP-Method-Override) because my research shows that Facebook loads HTTPS hosted iframe apps via HTTP POST instead of HTTP GET which causes S3 and CloudFront errors.
Can anyone please help me with this problem?
This is what's returned from S3 if I served my Facebook app directly from S3:
<?xml version="1.0" encoding="UTF-8" ?>
- <Error>
<Code>MethodNotAllowed</Code>
<Message>The specified method is not allowed against this resource.</Message>
<ResourceType>OBJECT</ResourceType>
<Method>POST</Method>
<RequestId>B21565687724CCFE</RequestId>
<HostId>HjDgfjr4ktVxqlIBeIlvXT3UzBNuPg8b+WbhtNHOvNg3cDNpfLH5GIlyUUpJKZzA</HostId>
</Error>
This is what's returned from CloudFront if I served my Facebook app from CloudFront with S3 as the origin:
ERROR
The request could not be satisfied.
Generated by cloudfront (CloudFront)
I think the solution should be to write a bucket policy that makes use of X-HTTP-Method-Override... Probably I am wrong though. A solution to this problem would be highly appreciated.

After trying many different ways to get this to work, it turns out that it simply is not possible to make the POST to static content work on S3 as things stand. Even if you allow POST through Cloudfront, enable CORS, change the bucket policy so that the Cloudfront origin identity can GET/PUT etc. it will still throw an error.
As an aside, S3 is not the only thing that balks at responding to such a POST request to static content. If you configure nginx as an origin for a Facebook iframe you will get the same 405 error, though you can work around that problem in a couple of ways (essentially rewriting it to a GET under the covers). You can also change the page (though still static) to be a dynamic extension (.aspx or .php) to work around the issue with nginx.
You can host all your other content on S3 of course, and just move the page that you POST to onto a different origin. With a decent cache time you should see minimal traffic, but it will mean keeping your content in two places. What I ended up doing was:
Creating EC2 instances in an autoscaling group (just in case) to serve the content
They used a cron job to sync the content from S3 every 5 minutes
No change in workflow was required (still just upload content to S3)
It's not ideal, nor is it particularly efficient, but hopefully it will save others a lot of fruitless testing trying to get this to work on S3 alone.

You can set your Cloudfront distribution to allow POST methods.
If you go into your dashboard and edit the Behavior for the distribution
- Then select Allowed HTTP Methods - GET, HEAD, PUT, POST, PATCH, DELETE, OPTIONS
This allows the POST from Facebook to go through to your origin.

I was fighting with S3 and CloudFront for last couple of days. and I confirm that with any bucket policy we cannot redirect POST calls from Facebook to S3 static (JS enriched) contents.
The only solution seems to be the one Adam Comerford mentioned in this thread:
Having a light application which receives Facebook calls then fetching the content from S3 or CloudFront.
If anyone has any other solution or idea it will be appreciated.

you can't change POST to GET - that's the way Facebook loads app page because it also sends data about the current user as POST body (see signed_request for more details). I would suggest you look into fixing your app to make sure it properly responds to POST request.

Related

How to fix "load unsafe scripts"?

so I'll start from the very beginning.
Basicly I purchased a template off themeforest and I manually edited the code in a markup editor to match my preferences.
As I was finished, I decided to host my website on github pages - I uploaded my code directory to a repository as you do.
Here's a link to my repository:
https://github.com/KristofferHari/kristofferhari.github.io
Here's a link to my current website URL:
https://kristofferhari.github.io/ (As you can see, everything's kinda buggy)
So I managed to contact the seller and this is what I was provided with:
The reason for that is because the resources are using a http connection and they can’t be loaded on https connection website. So
you have to upload all the resources (scripts/stylesheets) to github
in order to use them on github.
So I suppose that through my browser, I am trying to connect to my website through a https connection rather than an http. (Is this what is actually causing the problem, and what's the difference between a http connection and a https?)
Secondly, how would I upload all my resources (scripts/stylesheets) to github?
Thanks in advance!
There is a relatively simple solution: to use a protocol-relative URL format.
e.g. your error
Mixed Content: The page at 'https://kristofferhari.github.io/' was loaded over HTTPS, but requested an insecure stylesheet 'http://fonts.googleapis.com/css?family=Open+Sans:400,700,300,900'. This request has been blocked; the content must be served over HTTPS.
The problem is you are loading
http://fonts.googleapis.com/css?family=Open+Sans:400,700,300,900'
from
https://kristofferhari.github.io/
The page is secure (HTTPS), but it's loading insecure content (HTTP).
To fix it, you basically need to change the stylesheet to:
https://fonts.googleapis.com/css?family=Open+Sans:400,700,300,900'
But a more flexible solution is to use a protocol relative format:
//fonts.googleapis.com/css?family=Open+Sans:400,700,300,900'
which will then work on either http or https.
Apply this change to all included resources.

REST Api - Created resource redirect

I'm building REST API, and when resource is created normally I return HTTP 201 Created along with Location header to specify where that resource is located. But from some reason http client is not redirecting.
I'm using Postman for this. Does anyone have idea on this problem?
In short, a Location header is not sufficient to trigger a client redirect. It must be used in conjunction with a 3xx HTTP status code.
References:
https://en.m.wikipedia.org/wiki/HTTP_location
Redirecting with a 201 created
This is one of those things where the expectation does not meet what actually happens, and the first thing people think is "well that doesn't work properly", as has been suggested in other comments.
The Location is just a random header, and clients, such as Postman or curl or anything else need to be instructed to follow them. Most won't do this by default, as that is an unreasonable default.
YouTube for example returns a body for some responses and a Location tag too. One example would be video uploads. They respond to your original meta-data for the video is sent with a POST, and they shove a Location URL which is the endpoint to upload the video too. If clients just randomly redirected to that you'd be having a bad time.
You can use Paw to make a "sequence", which I believe will let you take values from headers to reuse. This is also possible with Runscope Ghostinspector.

Authorization for a POST request to Google Storage bucket

I am trying to figure out how to use Google Cloud Storage for my app. The app should allow any user to POST (or PUT) objects into a Bucket and also let them read any files from said bucket. I am confused as to how I am supposed to form my POST requests in order to make this work.
I have just been playing around, sending requests to see if I can upload a file into a bucket. I have tried forming a request according to this example:
https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload
POST /upload/storage/v1/b/<bucketname>/o?uploadType=media&name=<objectname> HTTP/1.1
Host: www.googleapis.com
Content-Type: image/jpeg
Content-Length: 100
Authorization: Bearer <your_auth_token>
I am confused as to what exactly the 'auth_token' is. I have tried going into the developers console and generating a 'Public API access' key and attempted to use this, but I got a response saying it was unauthorized.
Am I generating the right type of key? I understand OAuth keys are used when you need access to a Google user's data. I don't need this: I simply need to allow users of my app to add files to a bucket and read from that bucket. Any help to point me in the right direction is appreciated.
It is like an ID to identify you have permission to perform your actions, as you haven´t provide which language you are using, I will provide a golang example
https://github.com/johnbalvin/google-cloud-go/blob/master/storage/resumableUpload.go

Drupal 8.x POST (create) node via REST doesn't work

I am working with Drupal 8.0 alpha 11. I've been able to follow the Drupal guides for REST services:
POST for creating content entities (https://drupal.org/node/2098511) and the related guides, GET on content entities and GET on Views-generated lists
"GET"s work great, but I haven't been able to get any "POST" to work (I've posted the issue on the drupal.org site, too).
I've tested POST for both a basic page and my own content entity and neither works. I've tried a lot of variations, including removing "entity" from the url as per the recent changes in Drupal 8, but the POST still does not work. I'm using Postman in Chrome for testing and again, I can "GET" a basic page and my own content entity just fine, but with POST, I always get a return code of 200 "OK", never "201" (which is what I should receive according to the guide) and the nodes don't get created.
I've updated the rest.settings.yml for both the basic page and my content type, have established permissions for the user, am using basic auth, and have added Content Type application/hal+json and cross-origin details to the header info.
Any idea what's missing? Do I need to add coding in my create entity form to "receive" the posted data? Where do I do this/in which directories should the files go? Is this required for the default Basic Page content type, too?
Thanks for any help...I've spent weeks on this and can't figure out what I'm missing.
Thank you!
On Drupal 8 alpha 11 it will work but make sure I am assuming that you have enabled REST , HAL, HTTP basic authentication, Serialization module on your site.
You have enabled POST method for 'entity:node' with basic_auth authentication type and hal_json as format
Give enough permission to a admin so that it can create node via REST , To do so navigate to admin/people/permissions on your drupal installation.
now /entity/node is REST end point to create node I am using REST Client to demonstrate POST request
this is link to image that will make it more clear
https://dl.dropboxusercontent.com/u/100492838/POST_Node.png
now make a POST request with Content-Type = hal+json and also set basic_auth header.
change URL according to your site.

Flickr API request over HTTPS, is it possible?

After migration to https we had a problem with the flickr-api. Cannot find whether the Flickr supports rest over https?
We expect to make this kind of request which works fine over http and no way over https.
https://api.flickr.com/services/rest/?format=json&sort=interestingness-desc&method=flickr.photos.search&tags=Italy&tag_mode=all&api_key=<key>
Any help please or advise?
You can simply replace: http://api.flickr.com/services
with: https://secure.flickr.com/services
Taken from Here
**** Update ****
As Michael pointed out, the URL has changes and it's now - https://api.flickr.com/services
After some hours of searching and posting at yws-flickr. We've seen for two workarounds:
proxying flickr request through your server via https (more load and
some security issues may come out)
pereodically update database of
links via cron service (implement this one)