Detecting Facebook canvas in Rails app - ruby-on-rails-3

I'm using a before_filter to detect the signed_request query string Facebook generates when a user is referred to a canvas app.
Then, I set session[:canvas] = true and test for that when I need different app logic based on whether the user is in the canvas or on the native browser app. The problem is that if the user, for any reason, leaves the canvas and navigates to the browser-based app, the session[:canvas] variable is still set to true.
Is there a better way to detect the difference between the canvas and the native browser app?

I personally like to use an "alias" url for the Facebook app, e.g. use fb.mysite.com instead of www.mysite.com in the app settings and set things up so that the two domains point to the same place. Or something similar can be done with directories, e.g. www.mysite.com/fb/ pointing to the same place as www.mysite.com/ but giving an easy way for the code to determine if it's a direct access or from an app.
Using a session can work too, but you have to add an additional javascript check in the case you are currently in "app mode" (canvas==true). The javascript just checks to see if the page is inside an iframe, and if it is not then it redirects to something like www.mysite.com/thispage?app=0. Your pages should check for the app=0 parameter and clear the session if present (or set canvas=false). This way, if a user starts out inside Facebook but then visits your site directly, things automatically get adjusted correctly.

Instead of storing this information at the session, check for the existence of the signed_request parameter, if there is no parameter, it possibly means the user is not inside the facebook app anymore.

I might be completely wrong, but doesn't Facebook access your canvas content by a POST instead of a GET request? Wouldn't that be the easiest way to distinguish where the request came from?

Related

Is it possible to track if a page finished loading with my current implementation of webView?

Picture of WebView
Hello, I am working on a login page for my app. Right now the webView login page works! However, there is one big issue with the current implementation.
Basically for my login I call a series of functions:
Opens hidden website with a webView,
Injects javaScript to login to website,
Changes to page of website containing data,
Extracts data,
Pushes to new view as login was successful
Now this is all working, except I had to hardcode times for each function to take place using DispatchQueue.main.async. This is of course problematic because some of the functions vary in time, for example the time it takes to load the webpage. This means my login is successful 75% of the time. I need a way to track if the webView is finished loading so I can call the next function only when it is done loading. However, every webView I have seen that has something like this, uses a completely different structure. When I have tried these other structures, I could not make certain things work like my login function that uses evaluateJavascript.
Is there anyway to have this feature by adding something to my current implementation? Thanks!

Navigating elm from URL without destroying state (elm 0.18)

I have an elm app that incorporates logging in and fetching data from a server. Once I've logged in, I navigate to /#/pages/13 and it updates the model with page id 13. If I click around within the app, I see evidence that that page persists in the model.
When I navigate away from that page via internal links, then enter http://localhost:3000/#/pages/13 into the URL, I still see that page.
If I enter that URL while I am at that location, it seems to treat the behavior as a complete refresh, resetting the model...including my token, so it logs me out.
How can I enter the same page into the URL without elm resetting the model?
(If it matters, I am using gulp)
That behaviour seems to be by design, although I didn't find an official source for this.
The most you can do is register a beforeunload listener, which might show a prompt allowing the user to cancel the navigation.
Related: https://stackoverflow.com/a/34415095/2014893

Showing file selection UI : Integrating Dropbox with OAuth 2

