Studio-42 / elFinder

📁 Open-source file manager for web, written in JavaScript using jQuery and jQuery UI
https://studio-42.github.io/elFinder/
Other
4.64k stars 1.41k forks source link

Driver "elFinderVolumeGoogleDrive" : Required option "access_token" or "refresh_token" is undefined. #3066

Closed osworx closed 4 years ago

osworx commented 4 years ago

Using latest elFinder official release. Currently installed in a development environment Win10Pro, xampp, php 7.2 to test a plain, unmodified elFinder instance.

Embedded via composer GoogleGrive and defined required setting like: array( 'driver' => 'GoogleDrive', 'client_id' => 'CLIENT_ID', 'client_secret' => 'CLIENT_SECRET', 'path' => '/' )

Before (connector.minimal.php) defined id and key the first time (why could that not be simplified?). Using elfinder.legacy.html

And no matter what I try, I am getting always the error (see subject) at initialization. Connecting to GDrive works, redirect also, but then I see only the json output in the new window instead the elfinder popup:

{
  "exit": true,
  "error": "errReauthRequire",
  "debug": {
    "connector": "php",
    "phpver": "7.2.4",
    "time": 1.9197759628295898,
    "memory": "4675Kb / 2417Kb / 512M",
    "upload": "",
    "volumes": [
      {
        "id": "l1_",
        "name": "localfilesystem",
        "mimeDetect": "finfo",
        "imgLib": "gd"
      },
      {
        "id": "t1_",
        "name": "trash",
        "mimeDetect": "finfo",
        "imgLib": "gd"
      }
    ],
    "mountErrors": [
      "Driver \"elFinderVolumeGoogleDrive\" : Required option \"access_token\" or \"refresh_token\" is undefined."
    ],
    "phpErrors": []
  }
}

Any tip what is needed to create a successful connection without any error? Maybe a simple "Howto embed Google Drive into elFinder" with requried settings?

And yes, I have added the composer files inside the php folder - see your latest commit - while this would work also outside if the path is adopted to the autolaod file.

nao-pon commented 4 years ago

@osworx Is #1815 helpful for you? Also, if you want to permanently mount the drive of Google service account, use the option serviceAccountConfigFile.

osworx commented 4 years ago

@nao-pon Will look at this and try - report later. About the 2nd option with the service file (json): did already checked this, but finally the whole thing should be able to be operated by completely noobs - guess when using this option they are simply be overwhelmed ..

osworx commented 4 years ago

So, after testing with a few different settings, here the results:

  1. defining refresh_token only (as described here: https://github.com/Studio-42/elFinder/issues/1815
    $roots[] = [
    'driver'    => 'GoogleDrive',
    'refresh_token' => '4/uwxxxxxxxxxxxxxxxxxxxxxxxx',
    'path'      => '/'
    ];

    Result - no mount, GDrive is not enabled > errors:

mountErrors
    0
        Driver "elFinderVolumeGoogleDrive" : Array ( [0] => Array ( [0] => Invalid token format [1] => Google Drive Service could not be loaded. ) ) 

The error output in this format can be seen only after adopting the line 784 from $this->mountErrors[] = 'Driver "' . $class . '" : ' . implode(' ', $volume->error()); to $this->mountErrors[] = 'Driver "' . $class . '" : ' . print_r( $volume->error(), true ); otherwise only array is displayed!

This because errors is an array (as can be seen for example inside the elFinderVolumeGoogleDrive.class.php $errors[] = $e->getMessage(); and somewhere the array includes a second array!

Adding more custom error output, gives me more informations:

google Client > token:
Array
(
    [error] => invalid_grant
    [error_description] => Bad Request
)

Driver [elFinderVolumeGoogleDrive] volume-error:
Array
(
    [0] => Array
        (
            [0] => Invalid token format
            [1] => Google Drive Service could not be loaded.
        )

)

invalid grant comes as result from the Client function fetchAccessTokenWithRefreshToken($refreshToken = null)) { .. }

But coming back to the initial subject. access_token has to be defined as array, otherwise the initial error message is goven:

$roots[] = [
    'driver'    => 'GoogleDrive',
    'client_id' => 'ID_HERE',
    'client_secret' => 'SECRET_HERE',
    'access_token'  => [
        'access_token'  => 'ACCESS_TOKEN_HERE',
    ],
    'path'          => '/'
];

This whole thing with the net drives and mounting them is already massively boring me! It would be good to have clear instructions what, where and how to use. Beside this - a library without basic bugs (see seperate issue/pull request about unlinking $aTokenFile)

nao-pon commented 4 years ago

@osworx I cannot reproduce the problem in my environment. If it is an appropriate refresh token, use that refresh token to perform processing to obtain an array of access tokens. To get the refresh token, you need to check off-line access in the network mount dialog. Try to get it again.

osworx commented 4 years ago

Currently I am trying your recommendation of the native Google API. Basically this library is "overbloaded" > 23 MB just to make a few simple calls! Second, both Google APi and Guzzle has bugs. Third, how do you define a "appropriate refresh token"? Currently the result after granting access to google (successful), leads only to (at init):

Driver "elFinderVolumeGoogleDrive" : refresh token must be passed in or set as part of setAccessToken

Calling the Google auth service (via the popup with Option Offline), granting successfully the access, gives me only that here: grafik

No refresh_token, but the return URL has the parameter "code" which is further the access_token As can be seen, Dropbox2 is successfully established - so my implemention works.

The return params (via GET) are:

[route] => extension/module/filemanager_extended/connect
    [cmd] => netmount
    [protocol] => googledrive
    [host] => 1
    [code] => 4/uwxxxxxxxxxxxxxxxxxxxxxxxxxxx
    [scope] => https://www.googleapis.com/auth/drive

but the code (token) is not applied! Seems the elFinderVolumeGoogleDrive.class.php lines 683 ff has some problems. For me, the line 693

if (!$aToken && empty($_GET['code'])) {

inside the condition

if (isset($options['user']) && $options['user'] === 'init') {

is not used for assigning, because we are here at the 2nd stage where $options['user'] is not "init" anymore!

nao-pon commented 4 years ago

Line 693 is the process when the user performs a network mount, so it has nothing to do with permanent mount.

For permanent mounts, the Dropbox is OK with access token without refresh token. But GoogleDrive require refresh token, Please refer to my post below for how to get a refresh token.

P.S External library dependencies are needed to reduce development costs.

osworx commented 4 years ago

I already did read your comment at 1815, but the issue is (as described above https://github.com/Studio-42/elFinder/issues/3066#issuecomment-569485592) that the response from Google stay in that former opened (popup) window and displays only the json result without any refresh_token!

nao-pon commented 4 years ago

What browser are you using? Such things may happen depending on the browser. Close the popup (tab) and return to elFinder. Is network mount available?

In addition, please perform verification in the latest nightly.

osworx commented 4 years ago

Using latest FireFox (72.0.1) with enabled dev-tools (F12). Did not try with other browsers.

What do you mean with

Is network mount available?

If it would be not enabled, I could not connect to Google, accept there successfully the access to the drive and return to elFinder.