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: expired token when set to not expire

expired token when set to not expire

donaldp
Collaborator | Level 9

Have read a few posts on related topics here, and something definitely not working correctly...

 

My app was doing weird things today, and I saw a expired token exception getting thrown. This has never happened before. From reading this post https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/API-access-token-expired/td-p/363473 I can see that I do indeed have a temporary token, as it starts with "sl", but from this post https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/Tokens-only-valid-for-4-hours-from-app-... I have gone to my app console, and it is still set to never expire, so I'm not sure how I've got an sl token when it should never expire? Sounds like a bug in the system somewhere. This has only happened the once. I'm going to add some code into my app to actually try the token out first (an API to check the validity of the token would be good, but apparently there isn't one), then I'll get a fresh one and let you know if it happens again. To date I have always assumed the token was good, and it always has been... until today.

donaldp_0-1638248187089.png

 

9 Replies 9

donaldp
Collaborator | Level 9

I'm having issues with trying to catch this exception. As suggested in another post, I'm using GetCurrentAccountAsync to test if the token is valid - I've put that into a try/catch, and the catch doesn't run! THEN in later calls I start getting the expired token exceptions. i.e. GetCurrentAccountAsync doesn't seem to care that the token is expired (or at least it's not throwing an exception for it). I'm not sure which call is actually triggering the exception (I'm trying to catch it at authorisation so that it doesn't go any further).

 

CODE

DxClient??=new DropboxClient(DxToken);
try {
System.Diagnostics.Debug.WriteLine("********************************** Checking that token works");
DxClient.Users.GetCurrentAccountAsync();
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine($"********************************** Exception in changing Authorised: {ex.Message}");
return;
}
System.Diagnostics.Debug.WriteLine("********************************** Token works!");


OUTPUT
********************************** DxToken is sl......
********************************** Checking that token works
********************************** Token works!

.....
Exception thrown: 'Dropbox.Api.AuthException' in Dropbox.Api.dll
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/

 

donaldp
Collaborator | Level 9

I also tried

var result=DxClient.Users.GetCurrentAccountAsync()

in the try/catch - still no exception.

Greg-DB
Dropbox Staff

Dropbox is switching to issuing only short-lived access tokens (and optional refresh tokens) instead of long-lived access tokens. You can find more information on this migration here.

 

Apps can still get long-term access by requesting "offline" access though, in which case the app receives a "refresh token" that can be used to retrieve new short-lived access tokens as needed, without further manual user intervention. You can find an example of processing the app authorization flow for "offline" access using the Dropbox API v2 .N....

 

For reference, while the creation of new long-lived access tokens is now deprecated, we don't currently have a plan to disable existing long-lived access tokens. (If that changes, we will of course announce that ahead of time.) That being the case, you can continue using existing long-lived access token(s) without interruption. Note though that after the change you won't be able to create new long-lived access tokens.

 

While the change began on September 30th, we're releasing it gradually, so you may not have seen your app(s) affected until now. Once it applies to your app, it would apply regardless of the "Access token expiration" setting for your app.

 

In any case, to proactively check the validity of a given token, UsersUserRoutes.GetCurrentAccountAsync is a good option. You can also use CheckUserRoutes.UserAsync. Note that short-lived access tokens are only valid for a few hours though, so they can expire between checking them like that and then making additional calls later, so you'll need to make sure you have error handling, e.g., for the AuthException you showed, on every API call you make.

donaldp
Collaborator | Level 9

Hi Greg,

 

   Thanks for the extra info, but as per earlier post I'm still unable to get an exception using any of those methods. In the earlier case, I had been testing it within a C#/.NET property change. I thought perhaps it might be a limitation with properties, so I wrote the code as a separate method which I then call at the appropriate place. Still not getting an exception. So I thought, well if I'm not getting an exception, then let's assign it to something and see what's in it - I got nothing. Not a result, not a null, nothing. No further code from the method executes after the first call to the Dropbox server (i.e. none of the writelines), so it seems I'm simply not getting any response at all from the server (until I try other calls later in my app and start getting the exception). This is consistent with my first observations of incorrect behaviour in that my app displays the username or "not logged in" as the case may be, but neither was appearing on screen (so again, looks like the call was hung). Not sure what the time-out period is on such a call? At this point I'm not sure what else I can do to check the token is valid, as nothing I've tried so far works. See below (in the meantime I shall read-up about what I need to do to implement refresh tokens)...

 

