← All changes
|
src/myyoast-client/application/oauth-grant-handler.php
+26
-5
27.7
→
trunk
View file →
| @@ -12,8 +12,9 @@ | ||
| 12 | 12 | use Yoast\WP\SEO\MyYoast_Client\Application\Ports\Client_Authenticator_Interface; |
| 13 | 13 | use Yoast\WP\SEO\MyYoast_Client\Application\Ports\Client_Registration_Interface; |
| 14 | 14 | use Yoast\WP\SEO\MyYoast_Client\Application\Ports\Discovery_Interface; |
| 15 | 15 | use Yoast\WP\SEO\MyYoast_Client\Application\Ports\OAuth_Server_Client_Interface; |
| 16 | +use Yoast\WP\SEO\MyYoast_Client\Domain\Resource_Indicator; | |
| 16 | 17 | use Yoast\WP\SEO\MyYoast_Client\Domain\Token_Set; |
| 17 | 18 | use YoastSEO_Vendor\Psr\Log\LoggerAwareInterface; |
| 18 | 19 | use YoastSEO_Vendor\Psr\Log\LoggerAwareTrait; |
| 19 | 20 | use YoastSEO_Vendor\Psr\Log\NullLogger; |
| @@ -80,18 +81,27 @@ | ||
| 80 | 81 | /** |
| 81 | 82 | * Executes a token endpoint request using the provided grant strategy. |
| 82 | 83 | * |
| 83 | 84 | * Ensures the client is registered, creates a client assertion, merges |
| 84 | - * grant-specific parameters, and sends the request. | |
| 85 | + * grant-specific parameters, and sends the request. The resource indicator | |
| 86 | + * is added to the body (unless it's the default-resource instance) and | |
| 87 | + * stamped onto the resulting Token_Set so storage and audit code can | |
| 88 | + * introspect the audience. | |
| 85 | 89 | * |
| 86 | - * @param Grant_Interface $grant The grant strategy providing grant-specific parameters. | |
| 90 | + * @param Grant_Interface $grant The grant strategy providing grant-specific parameters. | |
| 91 | + * @param Resource_Indicator $resource_indicator The resource indicator (RFC 8707) the grant targets. Use Resource_Indicator::default() for the default resource. | |
| 87 | 92 | * |
| 88 | 93 | * @return Token_Set The token set from the response. |
| 89 | 94 | * |
| 90 | 95 | * @throws Token_Request_Failed_Exception If the token request fails. |
| 91 | 96 | */ |
| 92 | - public function request_token( Grant_Interface $grant ): Token_Set { | |
| 93 | - $registered_client = $this->client_registration->ensure_registered(); | |
| 97 | + public function request_token( Grant_Interface $grant, Resource_Indicator $resource_indicator ): Token_Set { | |
| 98 | + // A token request requires an existing registration; it never triggers DCR or a | |
| 99 | + // redirect-URI update — that is the connect flow's responsibility. | |
| 100 | + $registered_client = $this->client_registration->get_registered_client(); | |
| 101 | + if ( $registered_client === null ) { | |
| 102 | + throw new Token_Request_Failed_Exception( 'not_registered', 'Site is not registered with MyYoast; complete the connect flow first.' ); | |
| 103 | + } | |
| 94 | 104 | |
| 95 | 105 | try { |
| 96 | 106 | $token_endpoint = $this->discovery->get_document()->get_token_endpoint(); |
| 97 | 107 | } catch ( Discovery_Failed_Exception | Server_Capability_Exception $e ) { |
| @@ -117,8 +127,14 @@ | ||
| 117 | 127 | ], |
| 118 | 128 | $grant->get_grant_params(), |
| 119 | 129 | ); |
| 120 | 130 | |
| 131 | + // RFC 8707 resource indicator is cross-cutting — independent of grant type. | |
| 132 | + // The Resource_Indicator value object proves the value is already canonical. | |
| 133 | + if ( ! $resource_indicator->is_default() ) { | |
| 134 | + $body['resource'] = $resource_indicator->value(); | |
| 135 | + } | |
| 136 | + | |
| 121 | 137 | $result = $this->oauth_server_client->request( |
| 122 | 138 | 'POST', |
| 123 | 139 | $token_endpoint, |
| 124 | 140 | [ |
| @@ -155,11 +171,16 @@ | ||
| 155 | 171 | throw new Token_Request_Failed_Exception( 'invalid_token_response', 'Token endpoint did not return a JSON object.' ); |
| 156 | 172 | } |
| 157 | 173 | |
| 158 | 174 | try { |
| 159 | - return Token_Set::from_response( $body ); | |
| 175 | + $token_set = Token_Set::from_response( $body ); | |
| 160 | 176 | } catch ( InvalidArgumentException $e ) { |
| 161 | 177 | // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message. |
| 162 | 178 | throw new Token_Request_Failed_Exception( 'invalid_token_response', $e->getMessage(), 0, $e ); |
| 163 | 179 | } |
| 180 | + | |
| 181 | + // Per RFC 8707's trust model (§2, §4), the client is authoritative for the | |
| 182 | + // canonical resource indicator. We always stamp the requested value on the | |
| 183 | + // result rather than honouring any echoed `resource` field from the AS. | |
| 184 | + return $token_set->with_resource_indicator( $resource_indicator ); | |
| 164 | 185 | } |
| 165 | 186 | } |