Need to see if your shared folder is taking up space on your dropbox 👨💻? Find out how to check here.
Forum Discussion
gregarican
4 years agoExplorer | Level 4
C# Dropbox.API File Upload Errors
I'm using the most recent NuGet package for my VS 2019 project. My app has worked consistently for several years now. But recently I have logged errors when invoking the client.Files.UploadAsync() me...
- 4 years ago
Yes, for the official Dropbox API v2 .NET SDK, you can find an example of using the new authorization functionality in the OauthBasic example (non-PKCE, meant for server-side apps) as well as in the OAuthPKCE example (PKCE, meant for client-side apps).
gregarican
4 years agoExplorer | Level 4
Okay, I'm making headway recoding my project to account for the new mechanism. I'm hitting a stumbling block trying to perform the second half of the initial OAuth2 process. Taking the code that's supplied in the URI and getting the refresh token. Below is a code snippet. I'm using a WebView2 form to run through the process, since it can run as user-level and doesn't require local admin rights.
The choke point is when my routine hits the ProcessCodeFlowAsync() step. It consistently comes back with an invalid_grant exception. I've run across other posts on here where there were multiple calls going on, and the duplication was leading to this. But I'm only initially hitting this step once, when I first launch my app.
Any suggestions on where to go from here? I do appreciate all of your timely assistance. It's been very helpful!
private async void Start(string appKey, string appPwd)
{
this.ApiKey = appKey;
this.ApiPwd = appPwd;
this.oauth2State = Guid.NewGuid().ToString("N");
var authorizeUri = DropboxOAuth2Helper.GetAuthorizeUri(OAuthResponseType.Code, appKey, new Uri(RedirectUri), state: oauth2State, tokenAccessType: TokenAccessType.Offline);
await this.Browser.EnsureCoreWebView2Async(null);
this.Browser.CoreWebView2.Navigate(authorizeUri.ToString());
this.Visibility = Visibility.Visible;
this.Focus();
}
private void BrowserNavigating(object sender, CoreWebView2NavigationStartingEventArgs e)
{
if (!e.Uri.ToString().StartsWith(RedirectUri, StringComparison.OrdinalIgnoreCase))
{
// we need to ignore all navigation that isn't to the redirect uri.
return;
}
try
{
var uri = new Uri(e.Uri, UriKind.Absolute);
var queryParm = uri.Query;
var code = queryParm.Split('=')[1];
var tokenResult = Task.Run(() => DropboxOAuth2Helper.ProcessCodeFlowAsync(responseUri: uri, appKey: this.ApiKey, appSecret: this.ApiPwd, state: this.oauth2State)).Result;
this.AccessToken = tokenResult.AccessToken;
this.RefreshToken = tokenResult.RefreshToken;
this.UserId = tokenResult.Uid;
this.Result = true;
}
catch (ArgumentException)
{
// There was an error in the code being processed.
}
finally
{
e.Cancel = true;
this.Close();
}
}
Greg-DB
Dropbox Community Moderator
4 years agoAn 'invalid_grant' error can indicate that the values you're supplying to ProcessCodeFlowAsync don't match the configuration used with GetAuthorizeUri to get that particular authorization. For instance, I see you're using a redirect URI ('new Uri(RedirectUri)') with GetAuthorizeUri. In that case, you need to supply that same redirect URI to ProcessCodeFlowAsync to validate that request.
That is, in addition to setting the 'responseUri' parameter on ProcessCodeFlowAsync, you should set 'redirectUri' as well (matching the 'redirectUri' value you gave to GetAuthorizeUri).
By the way, I should mention that we don't officially support processing the OAuth app authorization flow in a web view. The OAuth app authorization flow should be processed in the user's system browser. See here for more information. It sounds like we don't have a full sample app that meets your use case exactly, but I have a post here with some information that may be helpful.
- gregarican4 years agoExplorer | Level 4
That did the trick! I just modified the one line for that second step so it's now below (added the argument in bold italics):
var tokenResult = Task.Run(() => DropboxOAuth2Helper.ProcessCodeFlowAsync(responseUri: uri, appKey: this.ApiKey, appSecret: this.ApiPwd, state: this.oauth2State, redirectUri: RedirectUri)).Result;
Now previously I was only connecting to the API by checking tokens when first launching my app. You're saying my client will automatically pull new access tokens once the old ones expire? So the refresh token remains static and the access token is automatically refreshed?
Here is my code where I instantiate the client when the app first launches.
DropboxCertHelper.InitializeCertPinning();
DropboxClient client;
var httpClient = new HttpClient(new WebRequestHandler { ReadWriteTimeout = 10 * 1000 })
{
Timeout = TimeSpan.FromMinutes(20)
};var config = new DropboxClientConfig("DcDocScanner")
{
HttpClient = httpClient
};config.HttpClient.Timeout = new TimeSpan(0, 5, 0);
client = new DropboxClient(Properties.Settings.Default.AccessToken, Properties.Settings.Default.RefreshToken, Properties.Settings.Default.DropboxApiKey, Properties.Settings.Default.DropboxApiPwd, config);
- Greg-DB4 years ago
Dropbox Community Moderator
Great, I'm glad to hear that fixed it.
And yes, the refresh token doesn't change or expire, and can be re-used multiple times. When you pass it to the DropboxClient like this, the client will automatically perform the refresh to get a new short-lived access token whenever needed, without you needing to do anything extra. (Note that just like with long-lived access tokens though, refresh tokens can be revoked on demand by the app or user.)
- gregarican4 years agoExplorer | Level 4
Quick follow-up to this long thread 😅 I was still running into the expired access token exception, but this was because of the method overload I was using for instantiating the DropboxClient. I was using this:
client = new DropboxClient(Properties.Settings.Default.AccessToken, Properties.Settings.Default.RefreshToken, Properties.Settings.Default.DropboxApiKey, Properties.Settings.Default.DropboxApiPwd, config);
Apparently referencing the access token value (even an old/expired one) was throwing a monkey wrench into the works. So I changed this to:
client = new DropboxClient(Properties.Settings.Default.RefreshToken, Properties.Settings.Default.DropboxApiKey, Properties.Settings.Default.DropboxApiPwd, config);
await client.RefreshAccessToken(null);
Leaving out the access token argument and forcing an access token refresh appears to have cleaned things up. There are a lot of method overloads for creating a new DropboxClient instance, and I got lost in the sauce. But all fine now.
Thanks again for all of the timely, helpful feedback. Honestly most API service providers aren't anywhere as responsive and supportive as I've experience on here!
About Dropbox API Support & Feedback
Find help with the Dropbox API from other developers.
The Dropbox Community team is active from Monday to Friday. We try to respond to you as soon as we can, usually within 2 hours.
If you need more help you can view your support options (expected response time for an email or ticket is 24 hours), or contact us on X, Facebook or Instagram.
For more info on available support options for your Dropbox plan, see this article.
If you found the answer to your question in this Community thread, please 'like' the post to say thanks and to let us know it was useful!