CODE

async Task<bool> TokenIsValid()
{
System.Diagnostics.Debug.WriteLine($"********************************** {nameof(TokenIsValid)} is checking token {DxToken}");
DxClient??=new DropboxClient(DxToken);
try {
    Account result=await DxClient.Users.GetCurrentAccountAsync();
    if (result!=null) {
        System.Diagnostics.Debug.WriteLine($"********************************** Name in result is {result.Name}");
    } else {
        System.Diagnostics.Debug.WriteLine($"********************************** Result is null!!");
    }
}
catch (Exception ex) {
    System.Diagnostics.Debug.WriteLine($"********************************** Exception in {nameof(TokenIsValid)}: {ex.Message}");
    return false;
}
System.Diagnostics.Debug.WriteLine($"********************************** Token is valid!");
return true;
}

 

OUTPUT (note that I have no further output from TokenIsValid after that first writeline)

********************************** DropboxService is being initialised
********************************** TokenIsValid is checking token sl.....
********************************** OnAuthorisedChanged is running with value Authorised:True
********************************** DropboxService has been initialised
Exception thrown: 'Dropbox.Api.AuthException' in Dropbox.Api.dll
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/..
at Dropbox.Api.DropboxRequestHandler.RequestJsonString(String host, String routeName, String auth, RouteStyle routeStyle, String requestArg, Stream body); Request Id: b156453a19334fd0bfd773534492fe9c
Exception thrown: 'Dropbox.Api.AuthException' in System.Private.CoreLib.dll
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/..
at Dropbox.Api.DropboxRequestHandler.RequestJsonString(String host, String routeName, String auth, RouteStyle routeStyle, String requestArg, Stream body)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(); Request Id: b156453a19334fd0bfd773534492fe9c

 

thanks,

   Donald.

donaldp
Collaborator | Level 9

So tonight my screens went black all of a sudden, but computer didn't crash, so I did a hot-restart - Visual Studio was open at the time. When I re-opened everything and tried my app again to see if I'd lost anything (don't remember where I last saved) I was getting a response to my token-check! This brings up a few points...

1. maybe something glitchy on my machine?

2. maybe something glitchy on the server which is now resolved?

3. it did indeed take a while - heaps of other messages before the response - but I hadn't put any time-stamps in, so I'm not sure exactly how long it took, but it was a while.

4. the qualifier here is that it was no longer the same token, as I'd given up on that issue for today and signed out and back in so I could do some other work. Perhaps related to the token itself? I'll have to look into it some more when this token expires.

Greg-DB
Dropbox Staff

Thanks for following up. I can't say for sure exactly what happened here, but I'm glad to hear you got this working. For reference, any given access token, expired or not, shouldn't cause an API call to hang. The server would respond with either success or an error, or the call would eventually time out if there's a network issue. If you can reproduce the issue though, let us know how to do so and we'll be happy to look into it.

donaldp
Collaborator | Level 9

Hi Greg,

 

   Sorry didn't reply before. No, I didn't actually get it working yet with an expired token - my code was working because I had an unexpired token now. I still haven't had the code around an expired token work yet, but since I had an unexpired token I've had to move onto more urgent things. I'll be coming back to this when I have time.

donaldp
Collaborator | Level 9

Hi @Greg-DB ,

 

   Now that I have my hands on an expired token again (and a bit of time) I'm circling back to this issue, as I'm now seeing the same results (and I want to get all my expired access token catching handled before I turn back to the code changes I still need to make for refresh tokens).

 

   So, as before I'm using GetCurrentAccountAsync to test if the token is valid (since there's no method to check if a token is valid). I have a global exception catcher in the root of the app. I also have the GetCurrentAccountAsync call in a try/catch (and this itself is being called by an AuthoriseAsync method, which is also in a try/catch). Despite all this, the GetCurrentAccountAsync call never returns, never catches an exception, and yet the expired access token exception does indeed show up in my global exception catcher, so I don't know how it's showing up there but not getting caught by any of the local catches (which of course is where you want to deal with it in the first place)?

 

So here's the relevant lines of code...

 

 

