0

I'm attempting to implement file uploading to Dropbox on my site. However, I'm having trouble getting the accessToken after the user clicks to authorize my app.

Here is my code to grab the URL, which gets returned to the client to open a new window in Javascript.

[WebMethod]
public String setUpDropboxOA(String uri, Int32 form_id, String user_auth)
{
    var client = new DropNetClient("xxxxxxxxx", "xxxxxxxxx");
    return client.GetTokenAndBuildUrl(uri);
}

And here is my callback function:

[WebMethod]
public void AuthorizeDropboxCallback(String oauth_token)
{
    var client = new DropNetClient("xxxxxxxxx", "xxxxxxxxx");
    var accessToken = client.GetAccessToken();
    var jsonObj = new { oauth_token = accessToken.Token, oauth_secret = accessToken.Secret };
    var JSONAuthorizationData = JsonConvert.SerializeObject(jsonObj);
    saveNotification(form_hash, "Dropbox", JSONAuthorizationData, user_id);
}

And here is the error that I'm getting on client.GetAccessToken():

Exception of type 'DropNet.Exceptions.DropboxException' was thrown.

The documentation of DropNet says that there is an overload to GetAccessToken that will allow you to specify a token to use, however, I'm not seeing one. I feel like this is the problem here, but I'm not entirely sure.

NoxelNyx
  • 995
  • 1
  • 7
  • 21

2 Answers2

1

As @albattran's answer suggested it is because you are creating 2 different instances of the DropNetClient.

client.GetTokenAndBuildUrl(uri);

Thismethod actually does 2 things under the hood. 1, Makes an API call to Dropbox to get a request token then using that request token it creates the login url.

To solve this you will need a way to store that request token between web requests.

Maybe think about something like the below using the session.

var userToken = client.GetToken();
Session["user_token"] = userToken.Token;
Session["user_secret"] = userToken.Secret;

Then ok the callback read those session variables and add them to the constructor overload of the DropNetClient.

var token = Session["user_token"];
var secret = Session["user_secret"];
var client = new DropNetClient("XXXX", "XXXX", token, secret);
client.GetAccessToken();
dkarzon
  • 7,868
  • 9
  • 48
  • 61
  • Isn't it bad practice to use session variables in WebMethods? Also, wouldn't this still not work since we are trying to set the session variable before the user has clicked authorize? I'm returning the URL back to the success of an AJAX call which then opens the window with Javascript. Seems the token and the secret wouldn't exist yet. – NoxelNyx Sep 12 '14 at 13:34
  • It doesn't need to be a session variable, but you need to store it somewhere, otherwise your oAuth process is broken. – albattran Sep 13 '14 at 03:07
  • Sorry the session variable example was just an example to explain as I just did the answer off the top of my head but the point is you need the request token from when you requested the user to login to get the access token. – dkarzon Sep 14 '14 at 08:53
  • Since the request token doesn't exist yet, I ended up storing the client itself instead. This worked. If you change your answer to store the client, I will mark it as the answer. – NoxelNyx Sep 15 '14 at 13:52
  • @Nyx No I don't think that's what you want to do there. You want to call the `client.GetToken()` method and save that then prompt the user for login using `client.BuildAuthorizeUrl()` Then once you have got the login callback create an instance of the DropNetClient using the saved request token and then convert it to an access token with `client.GetAccessToken()` – dkarzon Sep 15 '14 at 21:34
  • This does work, but why not just store the client to cut back on code and avoid having to create a new instance of DropNetClient? Is there a performance issue, or perhaps a security one? – NoxelNyx Sep 16 '14 at 14:09
  • The main problem would be that storing a non-data object could be a security issue, if someone could get access to that they would also have your API keys and with that could potentially access your users dropbox accounts. But you are also storing a whole lot more info than you need to, the DropNetClient has a lot of properties that are not specific to the user you are authenticating. General rule of thumb when using caching/session is to only store what you need to save on the memory footprint and also less memory used by sessions means more memory for hosting your site. – dkarzon Sep 16 '14 at 22:07
0

I think your problem is a result of losing the instance of DropNetClient between the different requests, you are creating two instances of DropNetClient.

You need to persist the initial token form GetTokenAndBuildUrl and restore it when you call GetAccessToken.

Because oAuth is 3 steps:

  1. Get Request Token
  2. Send user for authorization, and get back verifier
  3. Get Access token using the original Request Token and the verifier
albattran
  • 1,887
  • 1
  • 12
  • 16
  • Seeing as I'm returning out of the method to Javascript, is it possible to keep using the same instance? This is why I was wondering about the Dropnet documentation saying that GetAccessToken can be overloaded to accept its own token. – NoxelNyx Sep 11 '14 at 20:19