LW IT Solutions
« Blog Overview /Digital Marketing / Google Ads API Passkey Requirement: What It...
Read this article in other languages:

Google Ads API Passkey Requirement: What It Applies To and How to Find Forgotten Authorizations

Google Ads API Passkey Requirement: What It Applies To and How to Find Forgotten Authorizations
Contents
  1. 1. The login is in scope, the OAuth client is not
  2. 2. Write down who authorizes what
  3. 3. Find the forgotten authorizations
  4. 4. The emergency path for shared and agency access
  5. 5. Summary
  6. Questions and answers
  7. Sources

Google announced the passkey requirement for Google Ads API access on 27 July 2026, and the rollout began on 5 August. Since then the recurring question in every team chat has been some version of “do we have to reissue our OAuth client?” No. The requirement applies to how the user account behind an authorization signs in. The OAuth client is not the subject of this change, and existing tokens stay valid, so nothing stops working in the meantime. What the situation calls for is not a panic migration but an honest inventory of which integrations depend on a human being able to log in.

1. The login is in scope, the OAuth client is not

The distinction is narrow and it decides everything else. If an integration was authorized by a person clicking through a consent screen with their own Google account, that account’s sign-in falls under the passkey requirement. If it runs through a service account, it does not: service accounts are exempt. Same API, same client library, same customer IDs; the only difference is who authenticated.

Two things follow. No dashboard goes dark on a fixed date: existing tokens keep working, so the pressure point is the next time someone has to sign in, after a token is revoked by accident or a machine is rebuilt. And the risk sits in people, not in code. No repository records who holds the refresh token.

One correction, because it keeps circulating: several write-ups claim there is a seven-day lockout period for affected accounts. The announcement says something narrower: a 7-day security delay may apply before a newly created passkey becomes trusted and operational. That locks no account and sets no deadline, but a passkey created only when the next sign-in is due may not be usable yet.

Two paths into a checkpoint: an integration authorised by a personal account must pass the passkey requirement, while a service account bypasses it
The requirement lands on the account that authorised the integration, not on the OAuth client. Everything wired through a service account walks past the checkpoint; everything wired through a person does not.

2. Write down who authorizes what

Start with the artefact almost nobody has: a written matrix of the access itself. A YAML file in the repository is a start, but a small SQLite table is better, because it will need querying. The columns that matter are the ones nobody can reconstruct from memory six months from now.

create table ads_authorization (
  integration     text primary key,
  auth_type       text not null check (auth_type in ('user_account','service_account')),
  google_account  text,
  config_path     text,
  token_store     text,
  owner           text not null,
  deputy          text,
  customer_ids    text,
  last_verified   date
);

insert into ads_authorization values
 ('nightly-cost-load','user_account','ads-bot@example.com','/srv/etl/conf/ads.yaml',
  'vault:kv/ads/refresh','l.wojcik','m.kowalski','123-456-7890,222-333-4444','2026-08-08'),
 ('bi-connector','service_account',null,'/srv/bi/sa.json',
  'gcp-secret-manager','platform-team',null,'123-456-7890','2026-08-08');
  • auth_type: splits the estate into in scope and out of scope with a single where clause.
  • deputy: the field this requirement is really about. If the person in owner is away for three weeks, who signs in?
  • token_store: a personal home directory here is a finding, not a value.

3. Find the forgotten authorizations

An inventory is only as good as its coverage, and the forgotten entries are the ones that hurt. Sweep the config trees, then compare the result against the written record.

grep -rIls -e refresh_token --include='*.y*ml' --include='*.json' --include='*.env' \
  /etc /srv /opt /home
#!/usr/bin/env python3
"""Classify local OAuth configs and diff them against the access inventory."""
import pathlib, re, sqlite3, sys

root = pathlib.Path(sys.argv[1])
patterns = ("*.yaml", "*.yml", "*.json", "*.env", "*.ini")
has_refresh = re.compile(r"refresh_token\s*[:=]\s*\S")
is_service = re.compile(r"service_account|private_key_id")

db = sqlite3.connect("access.db")
known = {row[0] for row in db.execute("select config_path from ads_authorization")}

