cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements
Want to learn some quick and useful tips to make your day easier? Check out how Calvin uses Replay to get feedback from other teams at Dropbox here.

Dropbox API Support & Feedback

Find help with the Dropbox API from other developers.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Re: OAuth2 issues with Dropbox and Xamarin.Auth

OAuth2 issues with Dropbox and Xamarin.Auth

PaulELong
Helpful | Level 6
Go to solution

I have Xamarin.Auth working with Google drive on Android/iOS/UWP, and I want to add support into my app for Dropbox. Xamarin.Auth is nice because I only have to write the code once, and it handles a lot of the complications. It works with multiple oauth like Twitter, facebook and others. But I've run into an issue with the redirect_uri when using Xamarin.Auth. For Google Drive, the google webpage creates a redirect like "com.googleusercontent.apps...". The deep link allows my app to wake up when the redirect occurs. My hope was to quickly extend this to Dropbox, but the options for redirect URI seem limited.

Dropbox allows you to specify a Redirect URI of either "https://something.here" or a loopback like "http://127.0.0.1/authorize". I can also enter "anything://anything_else" into the website. But I can't enter a deep link address, like "com.something/oauth2redirect". If I use https://something.here, the redirect attempts to load a webpage, which of course doesn't exist. If I use a deep link, dropbox API complains that it's not valid and must start with https. If I use a loopback address, my app doesn't wake up automatically, though I'm not sure how it would.

Does anybody have some advice on how to make Dropbox work with Xamarin.Auth, is this possible?

Is there there a cross platform solution I can leverage? Or do I have to create a unique (and way more expensive) solution individually for iOS and Android?

Thanks - Paul

1 Accepted Solution

Accepted Solutions

PaulELong
Helpful | Level 6
Go to solution

I found the solution, but to answer your question first, the text is output from a sniffer trace showing the HTTP Get request.

And you are right, in that the second response_type and client_id are a duplication.  It confused me and at first I thought it was the HTTP body.  One thing I didn't understand is that GetAuthorizeUri returns the URL plus the params.  Xamarin.Auth requires just the URL, so I can just send "https://www.dropbox.com/oauth2/authorize", and I won't call GetAuthorizeUri at all, since OAuth2Authenticator takes care of building the request.

The reason there were two response_types where one was code type rather than token type was because I supplied the AccessTokenURL to OAuth2Authenticator, which is not needed in the case of token flow, as I understand.  Since I started with a dropbox API example for .NET and then plugged in each into the OAuth2Authenticator call, I mistakenly sent an AccessTokenUrl.  I found out from looking at the Xamarin code, if AccessTokenUrl==NULL will assume the implict flow (token flow).  Interestingly, and as a note to help others, I tried setting the AccessTokenUrl to null, which caused an exception.  Instead I found this version worked and now I'm authenticating.

authenticator = new Xamarin.Auth.OAuth2Authenticator(
clientId: ApiKey,
scope: "",
authorizeUrl: new Uri("https://www.dropbox.com/oauth2/authorize"),
redirectUrl: new Uri(RedirectUri),
isUsingNativeUI: false) ;

Hope this information helps somebody else trying to get Xamarin.Auth working with Dropbox.

 

View solution in original post

6 Replies 6

Greg-DB
Dropbox Staff
Go to solution

First, I should note that we can't provide support for or endorse any other third party products or libraries, such as Xamarin.Auth.

That said, on the Dropbox side of things, it's true that in the Dropbox OAuth 2 implementation, as a security feature, when using the "code" flow, the redirect URI (if provided) must start with https:// (except for localhost addresses).

