token variant
This commit is contained in:
+60
-6
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user