for pattern in patterns:
    for path in sorted(root.rglob(pattern)):
        text = path.read_text(errors="ignore")
        if not (has_refresh.search(text) or is_service.search(text)):
            continue
        kind = "service_account" if is_service.search(text) else "user_account"
        flag = "" if str(path) in known else "  UNTRACKED"
        print(f"{kind:16}{path}{flag}")

Run it on every host that talks to the API, including the analyst laptop nobody wants to mention. Each UNTRACKED line is either a row missing from the inventory or a credential to revoke today. Each user_account line is a person who now has to be named.

4. The emergency path for shared and agency access

Now the operational part. For every user_account row, decide in advance what happens when that person is unavailable, because a sign-in that needs a passkey needs the human who holds it.

  1. Name a deputy with access to the same Google account under the applicable policy, and record them in the matrix.
  2. Move the refresh token out of personal files into the secret store, so re-authentication is the only step that still requires a person.
  3. Note per integration which customer IDs stop reporting if that authorization dies. That is the blast radius, and it sets the order of work.
  4. For agency setups, agree in writing which side holds the authorization and who is called on a Friday evening. Then check whether a service account is workable there, since those rows leave the scope of the requirement entirely.
select integration, google_account, owner, customer_ids
from ads_authorization
where auth_type = 'user_account'
  and (deputy is null or last_verified < date('now','-90 day'))
order by owner;

Put that query in a quarterly cron job and have it mail the output to the team. An empty result set is the whole review.

5. Summary

Three small things came out of this: a table that records which integration is authorized by which account, a sweep that finds the configurations nobody wrote down, and a query that lists every single point of failure with no deputy. None of it is specific to Google. It answers a question that every API with a human in the authorization chain eventually raises.

The gain is calm. Existing tokens keep working, service accounts are exempt, the OAuth client is untouched, and the seven-day lockout the forums keep repeating is, in the announcement, only a possible delay before a new passkey works. Read the original before acting on any summary, including this one: Passkey authentication requirement for the Google Ads API. Then spend the time saved on the rows in the matrix where deputy is still empty.

Questions and answers

A config sweep finds tokens but not the person behind an authorization. How can that half be established without interviewing everyone?

From the platform side, which is the half the repository genuinely cannot answer.

Two sources cover most of it. The list of third-party applications connected to a Google account shows which OAuth clients that account has authorized, and in a managed organization administrators can see the same information centrally; that maps a human to a set of integrations without asking anyone. And the change history in the advertising account attributes API-driven changes to the account that made them, which connects a running job to a named person even when nobody remembers setting it up. That second source only sees jobs that write; a pure reporting export leaves no trace there.

Between those two and the file sweep the picture usually closes: files say what exists, the consent list says who authorized it, the change history says what it is still doing. The remainder, an integration whose token works but whose owner has left, is exactly the row the inventory exists to surface, and it is worth revoking rather than researching.

Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Get in Touch

Briefly describe your project or inquiry for a tailored response. This site is protected by reCAPTCHA.

One comment

  1. Lukas Wojcik Author

    Update: Since 10 September 2026 the access level of the Google Ads API is tied to the Google Cloud project used to generate the OAuth credentials. This changes nothing about the passkey requirement. The inventory described in the article should now also record the Cloud project of each integration, though, because that project decides which access level the integration works with. Sources: Google Ads Developer Blog, 10 September 2026, Access levels.

Write a comment

Practical experience and questions about the implementation are welcome here.

The email address is not published. Required fields are marked with an asterisk.

Articles & categories

CCTV

Follow this category by RSS

Cloud & AI

All 17 articles in this category Follow this category by RSS

Data Privacy

All 19 articles in this category Follow this category by RSS

Digital Analytics

All 58 articles in this category Follow this category by RSS

Digital Marketing

All 37 articles in this category Follow this category by RSS

IT & Networks

All 18 articles in this category Follow this category by RSS

Music Production

All 17 articles in this category Follow this category by RSS

Raspberry PI

Follow this category by RSS

SaaS & Internet Earning

Follow this category by RSS

Smart Home

All 18 articles in this category Follow this category by RSS

Web Development

All 11 articles in this category Follow this category by RSS

WordPress Plugins & Tricks

All 14 articles in this category Follow this category by RSS