Please add this plugin to GPM.
What it does: Google sign-in for a Grav 2 Google Drive plugin family. A site connects a Google account once, either as an OAuth user through its own Google Cloud "Web application" client (PKCE S256, offline access, revoke) or as a service account (RS256 JWT signed with openssl_sign), and plugins built on it call Gdrive::drive($account, $scopes) for a thin Drive v3 client (Shared Drives on every call, 401 → refresh-once, backoff on 429/5xx, resumable single-PUT upload). Dependent plugins declare the account and scopes they need through an onGdriveScopes event; an OAuth account that hasn't granted a scope is refused with scope_not_granted.
The Admin2 settings page (two custom fields plus server-rendered display fields) has a guided setup that asks a few questions and shows only the steps that apply, an Accounts tab (add by upload or paste, Test, Connect in a popup, Remove) and full OAuth, service-account and Troubleshooting guides with the site's redirect URI, service-account emails and needed scopes filled in. Its routes live under /api/v1/gdrive behind a dedicated api.gdrive.manage permission; the public OAuth callback at /gdrive-oauth/callback is the only front-end route. No Composer dependencies: curl and openssl only.
Security notes (SECURITY.md has the full list): credentials live only in user/data/gdrive/auth/, written atomically with mode 0600, never in config, logs or API responses; account names are validated before any path is built and uploaded JSON is shape-checked; sign-in and token requests go only to Google's own endpoints whatever an uploaded file says; the callback trusts a single-use, 10-minute, server-side state (32 random bytes stored by SHA-256) plus PKCE and answers a generic 400 otherwise, with the reason logged; the redirect URI follows system.custom_base_url and Google exact-matches it, so a forged Host header goes nowhere; the callback page sends a nonce CSP, X-Frame-Options: DENY, Cache-Control: no-store and Referrer-Policy: no-referrer.
Testing: tests/smoke.php (fake transports, no network: JWT, PKCE, state single-use and expiry, scope enforcement, retry and 401 logic, upload request shape, pinned endpoints, credential and name validation, the settings page's rows and guides, a Troubleshooting anchor for every reason code, version drift), PHPStan level 6 against Grav 2.0.23 / api 1.0.41 and Grav 2.2.4 / api 1.0.44, PHP 8.3 and 8.4, all in CI. Clicked through on a production site running Grav 2.2.4, api 1.0.44, admin2 2.1.27, PHP 8.3: every tab renders, Test passes against Drive.
Note: the two plugins built on it (gdrive-images, gdrive-backup) are still private and will be submitted separately once they're ready, so the README's links to them don't resolve yet.
Please add this plugin to GPM.
gdrive-authversion:inblueprints.yaml)grav: ['2.0']; dependenciesgrav >=2.0.23,api >=1.0.41,admin2 >=2.1.24; PHP 8.3+gdrive-auth-1.0.0.zip(git archive of the tag, dev files stripped), SHA-25679d292ec630d2d60b2df6d391e365ee529a0fa73b148d0249a6c5031e3e180a2What it does: Google sign-in for a Grav 2 Google Drive plugin family. A site connects a Google account once, either as an OAuth user through its own Google Cloud "Web application" client (PKCE S256, offline access, revoke) or as a service account (RS256 JWT signed with
openssl_sign), and plugins built on it callGdrive::drive($account, $scopes)for a thin Drive v3 client (Shared Drives on every call, 401 → refresh-once, backoff on 429/5xx, resumable single-PUT upload). Dependent plugins declare the account and scopes they need through anonGdriveScopesevent; an OAuth account that hasn't granted a scope is refused withscope_not_granted.The Admin2 settings page (two custom fields plus server-rendered display fields) has a guided setup that asks a few questions and shows only the steps that apply, an Accounts tab (add by upload or paste, Test, Connect in a popup, Remove) and full OAuth, service-account and Troubleshooting guides with the site's redirect URI, service-account emails and needed scopes filled in. Its routes live under
/api/v1/gdrivebehind a dedicatedapi.gdrive.managepermission; the public OAuth callback at/gdrive-oauth/callbackis the only front-end route. No Composer dependencies: curl and openssl only.Security notes (SECURITY.md has the full list): credentials live only in
user/data/gdrive/auth/, written atomically with mode 0600, never in config, logs or API responses; account names are validated before any path is built and uploaded JSON is shape-checked; sign-in and token requests go only to Google's own endpoints whatever an uploaded file says; the callback trusts a single-use, 10-minute, server-side state (32 random bytes stored by SHA-256) plus PKCE and answers a generic 400 otherwise, with the reason logged; the redirect URI followssystem.custom_base_urland Google exact-matches it, so a forged Host header goes nowhere; the callback page sends a nonce CSP,X-Frame-Options: DENY,Cache-Control: no-storeandReferrer-Policy: no-referrer.Testing:
tests/smoke.php(fake transports, no network: JWT, PKCE, state single-use and expiry, scope enforcement, retry and 401 logic, upload request shape, pinned endpoints, credential and name validation, the settings page's rows and guides, a Troubleshooting anchor for every reason code, version drift), PHPStan level 6 against Grav 2.0.23 / api 1.0.41 and Grav 2.2.4 / api 1.0.44, PHP 8.3 and 8.4, all in CI. Clicked through on a production site running Grav 2.2.4, api 1.0.44, admin2 2.1.27, PHP 8.3: every tab renders, Test passes against Drive.Note: the two plugins built on it (gdrive-images, gdrive-backup) are still private and will be submitted separately once they're ready, so the README's links to them don't resolve yet.