How can I make PHP to access a given normal-user DRIVE without requesting OAUTH2 credentials?

46 Views Asked by At

I'm willing to manage a Google Drive folder via FlySystem. I've found tons of informations about accessing Google Drive via PHP thru the official client library.

But I find only 2 scenarios I can see and I need a 3rd one:

Scenario a: Each user identifies himself

  • If I use the OAUTH2 system, it is supposed that the user is prompted a login screen and thereafter the library can access their files (you need to configure the redirect URLs and so on).

Scenario b: Access a "service account"

  • If I use the service account, the program accesses the files of a "service account" that starts with an empty drive and does not have a user-friendly UI.

Wanted scenario

  • We currently have some standard user like [email protected] and that user is administered ONLY by the boss of the office.
  • The boss uploads files that are available to the employees via the google-drive web interface. Currently [email protected] has a shared folder with all the employees.
  • But we want to do some automation on file-uploading, but some other file uploading will still be manual.
  • We don't want every employee to have access to the [email protected] credentials.
  • I want PHP to manage that folder in [email protected].

What I see:

  • In scenario A, I should give employees the passwords of [email protected]
  • In scenario B, I don't know how to make the boss access to -say- [email protected] easily to see all the files via the standard drive web-UI.

Question

  • How can I make PHP to access files in a GIVEN REGULAR google account (not a service account), always the same account, wihout giving the users the password of that account?

PD: My final goal is use that drive from flysystem, although the question is not directly related to flysystem itself, but the drive access.

1

There are 1 best solutions below

7
Xavi Montero On

Found it.

TL;DR

Long story short, it's not about having a service account. It's about using OAuth2 in "offline-mode".

Use OAuth2, not a service account

This is the trick:

  • In the normal OAuth2 flow, the user is in front of your application, requests access, then a screen pops up to authorize, and then the user gets redirected back to your application. A short-lived access-token is granted.
  • In offline flow, you manually do once the popup process to authorize, but then you request a long-lived refresh-token, that the application will use to get your short-lived token in the background.

Steps

Those are the steps to get the needed data.

  1. Your create the application. Set a name. Get client_id and client_secret.
  2. You configure the OAuth Screen. It's okey to have it in "development mode" (no need to publicly verify).
  3. You create a set of credentials. Those will be of OAuth2 type.
  4. Here you use the trick: Go to this client-simulator by google https://developers.google.com/oauthplayground
  5. There you can get the refresh-token.

Instructions found here to get the client id and secret and here to get the reresh token.

Sample code

Here's my sample code using all that, tested and allowing access from one gmail account (containing the application) to go to another different, fixed-always-the-same account (containing the data).

In this example I create a standard cross-driver League\Flysystem\Filesystem object driven by a Google\Client configured in such a way that it accesses the files from a given specific google drive without user interaction (background/server use).

use Google\Client as GoogleClient;
use Google\Service\Drive;
use League\Flysystem\Config;
use League\Flysystem\Filesystem;
use League\Flysystem\Visibility;

// Define the class, etc. Next is a single method.
// Inject $this->googleClientConfig via configuration-injection.

private getGoogleDriveFilesystem() : Filesystem
{
    $config = [
        'client_id' => $this->googleClientConfig[ 'clientId' ],
        'client_secret' => $this->googleClientConfig[ 'clientSecret' ],
        'application_name' => 'My Nice App Sandbox FlySystem Test',
    ];

    // This consumes the standard PHP Google Client.
    $googleClient = new GoogleClient( $config );

    // This is the key to skip the user-interaction.
    $googleClient->fetchAccessTokenWithRefreshToken( $this->googleClientConfig[ 'userRefreshToken' ] );

    $drive = new Drive( $googleClient );
    $adapter = new GoogleDriveAdapter(
        $drive,
        $this->googleClientConfig[ 'userRootFolder' ],
    );
    $filesystem = new Filesystem( $adapter, [ Config::OPTION_VISIBILITY => Visibility::PRIVATE ] );
    return $filesystem;
}