17

I am running a nodejs + express based api server from heroku and using the dropbox-js library. Here's what I'd like to do:

  1. A user hits a specific api endpoint and kicks off the process.
  2. Generate some text files via a node process and save them on the server
  3. Transfer these files to a dropbox that I own using my own credentials (user and dropbox app).

There will never be a case when a random user needs to do this.. it's a team account and this is an internal tool.

The part that is tripping me up is that dropbox wants to open a browser window and get permission from me to connect to the app. The issue is that I obviously can't click the button when the process is running on the heroku instance.

Is there any way for me to authorize access to the app totally in node?

I feel like I could potentially use a phantomJS process to click the button - but it seems too complicated and I'd like to avoid it if possible.

Here is my authentication code:

    // Libraries
    var Dropbox         = require('dropbox');

    var DROPBOX_APP_KEY    = "key";
    var DROPBOX_APP_SECRET = "secret";

    var dbClient = new Dropbox.Client({
      key: DROPBOX_APP_KEY, secret: DROPBOX_APP_SECRET, sandbox: false
    });

    dbClient.authDriver(new Dropbox.Drivers.NodeServer(8191));

    dbClient.authenticate(function(error, client) {
      if (error) {
        console.log("Some shit happened trying to authenticate with dropbox");
        console.log(error);
        return;
      }


      client.writeFile("test.txt", "sometext", function (error, stat) {
        if (error) {
          console.log(error);
          return;
        }

        console.log("file saved!");
        console.log(stat);
      });
    });
Javier Evans
  • 173
  • 1
  • 6

2 Answers2

19

Took me a bit of testing, but it's possible.

First, you need to authenticate through the browser and save the token and token secret that are returned by Dropbox:

dbClient.authenticate(function(error, client) {
  console.log('connected...');
  console.log('token ', client.oauth.token);       // THE_TOKEN
  console.log('secret', client.oauth.tokenSecret); // THE_TOKEN_SECRET
  ...
});

Once you have the token and the secret, you can use them in the Dropbox.Client constructor:

var dbClient = new Dropbox.Client({
  key         : DROPBOX_APP_KEY,
  secret      : DROPBOX_APP_SECRET,
  sandbox     : false,
  token       : THE_TOKEN,
  tokenSecret : THE_TOKEN_SECRET
});

After that, you won't get bothered with having to authenticate through a browser anymore (or at least not until someone runs the code again without the token and the secret, which will make Dropbox generate a new token/secret pair and invalidate the old ones, or the apps credentials are revoked).

robertklep
  • 198,204
  • 35
  • 394
  • 381
  • 2
    Thank you very much for taking the time to test that out! This is exactly what I was looking for. Cheers! – Javier Evans May 02 '13 at 17:09
  • I'm not sure what I'm doing wrong, but I'm using the above code with a key, secret, token key and token secret that I know to all be valid, and I'm unable to get anything beyond an unauthorized error when I try to upload a file. What am I missing here? – Sydin Nov 15 '13 at 23:24
  • 1
    Update: My guess is this is related to dropbox-js moving to oauth2, but it seems like the credentials are changing; I'm caching a single token rather than a token and secret, and that's doing the trick. – Sydin Nov 16 '13 at 01:45
  • 2
    I found this site that makes it easy to generate an oauth2 token for use in this manner: https://dbxoauth2.site44.com – funroll Apr 23 '14 at 04:17
9

Or you can just use the Implicit grant and get the oauth token.

        var client = new Dropbox.Client({
            key: "xxxxx",
            secret: "xxxxx",
            token:"asssdsadadsadasdasdasdasdaddadadadsdsa", //got from implicit grant
            sandbox:false
        });

No need to get to the browser at all.This line is no longer required!

   client.authDriver(new Dropbox.AuthDriver.NodeServer(8191));
lonelymo
  • 3,972
  • 6
  • 28
  • 36