Loading…
Loading…
Explains how the Admin API's IdentityResolver component determines a caller's identity from tokens, headers, and request attributes in a strict order.
The IdentityResolver is the canonical component within the Admin API responsible for determining the identity of a caller. It centralizes all identity resolution logic, providing a single point of truth for who is making a request.
The component solves the problem of supporting multiple authentication mechanisms by examining an incoming HttpServletRequest for various identity signals in a precise, fallback order. Its primary output is the caller's email address, which is then used by other services, such as AdminAuthorizationFilter, to make authorization decisions.
IdentityResolver is designed to be secure by default, with explicit configuration required to enable less secure modes for local development. It includes several startup guards to prevent insecure configurations in production environments.
The IdentityResolver attempts to find a caller's email address by checking for credentials in a specific, sequential order. The first valid identity found is used, and the process stops.
IdP Bearer Token: It first checks for an email address verified by the IdpAuthFilter. This filter processes a Bearer token from an external Identity Provider (IdP), and if valid, stores the user's email in the s2r.identity.idp-verified-email request attribute.
Identity-Aware Proxy (IAP) Assertion: If no IdP-verified email is found, it looks for the X-Goog-IAP-JWT-Assertion HTTP header. If this header is present, its JWT value is verified for signature, issuer, expiry, and audience by the IapJwtVerifier.
IMPORTANT
If the X-Goog-IAP-JWT-Assertion header is present but the assertion is invalid, resolution fails and returns no identity. The resolver does not fall through to subsequent methods.
Developer Identity Headers: If and only if the s2r.admin.auth.dev-identity-headers configuration flag is enabled, the resolver will trust plain, unverified HTTP headers to determine identity. The following headers are checked in order:
X-Goog-Authenticated-User-EmailX-User-EmailX-ActorNo Identity: If none of the above methods yield an identity, the request is considered anonymous by the IdentityResolver.
The following diagram illustrates this resolution logic:
flowchart TD
A[Incoming Request] --> B{IdP-verified email<br>in request attribute?};
B -- Yes --> C[Identity is email from attribute];
B -- No --> D{X-Goog-IAP-JWT-Assertion<br>header present?};
D -- No --> G{Developer mode enabled?};
D -- Yes --> E{Assertion is valid?};
E -- Yes --> F[Identity is email from assertion];
E -- No --> Z[No identity];
G -- No --> Z;
G -- Yes --> H{X-Goog-Authenticated-User-Email<br>header present?};
H -- Yes --> I[Identity is email from header];
H -- No --> J{X-User-Email<br>header present?};
J -- Yes --> I;
J -- No --> K{X-Actor<br>header present?};
K -- Yes --> I;
K -- No --> Z;The IdentityResolver includes a developer mode that allows a caller to claim any identity by setting a simple HTTP header. This mode is controlled by the s2r.admin.auth.dev-identity-headers configuration property.
CAUTION
This mode is for local development only. When enabled, the Admin API trusts unverified headers, allowing any caller who can reach the service to impersonate any user. Never enable this flag in a deployed or production environment.
When s2r.admin.auth.dev-identity-headers is true, the resolver logs the following error message at startup to ensure visibility:
S2R-AUTH dev-identity-headers is ON: plain X-Goog-Authenticated-User-Email / X-User-Email / X-Actor headers are trusted without verification. Any caller can claim any identity. Never enable this outside local development.
To prevent accidental use of developer mode in a production setting, the application will fail to start if s2r.admin.auth.dev-identity-headers is enabled while any of the following conditions are met:
s2r.iap.audience property.K_SERVICE environment variable is set, which indicates the process is running in a managed environment (e.g., Knative, Cloud Run).The behavior of the IdentityResolver is controlled by the following configuration properties.
| Name | Type | Default | Description |
|---|---|---|---|
s2r.admin.auth.dev-identity-headers | Boolean | false | If true, enables developer mode, trusting plain headers for identity. Can also be set with the S2R_ADMIN_DEV_IDENTITY_HEADERS environment variable. |
s2r.iap.audience | String | "" (empty string) | The audience value expected in IAP JWT assertions. Used to prevent developer mode from being enabled with an IAP. |
The resolver also inspects the following environment variable:
| Name | Description |
|---|---|
K_SERVICE | Set by Knative-based serving environments. Its presence indicates a deployed service, which prevents developer mode from being enabled. |
The IdentityResolver component exposes the following methods.
| Method | Description |
|---|---|
Optional<String> resolveEmail(HttpServletRequest request) | The primary method. Executes the identity resolution flow on the given request and returns an Optional containing the caller's email if found, or an empty Optional otherwise. |
boolean devIdentityHeadersEnabled() | Returns true if the s2r.admin.auth.dev-identity-headers property is enabled. |
static Optional<String> authenticatedActorEmail(HttpServletRequest request) | A static helper that retrieves the actor's email from a request attribute (s2r.auth.actor-email). This attribute is set by the AdminAuthorizationFilter after it has used resolveEmail. |
static Optional<String> authenticatedActorRole(HttpServletRequest request) | A static helper that retrieves the actor's role from a request attribute (s2r.auth.actor-role). This attribute is set by the AdminAuthorizationFilter. |
The resolver reads the following HTTP headers and request attributes to determine identity.
| Name | Type | Purpose |
|---|---|---|
s2r.identity.idp-verified-email | Request Attribute | Contains the email address from a Bearer token verified by the IdpAuthFilter. This is the highest-priority identity signal. |
X-Goog-IAP-JWT-Assertion | HTTP Header | Contains the JWT assertion from an Identity-Aware Proxy. |
X-Goog-Authenticated-User-Email | HTTP Header | A plain header used for identity in developer mode. It may contain a prefix (e.g., accounts.google.com:) which is stripped. |
X-User-Email | HTTP Header | A plain header used for identity in developer mode. It may contain a prefix which is stripped. |
X-Actor | HTTP Header | A plain header used for identity in developer mode. |
The application will fail to start with an IllegalStateException if s2r.admin.auth.dev-identity-headers is enabled under insecure conditions.
| Error Message | Cause |
|---|---|
S2R-AUTH refusing to start: s2r.admin.auth.dev-identity-headers (S2R_ADMIN_DEV_IDENTITY_HEADERS) is on while an identity-aware-proxy audience (s2r.iap.audience) is configured. Plain identity headers are for local development only; turn the flag off. | s2r.admin.auth.dev-identity-headers is true and s2r.iap.audience has a non-blank value. |
S2R-AUTH refusing to start: s2r.admin.auth.dev-identity-headers (S2R_ADMIN_DEV_IDENTITY_HEADERS) is on in a deployed service (K_SERVICE is set). Plain identity headers let any caller claim any identity and are for local development only; remove S2R_ADMIN_DEV_IDENTITY_HEADERS from the service. | s2r.admin.auth.dev-identity-headers is true and the K_SERVICE environment variable is set. |
S2R-AUTH refusing to start: s2r.admin.auth.dev-identity-headers (S2R_ADMIN_DEV_IDENTITY_HEADERS) is on and the active identity providers could not be read (...). Fix database access or turn the flag off. | s2r.admin.auth.dev-identity-headers is true, but the system could not query the database to check for active IdP configurations. |
S2R-AUTH refusing to start: s2r.admin.auth.dev-identity-headers (S2R_ADMIN_DEV_IDENTITY_HEADERS) is on while N identity provider(s) are active, so requests without a Bearer token could claim any identity through plain headers. Turn the flag off, or deactivate the identity providers for local development. | s2r.admin.auth.dev-identity-headers is true while the database contains one or more active IdP configurations. |
IdpAuthFilter is responsible for validating Bearer tokens and is the first source of identity checked by the IdentityResolver.IapJwtVerifier is responsible for validating JWTs from an IAP, which is the second source of identity.AdminAuthorizationFilter consumes the identity produced by IdentityResolver to grant or deny access to API resources.