Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk6 min

Publishing a Chrome Extension from GitHub Actions Without a Stored Secret

Set up keyless Chrome extension releases: GitHub OIDC, Workload Identity Federation, a service account authorized in the Developer Dashboard, and API v2 upload and publish calls.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

You can release a Chrome extension from GitHub Actions without saving a Google service-account key or OAuth refresh token in repository secrets. The workflow proves its identity to Google Cloud with a GitHub OpenID Connect (OIDC) token. Workload Identity Federation exchanges that token for short-lived credentials. Those credentials impersonate a service account that you have authorized in the Chrome Web Store Developer Dashboard. The workflow then calls Chrome Web Store API v2 to upload and submit the package.

“No stored secret” means no persisted, long-lived credential. Short-lived tokens still exist at runtime, but they expire and are never kept in GitHub. One timing note: the archived v1 API reference gives 2026-10-15 as the end of v1 support, so build on v2.

How the keyless chain fits together

  1. The GitHub job requests an OIDC token (this needs the id-token: write permission).
  2. A Google Cloud workload identity provider validates the token and checks your attribute condition.
  3. The federated identity impersonates a service account.
  4. That service account’s email has been added to your Chrome Web Store publisher account, so API calls are accepted as you.
  5. The job uploads the zip and calls publish.

Google’s documentation says Workload Identity Federation “eliminates the maintenance and security burden associated with service account keys.” GitHub’s guide, Configuring OpenID Connect in Google Cloud Platform, describes the same goal: workflows access Google Cloud without storing the credentials as long-lived GitHub secrets.

Choosing a credential approach

Approach Long-lived secret in GitHub? Trade-off
OIDC + Workload Identity Federation + service-account impersonation No Needs one-time Google Cloud IAM setup and a carefully written trust condition. Best fit for GitHub-hosted CI.
Service-account JSON key Yes Described in Chrome’s service-account guide as an option, but it is a persistent private key you must protect and rotate. Google recommends federation for external workloads where possible.
OAuth client + refresh token Yes The tutorial in Use the Chrome Web Store API. It also depends on durable credential material.

One-time setup

1. Create the service account and authorize it in Chrome

In the Google Cloud project you want to use, enable the Chrome Web Store API and create a service account. Then open the Chrome Web Store Developer Dashboard and add the service account’s email under Account. The service-account guide currently says a publisher can add only one service account, so decide which project and account will own this role before you start. Check that the publisher account and Google Cloud project are the intended ones.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Create a workload identity pool and GitHub provider

Create a pool and an OIDC provider whose issuer is GitHub’s token service. Map the claims you want to test and add an attribute condition. A sketch with gcloud (replace the placeholders):

gcloud iam workload-identity-pools create github 
  --project=PROJECT_ID --location=global

gcloud iam workload-identity-pools providers create-oidc github-provider 
  --project=PROJECT_ID --location=global 
  --workload-identity-pool=github 
  --issuer-uri="https://token.actions.githubusercontent.com" 
  --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" 
  --attribute-condition="assertion.repository == 'OWNER/REPO'"

The condition is the security boundary. GitHub’s guide cautions that trust conditions must keep untrusted repositories from obtaining credentials. Without one, workflows from other repositories may be able to federate. Tighten the condition further if you can, for example to a specific ref or a GitHub environment. If your workflow uses environments, add protection rules such as required reviewers as an extra control.

3. Let the federated identity impersonate the service account

gcloud iam service-accounts add-iam-policy-binding 
  SA_NAME@PROJECT_ID.iam.gserviceaccount.com 
  --role=roles/iam.workloadIdentityUser 
  --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github/attribute.repository/OWNER/REPO"

The service account needs no Google Cloud roles for Chrome Web Store calls. Its authority comes from being listed in the Developer Dashboard.

4. Meet the first-publication requirements

Per the API usage guide, you need 2-step verification to publish or update an extension. A new item also needs its Store Listing and Privacy tabs completed before it can be published. The API updates an existing item, so create the item once in the dashboard first.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The workflow

Keep id-token: write on the release job only. The provider path, service account, publisher ID and extension ID are identifiers, not secrets, so store them as repository or environment variables.

name: release
on:
  push:
    tags: ['v*']

jobs:
  publish:
    runs-on: ubuntu-latest
    environment: chrome-web-store
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v4
      - run: cd extension && zip -r ../extension.zip .

      - id: auth
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: ${{ vars.WIF_PROVIDER }}
          service_account: ${{ vars.WIF_SERVICE_ACCOUNT }}
          token_format: access_token
          access_token_scopes: https://www.googleapis.com/auth/chromewebstore

      - name: Upload
        run: |
          curl -fsS -X POST 
            -H "Authorization: Bearer ${{ steps.auth.outputs.access_token }}" 
            -T extension.zip 
            "https://chromewebstore.googleapis.com/upload/v2/publishers/${{ vars.CWS_PUBLISHER_ID }}/items/${{ vars.CWS_EXTENSION_ID }}:upload"

      - name: Submit for review
        run: |
          curl -fsS -X POST 
            -H "Authorization: Bearer ${{ steps.auth.outputs.access_token }}" 
            -H "Content-Length: 0" 
            "https://chromewebstore.googleapis.com/v2/publishers/${{ vars.CWS_PUBLISHER_ID }}/items/${{ vars.CWS_EXTENSION_ID }}:publish"

Pin the action to the major version or commit SHA you have reviewed, and confirm current input names in the action’s own documentation. The endpoint paths follow the resource names in the media.upload and publishers.items.publish references. Check those pages for the exact current request shape.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

What upload and publish actually do

Upload

The upload method sends a package to an existing item. The publisher ID and extension ID are part of the item’s resource name. Raise version in manifest.json before packaging; the usage guide says upload fails if the version was not increased. Deriving the version from the release tag, and failing the build if the two disagree, avoids this class of error.

Publish

By default, publish submits the item for review, and it goes live after approval. Setting the publish type to STAGED_PUBLISH leaves an approved submission staged until you take a later action in the dashboard. A skipReview option exists, but it is only a request. The API can return a validation error when the item requires review. Treat the workflow as automating upload and submission, not as guaranteeing instant availability, because Chrome Web Store review and policy still apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Limits and cautions

  • Use v2. The v2 reference says v2 supports service accounts. The archived v1 reference says v1 is deprecated and supported only until 2026-10-15. As of 2026-10-06 that is days away.
  • Intended use. The API reference says the API is primarily meant for personal use on your own extensions. It also notes that “verified” status may not be available to apps using the Chrome Web Store write scope, and says this does not block API use.
  • Scope of authority. The service account can manage items belonging to the publisher account, so protect the release path with a restrictive trust condition, environment approvals, and tag or branch rules.
  • Re-verify limits. Service-account limits, such as the one-per-publisher cap, are current as of the Chrome guide’s present text and may change.

Troubleshooting

  • Token exchange denied: the attribute condition probably does not match the token’s claims. Compare assertion.repository and the subject claim to what the run actually presents. Also check that id-token: write is set on that job.
  • Impersonation denied: the principalSet member in the IAM binding must use the project number and the same mapped attribute as your provider.
  • Chrome API returns a permission error: confirm the service account’s email was added under Account in the Developer Dashboard, and that the Chrome Web Store API is enabled in the project.
  • Upload rejected: check that the manifest version is higher than the one currently on the item.
  • Publish returns a validation error: the item may require review, so drop skipReview and use the default submission.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.