How to do Dropbox authentication in a single page app without opening a new window?
Asked Answered
F

3

8

I have a single page app that integrates with other services such as Dropbox and LinkedIn. Dropbox, for instance, has great API and I got the authentication working by opening Dropbox's authentication link in another window. Once the user authenticates, I ask them to close that new window to return to my app.

Clearly this is suboptimal as it takes the user away from my app, and even more cumbersome on tablets.

How would I do the authentication within the app, such is in a lightbox or a modal form?

Note that the integration itself happens server-side not client side. Presently, the Dropbox authentication page has a call back page that signals to my server that authentication was successful, which I store in the user's table in the database for future use.

Note: The bounty comment should read: A code sample is highly desired but not required.

Footstall answered 4/7, 2012 at 1:29 Comment(3)
Can you clarify where your app works, that is, is this a web app that the user accesses in their own browser, is it a native app/what platform, etc?Used
It's a web-app built on Backbone and friends, and will also be made available for download on mobile using PhoneGap. I may be able to use the Dropbox SDK with PhoneGap, so this question is focused on in-browser web-app.Footstall
thanks for the quick clarification! I've posted my answer, let me know if I misunderstood :-)Used
A
11

What you're proposing is to defeat the security model, so it should not be possible. The user should be able to see the URL of the real page for verification. Imagine when you're making a payment with Paypal, you likely check that you're on paypal.com before entering your important data right? The same applies to all other apps. It's a very ugly flow, but the best the industry has come up with today.

The ideal flow is you redirect user to the third-party web site or app, user logs in and authorizes, then redirects back to you. A native app has the benefit of switching to another native app, so the flow is a bit less ugly.

The work around that would do what you want is an app asking for user's name and password to the 3rd party service, then doing the auth dance themselves behind the scenes. This will likely deter users from your app and is very dangerous. I do not recommend it.

Albescent answered 31/8, 2012 at 14:0 Comment(1)
I did a quick test and turns out Dropbox sends X-Frame-Options in the response header, making the iframe approach described by Andreas unusable in this case. Not sure whether the ChildBrowser would work in the case of the phone app, but answer is the correct one for general webapps. Thanks Alex.Footstall
C
4

You may load the authorization endpoint in a iframe on your webpage. However, notice that some browsers have limitations on cookies sent to the login provider within an iFrame. Typically (Safari, iOS) you have only read access to the cookies, which is sufficient if the session cookie is already set at the provider.

On your callback page - where you are sent back from dropbox after authentication; you will need to call a javascript function to trigger an event at the parent page, that authentication is done.

window.parent.AppController.authenticationComplete();

The parent then may remove the iframe, and proceed as authenticated.

authenticationCompleted = function() {
     // [snipp]
     $("iframe#loginwrapper").remove();
}

Because of the potential cookie problem, I'd reccomend you to perform all the authentication steps initiated from the server end, before the main HTML page is served at all. Then you will make sure that your app is not loaded twice. This is typical behaviour of many authentication/identity middleware software solutions.


When you mention app it is unclear whether you mean a pure WebApp, or if you have the control available in a hybrid app by using frameworks such as Phonegap. With Phonegap or similar, you may load a browser inside the browser inside the app - in that case the ChildBrowser is not limited with the same cookie limitations.

I recently wrote a tutorial on how to make this work with Phonegap and Childbrowser for iOS.

Notice that this tutorial is on using OAuth 2.0 which is somewhat different from OAuth 1.0.

Caloyer answered 29/8, 2012 at 19:17 Comment(8)
Since I'm using server-side authentication, and tokens are sent to dropbox and back to the callback through get parameters, I suspect the cookie limitation wouldn't be an issue. I will make my app available both as a webapp and as a native app wrapped in phonegap, so the tutorial may come in handy. Would the iframe approach work on phonegap just as well? any benefits for using a ChildBrowser instead on iframe in phonegap if cookies are not an issue? Many thanks for your answer!Footstall
Yes, everything that works in the webapp, also works in phonegap.Diclinous
You may still run into issues with cookie limitations, regardless of the implementation of your app, when the user interacts with Dropbox authentication login page, it may be restricted from settinging cookies, which may result in an error.Diclinous
I see. Is there a way to find out more certainly whether this will be a problem or not without implementing the whole thing first?Footstall
BTW, that same approach not only works with IFrames but also with stand-alone child windows. Your auth-callback can send back some Javascript to the authentication window that first calls a function on the application's window to tell it the authentication is successful and then automatically closes the authentication window. This approach still opens a new window/tab for authentication, but takes the user right back to the app without having the user to do an extra click. Might be an alternative if the IFrame does not work out.Ambriz
Andreas, @Ambriz What's your view on the security concern raised by Alex Kennberg in his answer?Footstall
His point is perfectly valid - on web! But in a native app it does not really matter if the user can see the url or not because it can not trust it anyway.Diclinous
With one exception, if you redirect to the native browser, the user normally would be more comfortable and can trust the browser url. Register a custom schema to be able to redirect the user back to your app after completion of the login process.Diclinous
U
0

If your app is a web app, the best way to streamline the flow is to just redirect the current page (e.g., How to redirect to another webpage in JavaScript/jQuery? ) to the /authorize page on Dropbox, with an oauth_callback to a page on your app that indicates the process was completed.

This way the flow is just:

  1. (on your app) user clicks button to start OAuth flow
  2. (your app redirects to Dropbox authorize page) user authorizes app
  3. (Dropbox redirects per oauth_callback to your app) app gets access token and is ready to use integration

And this all happens within a single page, without closing/opening extra windows.

Used answered 4/7, 2012 at 19:52 Comment(1)
Thanks for your answer. Your proposed solution is great for keeping everything in one window, but it's not really "single page". Single page apps load a lot of data, JS, and HTML in the background to provide refresh-less experince, i.e., clicks on links don't trigger a full page load but only on-page changes of relevant sections. With your approach, the entire app data will need to be reloaded when the person returns to the app through the callback, defeating the benefit of having a single-page web app.Footstall

© 2022 - 2024 — McMap. All rights reserved.