You might see that the Dropbox Community team have been busy working on some major updates to the Community itself! So, here is some info on what’s changed, what’s staying the same and what you can expect from the Dropbox Community overall.
Forum Discussion
Melisek
3 years agoExplorer | Level 3
Token refreshing C#
I'm building an app in .net and accessing the app's folder for resources. So far everything is going smoothly, but i have no idea how to refresh the token in my app. I tried using the example code fr...
Greg-DB
Dropbox Staff
As Здравко said, as long as you provide the required credentials, the Dropbox .NET SDK will handle the refresh process for you automatically. I see you've already mentioned the example of getting and using a refresh token in the OauthBasic example (non-PKCE, meant for server-side apps); there's also the OAuthPKCE example (PKCE, meant for client-side apps).
Can you elaborate on what you mean when you say it "doesn't work" for you? What have you done so far, and what specifically isn't working and how?
Melisek
3 years agoExplorer | Level 3
When i run my app, the Run task is probably stopping at some point as when i try to acces dropbox files it throws out a NullReferenceException of the DropboxClient and i have no clue on how to get the refresh token. Also the ApiKey and ApiSecret are replaced in my code.
Here is what i have inside my app so far:
public partial class RWindow : Form
{
//Dropbox stuff
private const string ApiKey = "";
private const string ApiSecret = "";
private const string LoopbackHost = "http://127.0.0.1:52475/";
// URL to receive OAuth 2 redirect from Dropbox server.
// You also need to register this redirect URL on https://www.dropbox.com/developers/apps.
private static readonly Uri RedirectUri = new Uri(LoopbackHost + "authorize");
// URL to receive access token from JS.
private static readonly Uri JSRedirectUri = new Uri(LoopbackHost + "token");
static DropboxClient dbx;
private List<string> fileNames = new List<string>();
private string folder;
public RWindow()
{
InitializeComponent();
var task = Task.Run((Func<Task>)Run);
task.Wait();
}
static async Task Run()
{
DropboxCertHelper.InitializeCertPinning();
string[] scopeList = new string[3] { "files.metadata.read", "files.content.read", "account_info.read" };
var uid = await AcquireAccessToken(scopeList, IncludeGrantedScopes.None);
if (string.IsNullOrEmpty(uid))
{
return;
}
var httpClient = new HttpClient(new WebRequestHandler { ReadWriteTimeout = 10 * 1000 })
{
Timeout = TimeSpan.FromMinutes(20)
};
try
{
var config = new DropboxClientConfig("SimplePKCEOAuthApp")
{
HttpClient = httpClient
};
dbx = new DropboxClient(Settings.Default.RefreshToken, ApiKey, config);
await dbx.RefreshAccessToken(scopeList);
await AcquireAccessToken(scopeList, IncludeGrantedScopes.User);
dbx = new DropboxClient(Settings.Default.AccessToken, Settings.Default.RefreshToken, ApiKey, ApiSecret, config);
}
catch (HttpException e)
{
Debug.WriteLine("Exception reported from RPC layer");
Debug.WriteLine(" Status code: {0}", e.StatusCode);
Debug.WriteLine(" Message : {0}", e.Message);
if (e.RequestUri != null)
{
Debug.WriteLine(" Request uri: {0}", e.RequestUri);
}
}
}
private static async Task HandleOAuth2Redirect(HttpListener http)
{
var context = await http.GetContextAsync();
// We only care about request to RedirectUri endpoint.
while (context.Request.Url.AbsolutePath != RedirectUri.AbsolutePath)
{
context = await http.GetContextAsync();
}
context.Response.ContentType = "text/html";
// Respond with a page which runs JS and sends URL fragment as query string
// to TokenRedirectUri.
using (var file = File.OpenRead("index.html"))
{
file.CopyTo(context.Response.OutputStream);
}
context.Response.OutputStream.Close();
}
private static async Task<Uri> HandleJSRedirect(HttpListener http)
{
var context = await http.GetContextAsync();
// We only care about request to TokenRedirectUri endpoint.
while (context.Request.Url.AbsolutePath != JSRedirectUri.AbsolutePath)
{
context = await http.GetContextAsync();
}
var redirectUri = new Uri(context.Request.QueryString["url_with_fragment"]);
return redirectUri;
}
private static async Task<string> AcquireAccessToken(string[] scopeList, IncludeGrantedScopes includeGrantedScopes)
{
Settings.Default.Reset();
var accessToken = Settings.Default.AccessToken;
var refreshToken = Settings.Default.RefreshToken;
if (string.IsNullOrEmpty(accessToken))
{
try
{
Debug.WriteLine("Waiting for credentials.");
var state = Guid.NewGuid().ToString("N");
var authorizeUri = DropboxOAuth2Helper.GetAuthorizeUri(OAuthResponseType.Code, ApiKey, RedirectUri, state: state, tokenAccessType: TokenAccessType.Offline, scopeList: scopeList, includeGrantedScopes: includeGrantedScopes);
var http = new HttpListener();
http.Prefixes.Add(LoopbackHost);
http.Start();
System.Diagnostics.Process.Start(authorizeUri.ToString());
// Handle OAuth redirect and send URL fragment to local server using JS.
await HandleOAuth2Redirect(http);
// Handle redirect from JS and process OAuth response.
var redirectUri = await HandleJSRedirect(http);
var tokenResult = await DropboxOAuth2Helper.ProcessCodeFlowAsync(redirectUri, ApiKey, ApiSecret, RedirectUri.ToString(), state);
accessToken = tokenResult.AccessToken;
refreshToken = tokenResult.RefreshToken;
var uid = tokenResult.Uid;
Debug.WriteLine("Uid: {0}", uid);
Debug.WriteLine("AccessToken: {0}", accessToken);
if (tokenResult.RefreshToken != null)
{
Debug.WriteLine("RefreshToken: {0}", refreshToken);
Settings.Default.RefreshToken = refreshToken;
}
if (tokenResult.ExpiresAt != null)
{
Debug.WriteLine("ExpiresAt: {0}", tokenResult.ExpiresAt);
}
if (tokenResult.ScopeList != null)
{
Debug.WriteLine("Scopes: {0}", String.Join(" ", tokenResult.ScopeList));
}
Settings.Default.AccessToken = accessToken;
Settings.Default.Uid = uid;
Settings.Default.Save();
http.Stop();
return uid;
}
catch (Exception e)
{
Debug.WriteLine("Error: {0}", e.Message);
return null;
}
}
return null;
}
//Rest of my code that handles requesting and downloading files stored in the application. Works properly when using the generated short-lived token in app console.
}
- Melisek3 years agoExplorer | Level 3
Also found this error
An error occurred trying to start process 'https://www.dropbox.com/oauth2/authorize?response_type=code&client_id=XXXXXXXXXXXXXXX&redirect_uri=http%3A%2F%2F127.0.0.1%3A52475%2Fauthorize&state=a6a4da2fe0f44dfe91c14f6a0917c8ac&token_access_type=offline&scope=files.metadata.read files.content.read account_info.read' with working directory 'C:\Programming\C#\MelisekGameManager\MelisekGameManager\bin\Debug\net6.0-windows'. Can't find specified file.: Error: {0}
- Greg-DB3 years agoDropbox Staff
To clarify, are you seeing the NullReferenceException in addition to the "Can't find specified file" error, or are you no longer getting a NullReferenceException?
Either way, is that the entirety of the error/output you're getting? Please be sure to share the whole error/output and whatever details you can if not, as it's not quite clear here. For example, if your IDE shows which line something is failing on, please show that.
Anyway, it sounds like that "Can't find specified file" error is occurring when attempting to launch the authorization URL in the system browser, on the System.Diagnostics.Process.Start line, but is the authorization page actually launching in the browser or not? It's unclear why that would fail but it may depend on your particular environment. For example, it sounds similar to this issue.
- Melisek3 years agoExplorer | Level 3
That's the entirety of the error output unless this is also paired with the error output:
Exception thrown: „System.ComponentModel.Win32Exception” in System.Diagnostics.Process.dll
The nullreference shows because the dropbox client isn't getting assigned in the Run tast as it doesn't reach this point of the task. The authorization page doesn't open.
- Здравко3 years agoLegendary | Level 20
Hi Melisek,
Are you certain that Windows machine, used as a DUT, has properly set default web browser? 🧐 Try set it anew or change to some other. If no luck yet, test again with a bit changed 'authorizeUri'. Add to following line:
Melisek wrote:...
... System.Diagnostics.Process.Start(authorizeUri.ToString());
......a real browser name to avoid relying on system settings (possibly broken). It can come up something like:
System.Diagnostics.Process.Start("firefox", authorizeUri.ToString());
Of course, other web browser can be used (on your opinion) too!
Let see the result...🤔
- Greg-DB3 years agoDropbox Staff
Melisek Thanks for following up. As Здравко said, please make sure the environment has a default web browser set.
Otherwise, it looks like you may be using Windows Forms, so please refer to this post for options, as it appears you may need to use something other than System.Diagnostics.Process.Start in that environment.
- Melisek3 years agoExplorer | Level 3
Yes i'm using WPF.
After giving the full path to the browser executable, it opens in the browser with the authorization site and for some reason opens two tabs passing into the URLS: http://files.content.read and http://account_info.read. But after allowing the app in the authorization site it throws this exception:
Exception thrown: „System.IO.FileNotFoundException” in System.Private.CoreLib.dll
Exception thrown: „System.IO.FileNotFoundException” in System.Private.CoreLib.dll
Could not find file 'C:\Programming\C#\MelisekGameManager\MelisekGameManager\bin\Debug\net6.0-windows\index.html'.: Error: {0}I think it's probably because i used the OauthBasic instead of OauthPKCE.
About Dropbox API Support & Feedback
Find help with the Dropbox API from other developers.5,917 PostsLatest Activity: 11 days ago
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 or Facebook.
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!