So, depending on your use case, there are a few options that might make sense:

  • use the "token" flow instead of the "code" flow: for the "token" flow, redirect URIs with custom URL schemes (like "anything://anything_else", which you'd register for your local app) are allowed. You can find more information on the two supported flows in the /oauth2/authorize documentation. The "token" flow is generally recommended for client-side apps anyway.
  • use the "code" flow, using a http://localhost... redirect URI.
  • use the "code" flow, omit the redirect URI entirely: in this case, the user would need to manually copy/paste the authorization code that Dropbox would present to them

PaulELong
Helpful | Level 6
Go to solution

Based on your response I looked at a network trace because I thought I was using the token flow.  But I see in the trace it sends the token flow in the HTTP header and code flow in the HTTP body.  That seems strange so I'm following up with Xamarin.Auth folks.  

Can you verify you use the HTTP body and the header to validate the code flow?  The packet looks like this:

GET /oauth2/authorize?response_type=token&client_id=ommited&redirect_uri=com.paulyshotel.testcloud%3A%2F%2Foauth2rediect%2F&state=c4045458ac394ad78752fad786151f5e?client_id=b2w6zorouokifto&redirect_uri=com.paulyshotel.testcloud%3A%2F%2Foauth2rediect&scope=&response_type=code

Thanks -Paul

 

Greg-DB
Dropbox Staff
Go to solution

The /oauth2/authorize location is a web page, and you should just be sending the user there in their browser, so the browser should just make a GET request to it. There shouldn't be a body for that HTTP GET request, nor would Dropbox use any parameters sent in the body. The URL parameters on the URL path itself are used.

PaulELong
Helpful | Level 6
Go to solution

You mentioned above that "it's true that in the Dropbox OAuth 2 implementation, as a security feature, when using the "code" flow, the redirect URI (if provided) must start with https:// (except for localhost addresses)."   And then you mention "use the "token" flow instead".  What I'm showing you above is that the GET request my app sends has set the parameter response_type=token as per the documentaiton link you provided above.

However, the result is that dropbox returns and error stating "Invalid redirect_uri. When response_type=code, redirect_uri must start with "https://", unless it's a localhost URI."

Why am I getting this message?

 

Greg-DB
Dropbox Staff
Go to solution

I'm not sure exactly what you were outputing for that GET request. Can you clarify exactly what you're logging and what is actually being sent to Dropbox? In your sample you repeated the 'response_type' parameter, which isn't expected. It's unclear if that's repeated in the URL parameters themselves, or if one is in the URL parameters and one is in the request body, for instance. 

Here are a few examples I just put together for reference, based on your output above, using your deep link redirect URI. You can try them directly in your browser by clicking on them.

This is a valid /oauth2/authorize URL for the token flow:
https://www.dropbox.com/oauth2/authorize?response_type=token&client_id=aa0sxbl9gon603m&redirect_uri=...
Dropbox allows this configuration.

This is an invalid /oauth2/authorize URL for the code flow:
https://www.dropbox.com/oauth2/authorize?client_id=aa0sxbl9gon603m&redirect_uri=com.paulyshotel.test...
Dropbox rejects this configuration with "Invalid redirect_uri. When response_type=code, redirect_uri must start with "https://", unless it's a localhost URI.".

This is an invalid /oauth2/authorize URL:
https://www.dropbox.com/oauth2/authorize?response_type=token&client_id=aa0sxbl9gon603m&redirect_uri=...
This is invalid, because you're supplying the 'client_id' and 'response_type' parameters twice, and since you're supplying an unexpected/undocumented 'scope' parameter. Dropbox rejects this configuration with "Invalid redirect_uri. When response_type=code, redirect_uri must start with "https://", unless it's a localhost URI." (Also, in your output your redirect URI was also specified twice, but I removed that for the sake of simplicity.)

If you do supply the 'response_type' parameter twice, it appears Dropbox will use the second one. (This isn't guaranteed though; supplying a single parameter twice is unexpected and the behavior should be considered undefined. Accordingly, please make sure you don't do so.) That may have been what was resulting in the confusing result, so please make sure you're only supplying each parameter once.

PaulELong
Helpful | Level 6
Go to solution

I found the solution, but to answer your question first, the text is output from a sniffer trace showing the HTTP Get request.

And you are right, in that the second response_type and client_id are a duplication.  It confused me and at first I thought it was the HTTP body.  One thing I didn't understand is that GetAuthorizeUri returns the URL plus the params.  Xamarin.Auth requires just the URL, so I can just send "https://www.dropbox.com/oauth2/authorize", and I won't call GetAuthorizeUri at all, since OAuth2Authenticator takes care of building the request.

The reason there were two response_types where one was code type rather than token type was because I supplied the AccessTokenURL to OAuth2Authenticator, which is not needed in the case of token flow, as I understand.  Since I started with a dropbox API example for .NET and then plugged in each into the OAuth2Authenticator call, I mistakenly sent an AccessTokenUrl.  I found out from looking at the Xamarin code, if AccessTokenUrl==NULL will assume the implict flow (token flow).  Interestingly, and as a note to help others, I tried setting the AccessTokenUrl to null, which caused an exception.  Instead I found this version worked and now I'm authenticating.

authenticator = new Xamarin.Auth.OAuth2Authenticator(
clientId: ApiKey,
scope: "",
authorizeUrl: new Uri("https://www.dropbox.com/oauth2/authorize"),
redirectUrl: new Uri(RedirectUri),
isUsingNativeUI: false) ;

Hope this information helps somebody else trying to get Xamarin.Auth working with Dropbox.

 

Need more support?