Yoast\WP\SEO\MyYoast_Client\Infrastructure\OIDC
ID_Token_Validator::validate
Validates an ID token.
Метод класса: ID_Token_Validator{}
Хуков нет.
Возвращает
Массив<Строку,. string|int|array<string>> The validated ID token payload (claims).
Использование
$ID_Token_Validator = new ID_Token_Validator(); $ID_Token_Validator->validate( $id_token, $client_id, $expected_nonce ): array;
- $id_token(строка) (обязательный)
- The raw ID token JWT.
- $client_id(строка) (обязательный)
- The expected client_id (audience).
- $expected_nonce(строка) (обязательный)
- The nonce sent in the authorization request.
Код ID_Token_Validator::validate() ID Token Validator::validate Yoast 27.7
public function validate( string $id_token, string $client_id, string $expected_nonce ): array {
// Parse the header to get the kid.
$parts = \explode( '.', $id_token );
if ( \count( $parts ) !== 3 ) {
throw new ID_Token_Validation_Exception( 'Invalid ID token format.' );
}
$header = \json_decode( Base64url::decode( $parts[0] ), true );
if ( ! \is_array( $header ) ) {
throw new ID_Token_Validation_Exception( 'Invalid ID token header.' );
}
if ( ( $header['alg'] ?? '' ) !== self::EXPECTED_ALG ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
throw new ID_Token_Validation_Exception( 'Unsupported ID token algorithm: ' . ( $header['alg'] ?? 'none' ) );
}
// Fetch the public key from JWKS.
$public_key = $this->get_public_key( ( $header['kid'] ?? '' ) );
if ( $public_key === null ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
throw new ID_Token_Validation_Exception( 'No matching key found in JWKS for kid: ' . ( $header['kid'] ?? 'none' ) );
}
// Verify signature and time-based claims (exp, nbf, iat).
try {
$result = $this->jwt_signer->verify( $id_token, $public_key );
} catch ( JWT_Signature_Exception $e ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
throw new ID_Token_Validation_Exception( 'ID token signature verification failed: ' . $e->getMessage(), 0, $e );
} catch ( JWT_Validation_Exception $e ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
throw new ID_Token_Validation_Exception( 'ID token rejected: ' . $e->getMessage(), 0, $e );
}
$payload = $result['payload'];
// OIDC Core 1.0 §2: exp, iat and sub are required claims.
foreach ( [ 'exp', 'iat', 'sub' ] as $required_claim ) {
if ( ! isset( $payload[ $required_claim ] ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
throw new ID_Token_Validation_Exception( 'ID token is missing required claim: ' . $required_claim );
}
}
// Validate issuer.
$expected_issuer = $this->discovery_client->get_document()->get_issuer();
if ( ! \hash_equals( $expected_issuer, ( $payload['iss'] ?? '' ) ) ) {
throw new ID_Token_Validation_Exception( 'ID token issuer mismatch.' );
}
// Validate audience.
$aud = ( $payload['aud'] ?? '' );
if ( \is_array( $aud ) ) {
if ( ! \in_array( $client_id, $aud, true ) ) {
throw new ID_Token_Validation_Exception( 'ID token audience does not contain client_id.' );
}
// OIDC Core 1.0 §2: when aud has multiple values, azp MUST equal client_id.
$azp = ( $payload['azp'] ?? '' );
if ( $azp !== '' && $azp !== $client_id ) {
throw new ID_Token_Validation_Exception( 'ID token azp claim does not match client_id.' );
}
}
elseif ( $aud !== $client_id ) {
throw new ID_Token_Validation_Exception( 'ID token audience mismatch.' );
}
// Validate nonce.
if ( ! \hash_equals( $expected_nonce, ( $payload['nonce'] ?? '' ) ) ) {
throw new ID_Token_Validation_Exception( 'ID token nonce mismatch.' );
}
return $payload;
}