I am trying to create a web page which will allow my user to upload a file to my S3 storage. For choosing the file user can use Google Drive, Dropbox and also local system. Am facing issues while implementing the Dropbox part of this.
Am using this technique for integration(using core API and OAuth 2).
First when user chooses Dropbox i am opening an HTML page in an IFrame. Here I have an authorize button which will open the authorize endpoint mentioned in the above link. This link shows me X-FRAME-Options error inside the Iframe so i had to open this link as a popup to work.
Is there a way around this? I'd like the authorize URL to open in the same iframe by using location.href.
Also when i open it as a popup, after the user logs in successfully the redirect_uri which i pass i getting opened in the popup. I had to do some unconventional setInterval coding to go around this. Can someone suggest a solution for this as well?
I also tried using CSRF tokens as mentioned in Smarx's blog but this also gives me the same error.
EDIT :
#smarx i tried using dropbox.js and it works fine. Stuck at one place
I used the OAuth popup driver and have a button which says sign-in.
First on load i create the client and then the popup driver as below
client = new Dropbox.Client({ key: client_id });
client.authDriver(new Dropbox.AuthDriver.Popup({
receiverUrl: "http://localhost/uploadCare/dbcallback.html"
});
);
And in the call back html i am writing
Dropbox.AuthDriver.Popup.oauthReceiver()
as mentioned in the docs.
But this does not take me back to the original page and show me the list of files.
I particularly did not understand this part of the explanation
"To use the popup driver, create a page on your site that contains the receiver code, change the code to reflect the location of dropbox.js on your site, and point the Dropbox.AuthDriver.Popup constructor to it."
Could you please help me out here.
You definitely can't put dropbox.com into an iframe, for security reasons (e.g. clickjacking).
A few suggestions:
Can you just use the Chooser for your use case? That would certainly be easier for you and your users.
If you can't use the Chooser, is there a reason you're not using dropbox.js? It has a popup auth driver that will pretty much just take care of all this for you. The redirect will definitely happen in the same window as auth, so communication between the windows (usually via localStorage) is generally necessary. This is already done in dropbox.js.

Additional pages with SPA

I'm creating a SPA app using Durandal and I would like to include a credit card payment facility. The guys that I'm looking at requires you to give return URLs to success, cancel and a view other pages, is that possible?
To me it would be breaking the 'single page' part of SPA, but is it possible? Could I do it all in a window?
Disclaimer: I don't know Durandal, but you would solve this in an SPA using either "hashbang URIs" or actually re-serving the SPA in your webserver for the requested return URI and adjusting the content using the same technique as hangbash URIs but using history.pushstate/history.popstate instead, see here: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history
A more general article from Google is available here that covers the same principle: https://developers.google.com/webmasters/ajax-crawling/
This "works" because SPAs are SPAs only in that the browser requests a new HTML document from the server once (or in your case, twice), the SPA should still be updating the history and address-bar state of the UA as the user navigates the application, just as though it were a regular multi-page application.
A great example of this is GitHub's source navigator: Try here ( https://github.com/angular/angular.js ) and navigate the repository, observe that the contents of the file-listing change as does the address bar, but your browser doesn't reload the whole page... yet if you copy+paste the (modified) address bar address into a new browser window, you get the same page back.
I looked into doing credit card processing from a SPA and the best option I had found was Stripe. They supply a javascript file that looks like it would work, I never implemented it on my project due to time constraints so I can't confirm that it works but it looked very promising.
IFRAMEs are quite good for this sort of thing. You can use jQuery to hook an event handler to the page load event and this will tell you when the other end has responded. Load the 3rd party page into the IFRAME and serve response pages on the URLs you provide to the service provider. As mentioned by others you can use routes to identify the response pages. The IFRAME will stop the round-tripping from mucking up your application state and in fact it is possible to put script in your response pages that dot-notates its merry way up the DOM and into your app.

Bring Safari to front

I'd like to bring Safari to the front (switch to) but without using a URL, instead I'd like to see the "pages" view so the user can pick an already loaded page. Is this possible?
We open links in Safari and if the user returns to the app and selects the link again, I'd rather let them pick which Safari page to browse instead of opening a new one. I know that if the same URL is called it will open the correct page but the user may have navigated within the original site so the url no longer matches.
Thanks,
Rick
I don't think that its possible, i would use a UIWebView inside your app in order to get that experience you want, you can find the UIWebView apple docs here (http://developer.apple.com/library/ios/documentation/uikit/reference/UIWebView_Class/Reference/Reference.html) and also the equivalence of c# methods here (http://tirania.org/tmp/rosetta.html) hope this helps
Alex
Your app doesn’t get control of Safari’s UI. You might, however, be able to design your site so that it handles navigation via Javascript—AJAX and whatnot—so that the actual page URL doesn't change, and thus so that the page, re-opened from your app, brings up the existing Safari page. Of course that introduces further problems with your pages no longer being bookmarkable, but you might find that an acceptable tradeoff.