Dropbox authorization in a Windows Store app

Posted by Steve Marx on April 11, 2014

Last week, I showed how to perform Dropbox authorization in a Windows Forms app. This time, we'll do the same thing but in a Windows Store app, where we get to take advantage of the WebAuthenticationBroker.

I've written a simple function in both JavaScript and C# that performs Dropbox authorization and returns the user's access token.

JavaScript code

app.authorizeWithDropbox = function () {
    // Be sure to replace this with your app key from dropbox.com/developers/apps.
    var appKey = "<YOUR APP KEY>";

    var vault = new Windows.Security.Credentials.PasswordVault();

    // Check for previously saved credentials.
    var creds = vault.retrieveAll();
    if (creds.length > 0) {
        var cred = creds[0];
        cred.retrievePassword();
        var accessToken = cred.password;
        return WinJS.Promise.as(accessToken);
    }

    // The redirect URI you use doesn't really matter, so feel free to use something else,
    // but this is one we've set up specifically for client-side apps to use.
    var redirectUri = "https://www.dropbox.com/1/oauth2/redirect_receiver";

    return Windows.Security.Authentication.Web.WebAuthenticationBroker.authenticateAsync(
        Windows.Security.Authentication.Web.WebAuthenticationOptions.none,
        Windows.Foundation.Uri(
            "https://www.dropbox.com/1/oauth2/authorize?response_type=token&redirect_uri="
            + redirectUri + "&client_id=" + appKey),
        Windows.Foundation.Uri(redirectUri))
    .then(function (result) {
        // Parse the URL to find the user ID and access token.
        var url = new Windows.Foundation.Uri(result.responseData);
        var decoder = new Windows.Foundation.WwwFormUrlDecoder(url.fragment.substring(1));
        var uid = decoder.getFirstValueByName("uid");
        var accessToken = decoder.getFirstValueByName("access_token");

        // Save the access token so the user doesn't have to log in next time.
        vault.add(new Windows.Security.Credentials.PasswordCredential(
            "Dropbox auth sample app",
            uid,
            accessToken
        ));

        return accessToken;
    });
};

C# code

private async Task AuthorizeWithDropbox()
{
    // Be sure to replace this with your app key from dropbox.com/developers/apps.
    var appKey = "<YOUR APP KEY>";

    // Check for previously saved credentials.
    var vault = new PasswordVault();
    var existing = vault.RetrieveAll().FirstOrDefault();
    if (existing != null)
    {
        existing.RetrievePassword();
        var accessToken = existing.Password;
        return accessToken;
    }

    // The redirect URI you use doesn't really matter, so feel free to use something else,
    // but this is one we've set up specifically for client-side apps to use.
    var redirectUri = new Uri("https://www.dropbox.com/1/oauth2/redirect_receiver");

    var uri = new Uri(
        string.Format(
            @"https://www.dropbox.com/1/oauth2/authorize?response_type=token&redirect_uri={0}&client_id={1}",
            redirectUri, appKey));
    var result = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, uri, redirectUri);

    // Parse the URL to find the user ID and access token.    
    var url = result.ResponseData.ToString();
    var decoder = new WwwFormUrlDecoder(new Uri(url).Fragment.Substring(1));
    var uid = decoder.GetFirstValueByName("uid");
    var accessToken = decoder.GetFirstValueByName("access_token");

    // Save the access token so the user doesn't have to log in next time.
    vault.Add(new PasswordCredential("Dropbox auth demo app", uid, accessToken));

    return accessToken;
}

I hope this helps those of you who are building Windows apps that integrate with Dropbox! If you have questions, please let us know on the developer forum.

New additional information about photo and video files

Posted by Leah Culver on April 10, 2014

Yesterday we launched Carousel, a beautiful gallery for all your photos and videos. Today we're happy to announce that we've updated our API to better support photos and videos.

Specifically, we've added more metadata about media files. You can now use the include_media_info parameter to fetch additional information about photos and videos in the /metadata endpoint.

Here's an example:

http://api.dropbox.com/1/metadata/auto/?include_media_info=true

{
  path: "/",
  contents: [
    {
      path: "/flower.jpg",
      photo_info: {
        time_taken: "Wed, 28 Aug 2013 18:12:02 +0000",
        lat_long: [
          37.77256666666666,
          -122.45934166666667
        ]
      },
      ...
    },
    {
      path: "/beach.mov",
      video_info: {
        duration: 4463,
        time_taken: "Fri, 13 Dec 2013 17:54:38 +0000",
        lat_long: [
          37.770338,
          -122.513565
        ]
      },
      ...
    }
  ]
  ...
}

Currently you can get the following data for each media file:

  • Photo: time taken, GPS coordinates
  • Video: time taken, GPS coordinates, video duration

