Bad Request 400 if using App Key and App Secret
I'm converting some existing code to use your package because the old package locked us into Guzzle 6.x. So I already have an app key, app secret, and non-expiring access token.
According to your documentation, it looks like I should be able to supply the app key and app secret in an array to the constructor of Client, or I can provide the access token as a string. The access token as a string works to connect, but with the array of app key and app secret I get a Bad Request 400 error. My test code shown below:
public function testDropboxConnection()
{
require WILDFISH_CONFIGS_DIR . '.dropbox.php';
$dropboxConfig = getWassDropboxConfig('production');
try{
$client = new \Spatie\Dropbox\Client( $dropboxConfig['accessToken'] );
// For some reason this doesn't work...
/*$client = new \Spatie\Dropbox\Client([
$dropboxConfig['appKey'],
$dropboxConfig['appSecret']
]);*/
dump( $client->getAccountInfo() );
}
catch( \Spatie\Dropbox\Exceptions\BadRequest $e )
{
if( ENVIRONMENT == 'development' && TRUE )
dump( $e );
}
catch( \Exception $e )
{
if( ENVIRONMENT == 'development' && TRUE )
dump( $e );
}
}
Since I have it working with the access token, it's not critical for me that you fix this, but it did waste some of my time, so I thought I'd leave this here so you can take a look.
Hi, i confirm this. It works with short-lived token but it doesn't work with app key/secret
Code example:
# $client = new Client('APP_TOKEN' ); # works with short-lived token
$client = new Client( [ 'APP_KEY', 'APP_SECRET' ] ); # doesn't work with app key/secret
$adapter = new DropboxAdapter($client);
$filesystem = new Filesystem($adapter, ['case_sensitive' => false]);
$filesystem->put('/some/path/to/file/' . $file , $file_content);
Error:
+dropboxCode: null
#message: ""
#code: 0
#file: "/var/www/app/current/vendor/spatie/dropbox-api/src/Client.php"
#line: 667
trace: {
/var/www/app/current/vendor/spatie/dropbox-api/src/Client.php:667 {
Spatie\Dropbox\Client->determineException(ClientException $exception): Exception …
› if (in_array($exception->getResponse()->getStatusCode(), [400, 409])) {
› return new BadRequest($exception->getResponse());
› }
}
@preBit
if it is working with short-lived token so how can we manage short-lived token after it expire?
Any solutions for token using that we dont need to add token manually when site goes to production mode.
App Authentication (Access key with Secret) only works on a couple of endpoints as per the http documentation
https://api.dropboxapi.com/2/check/app and https://content.dropboxapi.com/2/files/get_thumbnail_v2 to be specific.
You need to do everything else with a valid user token. If it's your own user token, it can be generated as non-expiring via your App console. If it's other user tokens you need to use the token refresh methods as documented in the readme.
Cheers.
See above linked dropbox documentation.
In my process, i fetch an offline token. https://www.dropbox.com/oauth2/authorize?client_id=[APP_KEY]&response_type=code&token_access_type=offline
- if token_access_type=offline, then the access token payload returned by a successful /oauth2/token call will contain a short-lived access_token and a long-lived refresh_token.
- the refresh_token can be used to request a new short-lived access token as long as a user's approval remains valid. ...
I am having the same issue. The endpoint "List Folder" is covered by App Authentication but does not work with this package.
The error message I get is
Spatie\Dropbox\Exceptions\BadRequest path/unsupported_content_type/. at vendor/spatie/dropbox-api/src/Client.php:667 +2 vendor frames
Hello, @GDmac I was reading the documentation above. I am not sure how to implement AutoRefreshingDropBoxTokenService. Please help
See https://github.com/spatie/dropbox-api/issues/75 In essence, you check if the accessToken is not expired, if so, then acquire a new accessToken with help of the refreshToken.
Can you give an example? I can't get it to work with
use Spatie\Dropbox\TokenProvider;
$tokenProvider = new AutoRefreshingDropBoxTokenService($refreshToken);
$client = new Spatie\Dropbox\Client($tokenProvider);
I had tried to put the code from https://www.dropbox.com/oauth2/authorize?client_id=%5BAPP_KEY%5D&response_type=code&token_access_type=offline to use as access token but it does not work. Can you please help?
@juliocoliveira here's an example of the implementation of the file AutoRefreshingDropBoxTokenService.php
<?php
namespace App\Services;
use Exception;
use GuzzleHttp\Client as HttpClient;
use Spatie\Dropbox\TokenProvider;
class AutoRefreshingDropBoxTokenService implements TokenProvider
{
private string $key;
private string $secret;
private string $refreshToken;
public function __construct()
{
$this->key = config('filesystems.disks.dropbox.key');
$this->secret = config('filesystems.disks.dropbox.secret');
$this->refreshToken = config('filesystems.disks.dropbox.refresh_token');
}
public function getToken(): string
{
return $this->refreshToken();
// return Cache::remember('access_token', 14000, function () {
// return $this->refreshToken();
// });
}
public function refreshToken(): string|bool
{
try {
$client = new HttpClient();
$res = $client->request(
'POST',
"https://{$this->key}:{$this->secret}@api.dropbox.com/oauth2/token",
[
'form_params' => [
'grant_type' => 'refresh_token',
'refresh_token' => $this->refreshToken,
],
]
);
if ($res->getStatusCode() == 200) {
$response = json_decode($res->getBody(), true);
return trim(json_encode($response['access_token']), '"');
} else {
return false;
}
} catch (Exception $e) {
// ray("[{$e->getCode()}] {$e->getMessage()}");
return false;
}
}
}
You should also have the .env variables:
DROPBOX_APP_KEY=<App key from dropbox website>
DROPBOX_APP_SECRET=<App scecret from dropbox website>
DROPBOX_ACCESS_TOKEN=<token generated on dropbox website>
DROPBOX_REFRESH_TOKEN=<this is created on the step 4 below >
How to get refresh token
- Visit in the browser: https://www.dropbox.com/oauth2/authorize?client_id=<APP_KEY>&response_type=code&token_access_type=offline
- copy that access code to use in the step below
- in the terminal use the access code provided above
curl https://api.dropbox.com/oauth2/token -d code=<ACCESS_CODE> -d grant_type=authorization_code -u <APP_KEY>:<APP_SECRET> - save refresh token in env variable
Hope it helps
Ahm thanks. Very helpful.