Loading…
Loading…
Explains how the platform verifies X-Goog-IAP-JWT-Assertion headers using JWKS public keys to authenticate administrative users.
The IAP JWT Verifier is a security component responsible for validating JSON Web Token (JWT) assertions provided by an Identity-Aware Proxy (IAP). It ensures that any request to the administrative API is accompanied by a valid identity assertion, which is passed in the X-Goog-IAP-JWT-Assertion HTTP header.
This component solves the problem of authenticating users in environments where access is managed by an IAP. It cryptographically verifies that the JWT was issued by the trusted IAP, has not expired, is intended for the correct backend service, and contains a valid user identity. The verifier's primary input is the JWT string from the header, and its output is the verified user's email address. If verification fails for any reason, access is denied.
The verifier processes each IAP assertion through a multi-step validation pipeline. The process is fail-closed, meaning any failure or ambiguity during validation results in the rejection of the assertion.
sequenceDiagram
participant C as API Consumer
participant IAP as Identity-Aware Proxy
participant Admin as Admin API
participant V as IAP JWT Verifier
C->>+IAP: Request to Admin API
IAP->>IAP: Authenticates user
IAP-->>+Admin: Forward request with<br>X-Goog-IAP-JWT-Assertion header
Admin->>+V: verifyEmail(JWT)
V->>V: Parse and validate JWT
V-->>-Admin: Return verified email or empty
Admin->>Admin: If email present, authorize user
Admin-->>-IAP: Process or reject request
IAP-->>-C: API ResponseWhen the verifyEmail method is called with a JWT assertion, it performs the following sequence of checks:
alg) and the key identifier (kid).alg is ES256. Assertions signed with any other algorithm are rejected.kid is used to find the corresponding public key needed to verify the signature.
KEY_TTL_MS).kid is in the cache and not expired, it is used immediately.MIN_REFRESH_INTERVAL_MS).iss (Issuer): Must be exactly https://cloud.google.com/iap.exp (Expiration Time): Must be in the future.iat (Issued At): Must be in the past.exp and iat checks allow for a 30-second clock skew (CLOCK_SKEW_SECONDS) to accommodate minor time differences between servers.aud (Audience) claim is validated to ensure the token was intended for this specific API. This validation operates in one of two modes. See Audience Validation Modes for details.email claim.
accounts.google.com: prefix if present.securetoken.google.com/ prefix. See External Identity Normalization for the specific conditions.@ symbol.The aud claim identifies the recipient for which the JWT is intended. The verifier supports two modes for validating this claim.
If the s2r.iap.audience configuration property is set, the verifier operates in a strict "pinned" mode. The JWT's aud claim must be a single string that exactly matches the configured value. This is the most secure configuration.
If s2r.iap.audience is not set, the verifier dynamically validates the audience.
WARNING
When s2r.iap.audience is not set, a warning is logged once upon startup. The platform will only accept assertions issued for a backend service belonging to the platform's own project. It is strongly recommended to pin the audience by setting this property to the exact audience value of your backend service.
In this mode, the aud claim must be a string matching the pattern /projects/<project_number>/<location>/backendServices/<service_id>. The verifier performs these checks:
s2r.iap.project-number configuration property. If that is not set, it attempts to discover the number from the runtime environment metadata.aud claim starts with /projects/<own_project_number>/.The platform can process assertions for users from external identity providers. These identities often have a unique prefix in the email claim, such as securetoken.google.com/<PROJECT>/<TENANT>:<user_email>.
IMPORTANT
The verifier will only strip this prefix and normalize the email address if all of the following conditions are met:
<PROJECT> or <PROJECT>/<TENANT> part) is explicitly listed in the s2r.iap.external-identity-trusted-tenants configuration property.gcip claim.gcip claim contains a field email_verified with a boolean value of true.If any of these conditions are not met, the prefix is not stripped. This prevents a user from an untrusted tenant or with an unverified email from impersonating a legitimate user with the same email address.
The IAP JWT Verifier is configured through the following properties.
| Property | Type | Default Value | Description
| --- | --- | --- |
| s2r.iap.jwks-url | String | https://www.gstatic.com/iap/verify/public_key-jwk | The URL from which to fetch the IAP's ES256 public keys in JWKS format. The key fetch respects proxy settings configured for the platform.
| s2r.iap.audience | String | — | The exact audience value expected in the JWT aud claim. If not set, the verifier uses dynamic audience validation. Setting this is highly recommended.
| s2r.iap.project-number | String | — | The numeric project number of the deployment. Used for dynamic audience validation if s2r.iap.audience is not set. Must be a string of 1 to 20 digits. If not set, the platform attempts to discover it from the environment.
| s2r.iap.external-identity-trusted-tenants | String | "" (empty) | A comma-separated list of trusted external identity issuers. An issuer is a PROJECT or PROJECT/TENANT string. This list is required to normalize emails from external identities.
When an IAP assertion is rejected, a warning is logged with a reason. The assertion token itself is never logged.
S2R-AUTH IAP assertion rejected: unsupported alg ... | The JWT was signed with an algorithm other than ES256. The IAP should be configured to use ES256.
| S2R-AUTH IAP assertion rejected: assertion missing kid header | The JWT header does not contain a kid (Key ID). This indicates a malformed token from the IAP.S2R-AUTH IAP assertion rejected: unknown kid | The kid from the JWT header does not match any of the public keys fetched from the JWKS URL. This can happen during a key rotation. The verifier will attempt to fetch new keys. If it persists, check that the s2r.iap.jwks-url is correct.
| S2R-AUTH IAP assertion rejected: assertion aud does not match | The aud claim in the JWT does not match what the verifier expects. If s2r.iap.audience is set, ensure it exactly matches the IAP configuration. If it's not set, ensure the IAP is configured for a backend service in the same project as the platform, and that the platform can determine its project number.
| S2R-AUTH IAP assertion rejected: ... (other reasons) | Includes assertion missing exp or iat, iat is in the future, missing email claim, etc. These usually indicate a malformed or invalid token. Check for clock synchronization issues between the platform and the identity provider.
| S2R-AUTH IAP JWKS fetch failed ... (ERROR log) | The verifier could not connect to or fetch from the s2r.iap.jwks-url. It will continue to use stale keys if any are cached. Check network connectivity, DNS, and any egress proxy configuration between the platform and the JWKS endpoint.| S2R-AUTH IAP project number unknown ... (ERROR log) | This error is logged once if s2r.iap.audience is not set and the platform could not determine its project number from s2r.iap.project-number or the environment. In this state, all IAP assertions will be denied. To fix, set either s2r.iap.audience or s2r.iap.project-number.