The time_taken and lat_long values are generated from the Exif data associated with the media file and we've nicely formatted this data to make it more useful to developers. Apps can now display when a photo or video was taken rather than just when it was uploaded to Dropbox. This also allows for sorting a user's media by creation date.

GPS coordinates are interesting for showing where a photo or video was taken, possibly on a map view. Apps could also group photos and videos based on location.

If you're using the /delta endpoint to stay up to date with changes to the user's Dropbox, you can also use the include_media_info parameter to get this additional information. A cool use of media info in the /delta endpoint would be to find out in real-time when a photo or video is taken within a certain geo-fence.

A big thanks to our developer community for suggesting these features. We're working on adding more useful information about media files so let us know what you think on our developer forum and stay tuned for updates!

Dropbox authorization in a Windows Forms app

Posted by Steve Marx on April 04, 2014

The first step to using the Dropbox API is to have a user authorize your app to access to their Dropbox. Dropbox uses OAuth in the browser for authorization. For web apps, the process involves redirecting the user or opening a pop-up window. In our mobile apps, our SDKs can open the default browser for you and redirect back to your app. For desktop platforms (like Windows), there are really two options:

  1. Set up a custom URI scheme and use that as your OAuth redirect URI. Then you can open the default browser to the authorization page and have the user be redirected back to your app. This is probably the most secure method from a user's perspective, since they enter their credentials directly on dropbox.com and don't need to worry about a malicious app stealing their username and password. This method works similarly to what happens in our mobile SDKs. One downside of this approach is that browsers present a somewhat scary warning before redirecting to a custom URI scheme.
  2. Embed a web browser within your app. In a Windows Forms app, this is done with the WebBrowser control. This method probably provides the smoothest user experience and is the easiest to implement.

In the code below, I've written a simple Windows Forms app that uses the second option. It navigates an embedded WebBrowser control to the Dropbox authorization page and then captures the access token when the user finishes the authorization process. Note that this code doesn't handle storing the user's access token and remembering it for subsequent runs of the app, and it also doesn't handle errors (like the user deciding to cancel authorization).

private void Form1_Load(object sender, EventArgs e)
{
    // Be sure to replace this with your app key from dropbox.com/developers/apps.
    var clientID = "<YOUR APP KEY>";

    // The redirect URI you use doesn't really matter, so feel free to use something else,
    // but this is one we've set up specifically for client-side apps to use.
    var redirectUri = new Uri("https://www.dropbox.com/1/oauth2/redirect_receiver");
    var uri = string.Format(
        @"https://www.dropbox.com/1/oauth2/authorize?response_type=token&redirect_uri={0}&client_id={1}",
        redirectUri, clientID);

    webBrowser1.Navigate(uri);
}

// This method gets called when the WebBrowser control loads a new page.
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    // Make sure that this is our redirect page.
    if (e.Url.AbsoluteUri.StartsWith(@"https://www.dropbox.com/1/oauth2/redirect_receiver"))
    {
        // Parse out the access token from the URL fragment.
        var accessToken = HttpUtility.ParseQueryString(e.Url.Fragment.Substring(1))["access_token"];
        // TODO: Save the access token somewhere so the user doesn't need to log in the next time!

        // Make a call to /account/info to verify that the access token is working.
        var client = new WebClient();
        client.Headers["Authorization"] = "Bearer " + accessToken;
        var accountInfo = client.DownloadString("https://www.dropbox.com/1/account/info");
        MessageBox.Show("Account info: " + accountInfo);
    }
}

Note that I'm using the OAuth 2 token flow, which is designed for client-side apps. Read the Core OAuth documentation to learn more about the authorization flow.

Up next

In an upcoming blog post, I'll show how to use a similar mechanism to perform Dropbox auth in a Windows Store app using the WebAuthenticationBroker.

Initializing data in datastores with getOrInsert

Posted by Leah Culver on March 31, 2014

When creating apps, it's common to want to start with some initial data. The Dropbox Datastore API provides a method, getOrInsert, that makes this super easy.

For example, our game Click the Box displays the user's current level using the Datastore API. Click the Box has a datastore with a record called current_level and a field called level. The level field should start with an initial value of 0 since the user hasn't played any levels yet.

By using getOrInsert, we will either fetch an existing record or insert a new record with (optional) initial data if the record doesn't exist. Perhaps more importantly, getOrInsert is the only way to specify a record ID when inserting a record. Normally when inserting a record, the Datastore API chooses a unique ID for you, but in this case, we want to make sure our record always has the same ID. This way, even if two devices create the record while offline, the result of conflict resolution will still just be a single record.

Here's the relevant code in Click the Box:

JavaScript (code | docs)

var table = datastore.getTable('state');
var record = table.getOrInsert('current_level', { level: 0 });

iOS (code | docs)

