dropbox-v2-api
dropbox-v2-api copied to clipboard
"expired_access_token" error messages
We use your Libary in our backup project for iobroker
https://github.com/simatec/ioBroker.backitup
Dropbox currently seems to have changes that only have a token validity of 4 hours for newly created apps. This is a problem for our plugin because we use the token to upload the backups to Dropbox.
How to work around the "expired_access_token" issue?
Since recent changes to the Dropbox API, we should probably go through OAuth flow to tackle that.
Great reading on the topic (flow described) - please get familiar with this: https://developers.dropbox.com/pl-pl/oauth-guide (especially Using Refresh Tokens section)
The new package version has been released (2.5.0) which includes a new function dropboxV2Api.refreshToken(token) designed to refresh a token. Also note, that to generate long-living refresh_token we have to specify token_access_type: 'offline' option in dropboxV2Api.authenticate(), as below:
const dropbox = dropboxV2Api.authenticate({
client_id: 'APP_KEY',
client_secret: 'APP_SECRET',
redirect_uri: 'REDIRECT_URI',
token_access_type: 'offline', // if you need an offline long-living refresh token
state: 'OPTIONAL_STATE_VALUE'
});
//generate and visit authorization sevice
const authUrl = dropbox.generateAuthUrl();
//after redirection, you should receive code
dropbox.getToken(code, (err, result, response) => {
// you are authorized now!
// ...then you can refresh your token! (flow for token_access_type='offline')
dropbox.refreshToken(response.refresh_token, (err, result, response) => {
//token is refreshed!
});
});
Hopefully, that answers your question. Cheers
I have already tried this.
However, I get the error that "code" is not defined.
dropbox.getToken(code, (err, result, response) => {
What exactly is the function of the variable "code"?
And what does the variable do?
const authUrl = dropbox.generateAuthUrl();
Unfortunately the code doesn't work
Unfortunately, another test still gives the error
code is not defined
However, I get the error that "code" is not defined.
The code is what you get from OAuth flow.
Here's a full example of how to go throughout the OAuth process: https://github.com/adasq/dropbox-v2-api/blob/master/example/oauth2-flow.js
Do I also have to write the example code in my source code or is the hapi server created automatically here?
To be honest, I don't quite understand oauth2
Unfortunately this method does not work. I can't get it to work with Hapi Server etc. either.
the variable "code" is still not passed and it seems to me that Dropbox has changed something in general. It doesn't seem to accept token_access_type either
Here is the current error log
`
| backitup.0 | 2022-03-20 14:34:05.314 | error | Cannot read property 'refresh_token' of undefined |
|---|---|---|---|
| backitup.0 | 2022-03-20 14:34:05.314 | error | TypeError: Cannot read property 'refresh_token' of undefined at /opt/iobroker/node_modules/iobroker.backitup/lib/dropboxAuthenticate.js:26:39 at Request._callback (/opt/iobroker/node_modules/iobroker.backitup/node_modules/dropbox-v2-api/src/dropbox-api.js:187:8) at Request.self.callback (/opt/iobroker/node_modules/iobroker.backitup/node_modules/request/request.js:185:22) at Request.emit (events.js:400:28) at Request. |
| backitup.0 | 2022-03-20 14:34:05.314 | error | uncaught exception: Cannot read property 'refresh_token' of undefined |
| ` |
I think the problem is somewhere with opn
https://github.com/adasq/dropbox-v2-api/blob/2f2bde4e4bdddb4a036e7a8e6a2c6dac63034aee/example/oauth2-flow.js#L63
If I manually fetch the code from the browser and put it in the "code" variable, it loops through and updates the token.
Can you look there again? ... unfortunately I don't really understand the code and can't find the error.
I only copied the example code in our code and adjusted the variables with the account data
Would it be possible to read out the URL with the code with axios?
Hey @simatec
OAuth flow implies authenticating via your browser. You can't automate it. Once you open the URL (dropbox.generateAuthUrl()) and authenticate via Dropbox account you'll be responded with a code. The code then Is utilized to generate a refresh_token (via dropboxSession.getToken(code)) and ultimately to refresh this token once it's expired (dropboxSession.refreshToken(refresh_token))
Thanks for the explanation ... I think this is exactly where the problem lies. Opn wants to open the URL in a browser, which is not possible.
iobroker mostly runs on Linux machines that have no GUI and no browser.
Is there a way to query the code via request or axios?
Currently, the Dropbox documentation still says "no expiration" tokens, but the dropdown can no longer be found in the app console.
Our backup plugin works independently in the background.
In the end, the tokens would have to be updated in order to be able to use the Dropbox.
As a developer myself, I have several apps in Dropbox. All older apps still have a "no expiration" token.
If I want to create a new app, I only get "short-live".
Unfortunately, this is a very bad situation for all new users at the moment, as this token expires after 4 hours.
Maybe you have an idea how to get around that topic.
I see your point now. As described here:
Applications that require offline access to the API - meaning using the API when the end user is not actively interacting through your app - will not be able to prompt for re-authorization. These apps may instead use long-lived refresh tokens can be used to obtain new access tokens.
When using refresh tokens, your call to the /oauth2/token endpoint with the grant_type of authorization_code will return a short-lived access token and a refresh token, which should be securely stored.
you can still "refresh" a short-living token (the one that expires every 4h) by using refresh_token, which should be stored securely:
To update your access token, call the /oauth2/token endpoint - specifying your refresh_token as a parameter and using the grant_type of refresh_token. The endpoint will return a new short-lived access token and a timestamp indicating its expiration time.
The problem is your users need to walk through OAuth flow, but only once - to generate refresh_token. I've seen some implementation how to tackle that on server-side, where authentication url is printed on command-line interface, then a user can copy it, authenticate via browser and set a newly generated refresh_token in the app, which stores it securely.
I think it's a shame that the integration has changed so drastically here.
With a good 45,000 users of our plugin, this probably means a huge amount of support if suddenly saving to Dropbox no longer works.
I'll try to add authorization to our configuration menu.
If you have a link to the server side implementation for me that would be cool.
I find it very unfortunate how to use redirect URL to get access code. I don't think this can be solved really well in the GUI.
With localhost as the redirect url, you don't get a reasonable output of the code for the user, but it is only displayed very unhappily in the browser's address line.
This is certainly a very big hurdle for some users.
But thanks in advance for your help.
If you still need information about the integration from me, let me know.
Here is the link to our project.
https://github.com/simatec/ioBroker.backitup
Totally agree. Certainly, they have some strong arguments (probably security considerations) to ditch an old way of creating long-living tokens
If you have a link to the server side implementation for me that would be cool.
Sorry, I don't. I've seen this in action while using CLI (I recall Heroku CLI does it).
With a good 45,000 users of our plugin, this probably means a huge amount of support if suddenly saving to Dropbox no longer works.
Great job on your project. I can see you have UI for it so you could leverage it to implement OAuth flow.
Even more details on the OAuth flow from Dropbox: https://dropbox.tech/developers/migrating-app-permissions-and-access-tokens
I've made quite a bit of progress now and have added authorization to our configuration menu.
Now Dropbox has approved an app for productive use.
I want to make this app available to the users.
However, the authorization should be done via PKCE.
Can you please add the PKCE option for getToken and refreshToken.
I'm currently doing this with request, but it would be great if you could do it all from your library.
Here are examples of how to do this with PKCE:
getToken:
curl https://api.dropbox.com/1/oauth2/token -d code=xxxxxxxxxxxxxxxxxx -d grant_type=authorization_code -d code_verifier=xxxxxxxxxxxxxxxxxxxxxxxxxxxx -d client_id=xxxxxxxxx
refreshToken:
curl https://api.dropbox.com/1/oauth2/token -d refresh_token=xxxxxxxxxxxxxxxxxxxxxxxxx -d grant_type=refresh_token -d client_id=xxxxxxxx
it will be actually good if your examples worked in documentation you say Redirection URI is optional but cant seem to run anything without it .
and ultimately to refresh this token once it's expired (dropboxSession.refreshToken(refresh_token)) [...] you can still "refresh" a short-living token (the one that expires every 4h) by using refresh_token, which should be stored securely:
you can avoid implementing your own validity check of the access token according to the 4h expiration, by switching to the other official Dropbox JavaScript NPM package https://www.npmjs.com/package/dropbox which handles refreshing itself (you just need set dbx.auth.setRefreshToken(refresh_token) once!), see full example on https://github.com/dropbox/dropbox-sdk-js/blob/main/examples/javascript/simple-backend/code_flow_example.js