// Root of the App
public App() {
AppDomain.CurrentDomain.FirstChanceException+=CurrentDomain_FirstChanceException;
...
private void CurrentDomain_FirstChanceException(object sender,System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e) {
    Trace.WriteLine($"********************************** UNHANDLED EXCEPTION! Details: {e.Exception}");
    }

// Dropbox class
public async Task AuthoriseAsync(string code="")
{
Trace.Write($"******************* {nameof(AuthoriseAsync)} has started\r\n");
Trace.Write($"******************* DxAccessToken is {DxAccessToken}\r\n");
try {
if (DxAccessToken is string s && s!=string.Empty) {
    await GetAccountNameAsync();
...
catch (Exception ex) {
    Trace.Write($"******************* EXCEPTION! in {nameof(AuthoriseAsync)} {ex.Message}\r\n");
    }

public async Task<string> GetAccountNameAsync(string NameType="")
{
Trace.Write($"******************* {nameof(GetAccountNameAsync)} has started\r\n");
try {
    Trace.Write($"******************* {nameof(GetAccountNameAsync)} is getting account info\r\n");
    Account account=await DxClient.Users.GetCurrentAccountAsync();
    Trace.Write($"******************* DisplayName is {account.Name.DisplayName}\r\n");
...
catch (Exception ex) {
    DxS=$"******************* EXCEPTION! {ex.Message}";
    UserNameText="Not logged in";

 

 

And here's the relevant output...

******************* AuthoriseAsync has started
******************* DxAccessToken is sl.BOypWqVzNCIJWfm3j..........
******************* GetAccountNameAsync has started
******************* GetAccountNameAsync is getting account info
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/
at Dropbox.Api.DropboxRequestHandler.RequestJsonString(String host, String routeName, String auth, RouteStyle routeStyle, String requestArg, Stream body); Request Id: f9474eb56bf049b7ac81dad99e59ce34
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/
at Dropbox.Api.DropboxRequestHandler.RequestJsonString(String host, String routeName, String auth, RouteStyle routeStyle, String requestArg, Stream body)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(); Request Id: f9474eb56bf049b7ac81dad99e59ce34
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/..
at Dropbox.Api.DropboxRequestHandler.RequestJsonString(String host, String routeName, String auth, RouteStyle routeStyle, String requestArg, Stream body); Request Id: 49117d5a4aea489c8dac85b8fefac953
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/..
at Dropbox.Api.DropboxRequestHandler.RequestJsonString(String host, String routeName, String auth, RouteStyle routeStyle, String requestArg, Stream body)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(); Request Id: 49117d5a4aea489c8dac85b8fefac953
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/..
at Dropbox.Api.DropboxRequestHandler.RequestJsonString(String host, String routeName, String auth, RouteStyle routeStyle, String requestArg, Stream body); Request Id: ad3db026e54c44318576b21a4ad53526
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/..
at Dropbox.Api.DropboxRequestHandler.RequestJsonString(String host, String routeName, String auth, RouteStyle routeStyle, String requestArg, Stream body)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(); Request Id: ad3db026e54c44318576b21a4ad53526
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/..
at Dropbox.Api.DropboxRequestHandler.RequestJsonString(String host, String routeName, String auth, RouteStyle routeStyle, String requestArg, Stream body); Request Id: 5033af5fb84943c6aef843ff3c8a6664
********************************** UNHANDLED EXCEPTION! Details: Dropbox.Api.AuthException: expired_access_token/..
at Dropbox.Api.DropboxRequestHandler.RequestJsonString(String host, String routeName, String auth, RouteStyle routeStyle, String requestArg, Stream body)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(); Request Id: 5033af5fb84943c6aef843ff3c8a6664

So none of those catches actually work - as far as I can see the app just gets stuck trying to get the account name with an expired token - and the exception only shows up in the global exception catcher in the root of the app. Do you know what's going on here? Oh also AuthoriseAsync is being called from the Dropbox class constructor (so the user doesn't have to login again if the token is still valid) - might be relevant.

 

Now that I know how to get the actual expiry-time of the token I can write some code around that, but also I would like to make sure all my exception-catching is working, and it's clearly not when it comes to calling GetCurrentAccountAsync.

 

thanks,

  Donald.

Greg-DB
Dropbox Staff

@donaldp Unfortunately it's not clear why that is occurring for you. I just tried and I am able to catch the expired_access_token Exception from a GetCurrentAccountAsync call when made with a DropboxClient with an expired short-lived access token and no refresh token.

 

I can't offer much insight with .NET or C# itself, but it sounds like there may be something about your project/environment impacting how exception handling is working for you. Do you have any unusual configuration in your project or environment?

Need more support?