gogcli Auth Flags: Understanding --readonly vs --drive-scope
The --readonly flag restricts all Google services to read-only access while forcing Drive to drive.readonly, whereas --drive-scope independently configures Drive permissions (full, readonly, or file) without affecting other services.
When authenticating with Google APIs through the gogcli tool (steipete/gogcli), you must define OAuth 2.0 scopes that determine what the generated refresh token can access. The gog auth add command provides two distinct flags—--readonly and --drive-scope—that control these permissions at different granularities. Understanding how these flags interact is critical for implementing the principle of least privilege in your Google Workspace automations.
What the --readonly Flag Controls
The --readonly flag, defined in internal/cmd/auth.go (lines 486-488), modifies the scope selection logic to request read-only variants of every supported Google service that offers them. When enabled, the authentication flow automatically includes standard OIDC identity scopes (openid, email, userinfo.email) alongside service-specific read-only scopes such as gmail.readonly, calendar.readonly, and spreadsheets.readonly.
The scope calculation logic resides in internal/googleauth/service.go. The scopesForServiceWithOptions function (lines 20-30) handles the per-service mapping, while the driveScopeValue() helper (lines 98-115) specifically manages Drive permissions. When --readonly is active, driveScopeValue() returns drive.readonly regardless of other settings, unless explicitly overridden by --drive-scope.
What the --drive-scope Flag Configures
The --drive-scope flag provides granular control specifically for Google Drive permissions without affecting other services. Defined alongside --readonly in internal/cmd/auth.go, this flag accepts three distinct modes:
- full (default): Requests
https://www.googleapis.com/auth/drive, granting complete access to all Drive files and folders - readonly: Requests
drive.readonly, permitting only read operations - file: Requests
drive.file, which grants write access only to files created or opened by the application, providing a restricted write capability
The implementation in internal/googleauth/service.go processes this through the ScopeOptions struct (lines 49-52), which carries both flag values to the scope calculation functions. When --readonly is false, driveScopeValue() returns the scope corresponding to the --drive-scope setting; otherwise, it defaults to drive.readonly.
Critical Interactions and Validation Rules
These flags interact in specific ways that trigger validation errors when misconfigured. The command-line parser in internal/cmd/auth.go (lines 507-508) explicitly forbids combining --readonly with --drive-scope=file because drive.file inherently grants write capabilities, contradicting the read-only restriction.
When both flags are present but valid (e.g., --readonly with --drive-scope=readonly), the --readonly flag takes precedence for Drive permissions, forcing drive.readonly regardless of the explicit drive scope setting. This ensures that the global read-only restriction cannot be inadvertently bypassed through specific service configuration.
Practical Usage Examples
The following examples demonstrate common authentication scenarios using these flags.
Request read-only access across all services including Drive:
gog auth add [email protected] \
--services gmail,calendar,drive \
--readonly
This generates scopes: openid, email, userinfo.email, gmail.readonly, calendar.readonly, drive.readonly.
Grant full Gmail and Calendar access with restricted Drive file access:
gog auth add [email protected] \
--services gmail,calendar,drive \
--drive-scope=file
This produces: gmail.modify, calendar, drive.file (plus OIDC scopes), allowing write access only to Drive files created by the application.
Attempting to combine conflicting flags results in an error:
gog auth add [email protected] \
--services drive \
--readonly \
--drive-scope=file
The command aborts with: "cannot combine --readonly with --drive-scope=file (file is write-capable)".
Summary
- The
--readonlyflag enforces read-only access across all Google services, automatically selectingdrive.readonlyfor Drive permissions - The
--drive-scopeflag independently configures Drive access levels (full, readonly, file) without affecting other services - These flags conflict when
--drive-scope=fileis combined with--readonly, triggering a validation error ininternal/cmd/auth.go - Scope calculation logic resides in
internal/googleauth/service.go, specifically withindriveScopeValue()andscopesForServiceWithOptions()
Frequently Asked Questions
Can I use --drive-scope=full with --readonly?
No. When --readonly is specified, it overrides any Drive scope setting to drive.readonly. The driveScopeValue() function in internal/googleauth/service.go checks the Readonly field first, returning the read-only variant regardless of the DriveScope setting.
What happens if I omit both flags?
The command requests full access scopes for all selected services. For Drive, this means https://www.googleapis.com/auth/drive, granting complete read and write access to all files and folders in the user's Google Drive.
Why does --drive-scope=file conflict with --readonly?
The drive.file scope grants write access to files created or opened by the application, which contradicts the global read-only restriction implied by --readonly. The validation logic in internal/cmd/auth.go (lines 507-508) explicitly checks for this combination and aborts with an error to prevent accidental privilege escalation.
Which services support read-only variants when using --readonly?
The implementation in internal/googleauth/service.go provides read-only mappings for Gmail (gmail.readonly), Google Calendar (calendar.readonly), Google Sheets (spreadsheets.readonly), and Google Drive (drive.readonly). Other services without explicit read-only variants in the codebase default to their standard scopes or are omitted based on the service selection.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →