Yoast\WP\SEO\MyYoast_Client\Application

OAuth_Grant_Handler::request_tokenpublicYoast 1.0

Executes a token endpoint request using the provided grant strategy.

Ensures the client is registered, creates a client assertion, merges grant-specific parameters, and sends the request. The resource indicator is added to the body (unless it's the default-resource instance) and stamped onto the resulting Token_Set so storage and audit code can introspect the audience.

Метод класса: OAuth_Grant_Handler{}

Хуков нет.

Возвращает

Token_Set. The token set from the response.

Использование

$OAuth_Grant_Handler = new OAuth_Grant_Handler();
$OAuth_Grant_Handler->request_token( $grant, $resource_indicator ): Token_Set;
$grant(Grant_Interface) (обязательный)
The grant strategy providing grant-specific parameters.
$resource_indicator(Resource_Indicator) (обязательный)
The resource indicator (RFC 8707) the grant targets. Use Resource_Indicator::default() for the default resource.

Код OAuth_Grant_Handler::request_token() Yoast 28.3

public function request_token( Grant_Interface $grant, Resource_Indicator $resource_indicator ): Token_Set {
	// A token request requires an existing registration; it never triggers DCR or a
	// redirect-URI update — that is the connect flow's responsibility.
	$registered_client = $this->client_registration->get_registered_client();
	if ( $registered_client === null ) {
		throw new Token_Request_Failed_Exception( 'not_registered', 'Site is not registered with MyYoast; complete the connect flow first.' );
	}

	try {
		$token_endpoint = $this->discovery->get_document()->get_token_endpoint();
	} catch ( Discovery_Failed_Exception | Server_Capability_Exception $e ) {
		// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
		throw new Token_Request_Failed_Exception( 'discovery_failed', $e->getMessage(), 0, $e );
	}

	$client_id = $registered_client->get_client_id();

	try {
		$client_assertion = $this->client_authenticator->create_client_assertion( $client_id, $token_endpoint );
	} catch ( Client_Authentication_Exception $e ) {
		// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
		throw new Token_Request_Failed_Exception( 'client_authentication_failed', $e->getMessage(), 0, $e );
	}

	$body = \array_merge(
		[
			'grant_type'            => $grant->get_grant_type(),
			'client_id'             => $client_id,
			'client_assertion_type' => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
			'client_assertion'      => $client_assertion,
		],
		$grant->get_grant_params(),
	);

	// RFC 8707 resource indicator is cross-cutting — independent of grant type.
	// The Resource_Indicator value object proves the value is already canonical.
	if ( ! $resource_indicator->is_default() ) {
		$body['resource'] = $resource_indicator->value();
	}

	$result = $this->oauth_server_client->request(
		'POST',
		$token_endpoint,
		[
			'headers' => [ 'Content-Type' => 'application/x-www-form-urlencoded' ],
			'body'    => $body,
			'dpop'    => true,
		],
	);

	if ( ! $result->is_successful() ) {
		$error       = (string) $result->get_body_value( 'error', 'unknown' );
		$description = (string) $result->get_body_value( 'error_description', '' );
		$this->logger->warning(
			'Token request failed for grant {grant_type}: HTTP {status}, error={error} {description}',
			[
				'grant_type'  => $grant->get_grant_type(),
				'status'      => $result->get_status(),
				'error'       => $error,
				'description' => $description,
			],
		);

		$body = $result->get_body();
		if ( \is_array( $body ) && isset( $body['error'] ) ) {
			// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
			throw Token_Request_Failed_Exception::from_response( $body, $result->get_status() );
		}
		// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
		throw new Token_Request_Failed_Exception( 'token_request_failed', 'HTTP ' . $result->get_status(), $result->get_status() );
	}

	$body = $result->get_body();
	if ( ! \is_array( $body ) ) {
		throw new Token_Request_Failed_Exception( 'invalid_token_response', 'Token endpoint did not return a JSON object.' );
	}

	try {
		$token_set = Token_Set::from_response( $body );
	} catch ( InvalidArgumentException $e ) {
		// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
		throw new Token_Request_Failed_Exception( 'invalid_token_response', $e->getMessage(), 0, $e );
	}

	// Per RFC 8707's trust model (§2, §4), the client is authoritative for the
	// canonical resource indicator. We always stamp the requested value on the
	// result rather than honouring any echoed `resource` field from the AS.
	return $token_set->with_resource_indicator( $resource_indicator );
}