DBTable *table = [self.store getTable:@"state"];
DBRecord *record = [table getOrInsertRecord:@"current_level" fields:@{@"level": @0} inserted:nil error:nil];

Android (code | docs)

DbxTable table = datastore.getTable("state");
DbxRecord record = table.getOrInsert("current_level", new DbxFields().set("level", 0));

Click the Box: a cross-platform, open-source game using the Datastore API

Posted by Steve Marx and Leah Culver on March 27, 2014

Here on the Dropbox developer relations team, one of our favorite things to do with the Dropbox Datastore API is to play games. Hot on the heels of our runaway successes Dropbox 2048 and Lucky Shamrock, today we're releasing Click the Box, a really simple game that demonstrates how the Datastore API can be used to sync game state.

You can play the game in your browser at clickthebox.site44.com. Try opening it in multiple browser tabs to see it sync in real-time!

Get the code!

The full source code for Click the Box is on GitHub for three different platforms: JavaScript, iOS, and Android.

All blog posts

Apr 2014Dropbox authorization in a Windows Store app
New additional information about photo and video files
Dropbox authorization in a Windows Forms app
Mar 2014Initializing data in datastores with getOrInsert
Click the Box: a cross-platform, open-source game using the Datastore API
Dropbox 2048 saves your current game and high scores
Upgrading a Dropbox OAuth 1 token to OAuth 2
Lucky Shamrock: resolving game state with the Datastore API
Feb 2014Dropbox Datastore API meetup: slides and video
Datastore API growth
Sync API and Datastore API 2.1 release
Jan 2014Dropbox Platform meetup with Guido van Rossum
Getting different sizes of thumbnails using the JavaScript Chooser
Update to the Chooser JavaScript API
Dec 2013Announcing Dropbox Python SDK 2.0
Is it Christmas? Find out with Dropbox
Writing a file with the Dropbox JavaScript SDK
Filtering Dropbox /delta results by path
Efficiently enumerating Dropbox with /delta
Python Datastore SDK beta 3
Nov 2013Announcing: OS X support for the Sync API and Datastore API
Python Datastore SDK beta 2
Dropbox at developer events in November
Low-latency notification of Dropbox file changes
Oct 2013Announcing the Python Datastore SDK and HTTP API documentation
Checking the datastore sync status in JavaScript
Sep 2013Datastore API stable release
Prepping your app for iOS 7? Dropbox SDKs have you covered
Supercharged productivity with Dropbox apps
Using the Sync API with Android Studio
Aug 2013How the Dropbox Datastore API Handles Conflicts – Part Two: Resolving Collisions
Integrating the Dropbox Datastore API with Ractive.js
Use Drop-ins with any app key
Programmatically download content from share links
Dropbox Core API and OAuth 2 "the hard way"
Dropbox + Xamarin webinar recording available
Using the Chooser with specific file extensions
Live webinar tomorrow: Dropbox + Xamarin
Jul 2013How the Datastore API Handles Conflicts – Part 1: Basics of Offline Conflict Handling
Simplifying view updates in JavaScript with the Datastore API
DBX 2013 session videos
Using OAuth 2.0 with the Core API
File type permission: access just the files your app needs
The Datastore API: a new way to store and sync app data
The Chooser, now for iOS and Android
Meet the Dropbox Saver
First timer’s guide to DBX
Introducing the Python Bee!
8 days to DBX!
Jun 2013DBX Conference Agenda
Now in beta: OAuth 2.0, File type permissions, and Sync API 1.1
Registration is open for DBX!
New developer guide and branding guidelines published
May 2013Chooser hits the mobile web
Introducing DBX - Dropbox’s first developer conference
New Core API SDK for PHP 5.3+
Apr 2013Reminder: Turning off Core API version 0 on Wednesday, May 1st, 2013
Easily add multi-select and drag-n-drop uploads with the Dropbox Chooser
Mar 2013Build great web apps, directly in Dropbox
Feb 2013Customer support and invoicing get better with the Dropbox Chooser
Introducing the Dropbox Sync API for mobile developers
2012Dropbox Chooser is already popping up in your favorite apps
Announcing the Dropbox Chooser
Using Dropbox's Delta API: Lessons Learned From Site44
Retiring the Deprecated Version 0 API
Chunked Uploads Beta
Using OAuth in "PLAINTEXT" mode
New sharing model will replace Public folder
Three's Company
A fix to the /shares API call
New "copy ref" feature and update to the /delta call
The new /delta API call (beta)
A single call for metadata and file content
Test your apps with up to five users
2011First ever Dropbox hack night
New API v1 - It's official!
Announcing... API v1 Beta!
Update for developers writing desktop apps
2010A few small changes
New Test Apps, iPhone SDK, and Documentation
Dropbox API Updates