Google OAuth Client Secret Is Now One-Time Visible: What Breaks and How to Rotate Safely
Google hashes OAuth client secrets. You see the full value once — on the creation screen — and never again. Most teams do not discover this until the day they actually need the secret, and by then the only route back is a rotation that has to be sequenced correctly or the integration goes down.
What actually changed
In April 2025 Google announced a set of changes to the Google Auth Platform. One of them quietly rewrote how every team stores credentials. Google’s support documentation now states it plainly:
“To prevent accidental exposure and increase protection, client secrets are hashed. This means you will only be able to view and download the full client secret once, at the time of its creation.”
Google Cloud Platform Console Help — Manage OAuth ClientsAfter creation, the console displays only the last four characters of the secret. Google is explicit that this truncated value exists purely so you can tell your secrets apart — it is an identifier, not a recoverable credential.
Who it applies to
Google’s documentation notes the feature covers clients created after June 2025, and was extended to existing clients starting November 2025. Older clients are not permanently exempt.
What the console shows now
A masked field with the final few characters. The download-JSON route that teams relied on for years no longer returns a usable secret after the creation screen closes.
The only way back
Google states that if you lose your client secret, you use the client secret rotation feature to get a new one. There is no “reveal” and no support recovery path.
Why this breaks more than people expect
On paper this is a one-line policy change. In practice it collides with how most integrations were actually built — and the failures do not surface at the moment of the change. They surface months later, at the worst possible time.
- The secret was never stored anywhere authoritative. It lived in a server config file, a CI variable, or a hosting panel — and the console was treated as the backup. That backup no longer exists.
- Server migrations become credential events. Moving a Google-integrated app to a new host used to mean copying the secret from the console. Now it means running a rotation on a live production integration.
- Handover between developers stalls. An agency, contractor or previous developer who never handed over the secret cannot be chased for it later — the client is left rotating a credential on a system they may not fully understand.
- Multi-environment setups multiply the risk. Staging, production and a mobile backend sharing one client means one rotation touches every one of them, and Google caps you at two secrets while you do it.
- It compounds with automatic client deletion. Google also deletes OAuth clients that have been inactive for six months — and a client whose secret nobody holds is a client nobody is using.
The rotation window is narrower than it looks
Google’s rotation feature is genuinely well designed: you add a second secret, migrate to it while the old one still works, then disable and delete the old one. No forced downtime. But there are hard constraints inside that window that decide whether a rotation is a non-event or an outage.
You get two secrets. That is the ceiling.
Google’s documentation is explicit that a client can hold a maximum of two client secrets. If it already has two, you must disable and delete one before you can create another — which removes your rollback option at exactly the wrong moment.
Both secrets stay live until you act.
The new secret is enabled and usable immediately, and the old one keeps working until it is manually disabled. Google explicitly instructs you to migrate and disable the old secret as soon as possible — two live secrets is a wider attack surface, not a safety net to sit in.
“Fully migrated” has to be proven, not assumed.
Google asks you to confirm the old secret is not used anywhere — code references, configuration, app and server logs, rollout status of the updated version, and any other metrics you hold. This is the step that decides the outcome, and it is the step most teams skip.
Disabling is reversible. Deleting is not.
A disabled secret is rejected in OAuth flows, but Google lets you re-enable it if something breaks. Deletion is different — the documentation states plainly that it cannot be undone. Delete before you have proven the migration and there is no way back.
The failure mode nobody plans for
A rotation that is disabled too early fails silently for some users and not others. Cached deployments, un-restarted workers, a mobile build still rolling out, or a background job server nobody remembered can all keep presenting the old secret. The dashboard looks healthy; a subset of sign-ins and token refreshes simply stop.
The six-month deletion clock running alongside it
Separate from secret hashing, Google automatically deletes OAuth 2.0 clients that have been inactive for six months. Per Google’s documentation, a client counts as unused if, within that period, it has neither been used for a credential or token request via the Google OAuth 2.0 endpoint, nor had its settings modified — manually or programmatically.
What deletion actually costs you
- The client can no longer be used for Sign in with Google or for data-access authorization.
- Calls to Google APIs using existing access tokens or refresh tokens tied to that client will fail — not just new sign-ins.
- Authorization requests using the deleted client ID return a
deleted_clienterror. - Recovery is time-boxed: Google states deleted clients are typically recoverable at least 30 days after deletion, via the Deleted Credentials page.
Google sends an email notification 30 days before an inactive client is scheduled for deletion — which is only useful if the developer contact details on the project are still a mailbox somebody reads. On projects that have changed hands, that is frequently not the case.
Where this sits in a wider verification problem
Credential handling is rarely the only thing standing between an app and a working Google integration. It runs alongside the consent screen, the scope tier your app falls into, and the verification review itself — and a problem in one area often gets misdiagnosed as a problem in another.
- If users are seeing a warning screen rather than a credential failure, the issue is the app’s verification state — see the Google OAuth “this app isn’t verified” warning.
- If the flow fails with a specific console error rather than an authentication failure, start with Google OAuth consent screen errors and what each one really means.
- If the wider review is the blocker, the Google OAuth verification guide covers how the sensitive and restricted scope review works.
Where this gets handled properly
The technically difficult part of this is not clicking Add Secret. It is establishing exactly where a live credential is presented from across every environment, sequencing the migration so no user-facing flow is ever holding a disabled secret, and confirming the cutover before the irreversible step — on a production integration that has to keep working throughout.
That is the work I do as part of Google OAuth and API verification support: reviewing how your credentials are actually held, planning the rotation sequence around your deployment reality, and preparing the surrounding verification material so a credential fix does not turn into a review problem.
Sources for every factual statement above: Google Cloud Platform Console Help, “Manage OAuth Clients”, and the Google for Developers blog post “Usability and safety updates to Google Auth Platform” (28 April 2025). Platform requirements change — confirm details against Google’s current documentation before acting. This is independent technical support and is not affiliated with, endorsed by, or a partner of Google. No specific review outcome or timeline can be guaranteed by any provider.