Skip to content
SheetForge

Web Google Sheets Access

Google Sheets access follows the credential you bring. On the deployed website there are two ways in, side by side: sign in with Google (OAuth), or pick a service-account key file that your own browser uses directly. The Unity / local path keeps its machine-local service-account key, unchanged.

On the deployed site — OAuth, read and write

On the deployed site, a signed-in user can both read and write Google Sheets over their own OAuth token.

  • Least privilege. Signing in asks for your basic profile and per-file spreadsheet access (drive.file): the app can read and write only the spreadsheet files you have explicitly opened for it. Nothing account-wide — it cannot list or browse the rest of your Drive, and a file you have not opened for it stays invisible.
  • The same core plan. A write on the web runs through exactly the same core plan and the same shared optimistic-lock verification as every other path — the live sheet is re-checked right before send, so a cell a third party changed after your import is skipped, never overwritten. Only the transport layer differs: on this path it carries the OAuth bearer token.
  • The sheet's ACL is the final authority. SheetForge does not decide who may write; Google does. A 403 from Google is remapped to an honest permission message rather than a partial write, so a refusal reads as a refusal.

The OAuth token is held in the session cookie (a JWT) and used by server actions. The one exception is Google's file picker, described next: it is a Google widget that runs in the page, so opening it hands the page a short-lived access token for your own session.

Start from the picker — you never need an ID

The signed-in tab leads with Choose a spreadsheet from Google: Google's own file picker opens over the page, you pick the spreadsheet, its ID lands in the panel and the import runs by itself. Picking is also what grants the app access to that file under drive.file, so one gesture does both. A Current spreadsheet line shows what the panel is pointed at.

Typing an ID by hand still works — it moved under an Advanced: start from a spreadsheet id fold, and a previously saved ID keeps working exactly as before. The honest catch is stated right there: Google only opens files you have picked at least once, so an ID for a file never picked is refused until you pick it (the Allow file access… line below covers that).

Opening a file for the app — once

Under drive.file, permission grows file by file. If the app hits a spreadsheet it has no access to yet — an ID typed under Advanced, a saved ID after switching accounts — it opens Google's own file picker with that spreadsheet already looked up, the moment it hits the permission error. Pick the file once, and the import or push you started finishes by itself. From then on, that spreadsheet behaves exactly as it always did.

  • Nothing to prepare up front. You do not grant access in advance; the picker appears exactly when it is needed, preset to the file in question, and the action you asked for retries automatically after you pick.
  • Re-granting is always at hand. The Google panel keeps an Allow file access… line that opens the same picker at any time — for example after switching to a different Google account.
  • An honest boundary. The picker is a Google widget running in the page, so while it is in use the page holds a short-lived access token (valid for at most one hour) for your session, fetched from a same-origin endpoint that requires your login. That is the same kind of trust the key-file path below places in the page — the app's strict Content Security Policy is what guards it. The token is not stored or logged.

The key-file tab keeps its ID field on purpose: a service account has no signed-in browsing session to pick with, so an ID — with the sheet shared to the account — remains the honest way in there.

On the deployed site — a service-account key file, signed by your browser

The Google panel's second tab takes a service-account JSON key file. Everything that key does happens in your browser:

  • The key never reaches the server. The browser itself signs the token request and calls Google's APIs directly, so the key, the signed request, the access token and your sheet data never touch SheetForge's servers. The server-side service-account routes stay gated closed (501) on the deployed site, exactly as before — this path adds a capability without opening one.
  • Remembering the key is honest about what it stores. If you choose to have the key remembered, the file's text is discarded immediately; what is kept — on that device, in the browser's storage — is a signing key that scripts on the page can use but can never read back out. Anyone who can open that browser profile could still recover it, so treat the device as you would treat the key file itself. Forget key removes it at once, in every open tab, and the app also asks Google to revoke the current access token.
  • Same plan, same verify. Reads and writes run through the same core plan and the same pre-send verification as the other paths.

The Unity / local path

The service-account key used by Unity and the local development server is read from a machine-local path and is never uploaded or bundled — the same key described in Google Sheets Setup; keep it outside Assets/ and outside the repo. The repository contains no credentials.

After a push from the web app, the sheet's data-validation dropdowns are rewritten automatically — every tab in one batch, with a reference column's dropdown written as a range over the target sheet's key column, so it grows as records are added. A rule aimed at a sheet tab that does not exist is skipped and reported. This matches what the editor's Google push writes.

Which path does what

Where you runGoogle credentialReadsWrites
Unity / localService-account key, read from a machine-local pathYesYes — surgical cell writes, structure rewrite, Push
Deployed siteThe signed-in user's OAuth token (drive.file — the files opened for the app)YesYes — same core plan + optimistic-lock verify
Deployed siteA service-account key file you pick, used by your browser directlyYesYes — same core plan and verify; requests go from your browser straight to Google
Deployed siteServer-side service-account routesGated closed (501)

The write behaviour is identical wherever it runs, because every path shares the core plan and the pre-send verify. Only the transport — a browser-signed service-account token, a per-user OAuth bearer, or the local server's key — changes.