token variant

This commit is contained in:
JiriUhlir
2026-06-22 05:26:20 +02:00
parent 125b112967
commit 28b29b8331
5 changed files with 77 additions and 10 deletions
+60 -6
View File
@@ -14,7 +14,11 @@ service account); they differ only in the OAuth *scope* and the header prefix:
* Google Ads -> ``X-GAds-*`` (scope adwords) + developer token
Each provides ``*-Access-Token`` (ready Bearer token, takes precedence) and
``*-Credentials`` (base64 service-account JSON; the proxy mints a token).
``*-Credentials`` (base64 service-account JSON; the proxy mints a token). As an
alternative, the ready access token may also be supplied via the standard
``Authorization: Bearer <token>`` header (the service-specific ``*-Access-Token``
wins if both are present); this keeps the original header path intact while
offering the conventional bearer-token path.
Sklik uses ``X-Sklik-Token`` (the proxy calls client.loginByToken).
"""
@@ -47,6 +51,29 @@ class GoogleAdsCredentials:
login_customer_id: str | None
def _bearer_from_authorization(authorization: str | None) -> str | None:
"""Extract the token from a standard ``Authorization: Bearer <token>`` header.
Only the ``Bearer`` scheme is accepted; any other scheme (e.g. ``Basic``) is
ignored so the caller falls through to the other credential sources and gets
a clear "no credentials" error rather than a token that cannot work.
"""
if not authorization:
return None
parts = authorization.strip().split(None, 1)
if len(parts) == 2 and parts[0].lower() == "bearer":
return parts[1].strip() or None
return None
def _authorization_description(token_header: str) -> str:
return (
"Standard OAuth2 bearer token, sent as 'Authorization: Bearer <token>'. "
f"Alternative to {token_header} (which wins if both are present) and to "
"the service-account credentials header. Must carry the service's scope."
)
def _build_google_credentials(
access_token: str | None,
raw_credentials: str | None,
@@ -55,9 +82,17 @@ def _build_google_credentials(
*,
token_header: str,
creds_header: str,
authorization: str | None = None,
) -> GoogleCredentials:
"""Parse a Google access token / base64 service-account JSON from headers."""
"""Parse a Google access token / base64 service-account JSON from headers.
The ready access token may arrive either in the service-specific
``*-Access-Token`` header (takes precedence, kept for backward
compatibility) or in a standard ``Authorization: Bearer <token>`` header.
"""
token = (access_token or "").strip() or None
if token is None:
token = _bearer_from_authorization(authorization)
service_account_info: dict | None = None
raw = (raw_credentials or "").strip()
@@ -81,7 +116,8 @@ def _build_google_credentials(
if not token and service_account_info is None:
raise MissingCredentialsError(
f"Provide either {token_header} or {creds_header}."
f"Provide either {token_header}, an 'Authorization: Bearer <token>' "
f"header, or {creds_header}."
)
return GoogleCredentials(
@@ -98,7 +134,12 @@ def get_ga_credentials(
default=None,
alias="X-GA-Access-Token",
description="Ready OAuth2 access token used directly as a Bearer token. "
"Takes precedence over X-GA-Credentials.",
"Takes precedence over Authorization and X-GA-Credentials.",
),
authorization: str | None = Header(
default=None,
alias="Authorization",
description=_authorization_description("X-GA-Access-Token"),
),
x_ga_credentials: str | None = Header(
default=None,
@@ -121,6 +162,7 @@ def get_ga_credentials(
config.GA_SCOPE,
token_header="X-GA-Access-Token",
creds_header="X-GA-Credentials",
authorization=authorization,
)
@@ -130,7 +172,12 @@ def get_gsc_credentials(
default=None,
alias="X-GSC-Access-Token",
description="Ready OAuth2 access token used directly as a Bearer token. "
"Takes precedence over X-GSC-Credentials.",
"Takes precedence over Authorization and X-GSC-Credentials.",
),
authorization: str | None = Header(
default=None,
alias="Authorization",
description=_authorization_description("X-GSC-Access-Token"),
),
x_gsc_credentials: str | None = Header(
default=None,
@@ -152,6 +199,7 @@ def get_gsc_credentials(
config.GSC_SCOPE,
token_header="X-GSC-Access-Token",
creds_header="X-GSC-Credentials",
authorization=authorization,
)
@@ -167,7 +215,12 @@ def get_google_ads_credentials(
default=None,
alias="X-GAds-Access-Token",
description="Ready OAuth2 access token used directly as a Bearer token. "
"Takes precedence over X-GAds-Credentials.",
"Takes precedence over Authorization and X-GAds-Credentials.",
),
authorization: str | None = Header(
default=None,
alias="Authorization",
description=_authorization_description("X-GAds-Access-Token"),
),
x_gads_credentials: str | None = Header(
default=None,
@@ -199,6 +252,7 @@ def get_google_ads_credentials(
config.GOOGLE_ADS_SCOPE,
token_header="X-GAds-Access-Token",
creds_header="X-GAds-Credentials",
authorization=authorization,
)
login_customer_id = (x_gads_login_customer_id or "").strip().replace("-", "") or None
return GoogleAdsCredentials(
+9 -2
View File
@@ -45,6 +45,12 @@ jen prefixem hlavičky a oprávněním (scope). **Jeden service account lze pou
pro všechny tři** (stačí mu udělit přístup v dané službě a povolit příslušné
API). U Google Ads navíc vždy potřebujete *developer token*.
> 💡 Hotový OAuth2 *access token* lze u všech tří Google služeb poslat dvěma
> způsoby: buď v původní hlavičce `X-…-Access-Token`, **nebo** ve standardní
> hlavičce `Authorization: Bearer <token>`. Obě cesty jsou rovnocenné; pokud
> pošlete obě, vyhrává `X-…-Access-Token`. Pořadí priority je
> `X-…-Access-Token` → `Authorization: Bearer` → `X-…-Credentials`.
---
## Kde vzít přihlašovací údaje
@@ -65,9 +71,10 @@ API). U Google Ads navíc vždy potřebujete *developer token*.
Service account (jeho `client_email` z JSON) pak musíte **přidat jako uživatele
v dané službě** viz níže. Místo service accountu lze vždy poslat i hotový
OAuth2 *access token* v `*-Access-Token` (např. z
OAuth2 *access token* (např. z
[OAuth Playground](https://developers.google.com/oauthplayground/) se správným
scope); platí ~1 hodinu.
scope); platí ~1 hodinu. Token pošlete buď v `*-Access-Token`, nebo ve
standardní hlavičce `Authorization: Bearer <token>`.
### 🔹 Google Analytics 4 (`X-GA-*`)