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
odoerlek
6 months agoExplorer | Level 3
Issues with Token Expiry and Auto-Refreshing in SwiftyDropbox for multiusers
Hi everyone,
I'm having trouble with managing multiple users in my app using SwiftyDropbox. While I can connect users, their tokens are expiring and not auto-refreshing as expected. Here are some snippets of my implementation:
public func setupWithAppKeyMultiUserDesktop(_ key: String) {
DropboxClientsManager.setupWithAppKeyMultiUserDesktop(key, tokenUid: nil)
NSAppleEventManager.shared().setEventHandler(self,
andSelector: #selector(handleGetURLEvent),
forEventClass: AEEventClass(kInternetEventClass),
andEventID: AEEventID(kAEGetURL))
}
@objc func handleGetURLEvent(_ event: NSAppleEventDescriptor?, replyEvent: NSAppleEventDescriptor?) {
if let aeEventDescriptor = event?.paramDescriptor(forKeyword: AEKeyword(keyDirectObject)),
let urlStr = aeEventDescriptor.stringValue, let url = URL(string: urlStr) {
let oauthCompletion: DropboxOAuthCompletion = {
if let authResult = $0 {
switch authResult {
case .success(let accessToken):
let tokenUid = accessToken.uid
self.clients[tokenUid] = DropboxClient(accessToken: accessToken.accessToken)
self.fetchUserData(tokenUid: tokenUid)
case .cancel:
print("Authorization flow was manually canceled by user!")
case .error(_, let description):
print("Error: \(String(describing: description))")
}
}
}
DropboxClientsManager.handleRedirectURL(url, includeBackgroundClient: false, completion: oauthCompletion)
NSApp.activate(ignoringOtherApps: true)
}
}
private func fetchUserData(tokenUid: String) {
guard let client = clients[tokenUid] else { return }
client.users.getCurrentAccount().response { result, error in
if let userData = result {
let account = DropboxAccount(tokenUid: tokenUid, fullAccount: userData)
self.connectedAccounts.append(account)
} else if let error {
if case .authError(let authError, _, _, _) = error, case .expiredAccessToken = authError {
DropboxClientsManager.reauthorizeClient(tokenUid)
self.fetchUserData(tokenUid: tokenUid)
}
}
}
}
Despite the reauthorization logic, tokens are not refreshing correctly. Any advice on how to resolve this issue would be greatly appreciated.
Thanks
- Greg-DBDropbox Staff
odoerlek Здравко is correct; in order for the SDK to perform the refresh for you automatically, the client needs to have the necessary credentials, such as the refresh token. In your code you are creating DropboxClient objects with only the access token but not the refresh token, so it can't refresh for you automatically.
I recommend using the client management functionality built in to the SDK whenever possible. For instance, you can use use DropboxClientsManager.reauthorizeClient to switch between stored clients (including their refresh tokens), so that you can then use the DropboxClientsManager.authorizedClient provided by the client. Calling reauthorizeClient will update which client is returned by DropboxClientsManager.authorizedClient.
If you do want to create and manage the clients yourself though, you'll need to make sure you supply the refresh tokens as well, in which case it will catch and handle expired access token errors for you automatically.
- ЗдравкоLegendary | Level 20
odoerlek wrote:... While I can connect users, their tokens are expiring and not auto-refreshing as expected.
...
Hi odoerlek,
I don't know what you expect to be, but to work refresh process, your Dropbox client object needs to be initialized with refresh token as well as other credentials like application key, not only access token, as you do:
odoerlek wrote:...
... self.clients[tokenUid] = DropboxClient(accessToken: accessToken.accessToken) ...
...
Hope this gives direction.
- odoerlekExplorer | Level 3
Generally, in the application, I want to enable the user to log in to multiple Dropbox accounts so that they have access to all of them in one place. Initially, when I set it up for a single account, it worked well. However, after switching to 'setupWithAppKeyMultiUserDesktop', everything works until the access token expires, which is after four hours. After this time, the token does not refresh automatically as it did for a single account, which means I don't have access to the account data (unless I log in again, but as we know, the access token will be new then, but still only valid for 4 hours).
- ЗдравкоLegendary | Level 20
odoerlek wrote:... Initially, when I set it up for a single account, it worked well. However, after switching to 'setupWithAppKeyMultiUserDesktop', everything works until the access token expires, ...
odoerlek, Single user or multi user implementation doesn't affect how every single client object behaves. The only difference is (or has to be at least) that you have one or multiple client objects.
As seems you have changed something else too. I don't know what, but you should know. Dropbox client object may be initialized in different ways as could be seen here. Most of them support automatic refresh (all but one actually). You have selected in your code the only that doesn't support it. 🤷 There is static token initialization - no refresh!
Take a bit more care. 😉
About Dropbox API Support & Feedback
Find help with the Dropbox API from other developers.
5,885 PostsLatest Activity: 12 hours agoIf 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!