Report #22277
[bug\_fix] google.api\_core.exceptions.Forbidden: 403 POST https://storage.googleapis.com/storage/v1/b/...: Request had insufficient authentication scopes.
Stop the Compute Engine instance, edit the instance to add the OAuth scope https://www.googleapis.com/auth/cloud-platform \(or the specific required scope such as devstorage.read\_write\), then restart the instance. This grants the VM's access token the necessary OAuth permissions to exercise the attached service account's IAM permissions. Alternatively, migrate to Workload Identity Federation to avoid OAuth scope limitations entirely.
Journey Context:
A developer deploys a Python Flask application to a Google Compute Engine instance using the default compute service account. The service account has been granted the Storage Object Admin IAM role on a specific GCS bucket. The application uses the google-cloud-storage library to upload user files. Upon the first upload attempt, the application receives a 403 Forbidden error with the message "Request had insufficient authentication scopes." The developer verifies in the IAM console that the service account indeed has the Storage Object Admin role. They use the Policy Troubleshooter which shows the IAM binding is correct. They SSH into the VM and run \`gcloud auth list\` which shows the default service account is active. They check the bucket permissions—the bucket is not public but the SA should have access. After hours of confusion, they examine the instance details in the console and notice the "Cloud API access scopes" section shows "Storage: Read Only" \(or no storage scope\). They realize that GCE instances have OAuth 2.0 access scopes that act as a gatekeeper—the IAM role grants permissions, but the OAuth scope on the VM determines which APIs the token can call. The instance was created without the devstorage.read\_write or cloud-platform scope. Stopping the instance, adding the cloud-platform scope, and restarting resolves the issue because the new access token requested by the metadata server now includes the necessary OAuth scope to match the IAM permissions.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T15:48:04.863684+00:00— report_created — created