| @@ -47,15 +47,23 @@ | ||
| 47 | 47 | */ |
| 48 | 48 | private $return_url; |
| 49 | 49 | |
| 50 | 50 | /** |
| 51 | + * The RFC 8707 resource indicator this flow targets. | |
| 52 | + * | |
| 53 | + * @var Resource_Indicator | |
| 54 | + */ | |
| 55 | + private $resource_indicator; | |
| 56 | + | |
| 57 | + /** | |
| 51 | 58 | * Auth_Flow_State constructor. |
| 52 | 59 | * |
| 53 | - * @param string $code_verifier The PKCE code verifier. | |
| 54 | - * @param string $state The CSRF state parameter. | |
| 55 | - * @param string|null $nonce The nonce for ID token validation (only when openid scope is requested). | |
| 56 | - * @param string $redirect_uri The callback redirect URI. | |
| 57 | - * @param string|null $return_url The URL to return the user to after authorization. | |
| 60 | + * @param string $code_verifier The PKCE code verifier. | |
| 61 | + * @param string $state The CSRF state parameter. | |
| 62 | + * @param string|null $nonce The nonce for ID token validation (only when openid scope is requested). | |
| 63 | + * @param string $redirect_uri The callback redirect URI. | |
| 64 | + * @param string|null $return_url The URL to return the user to after authorization. | |
| 65 | + * @param Resource_Indicator $resource_indicator The resource indicator (RFC 8707) this flow targets. Use Resource_Indicator::default() for the default resource. | |
| 58 | 66 | * |
| 59 | 67 | * @throws InvalidArgumentException If required fields are empty. |
| 60 | 68 | */ |
| 61 | 69 | public function __construct( |
| @@ -62,19 +70,21 @@ | ||
| 62 | 70 | string $code_verifier, |
| 63 | 71 | string $state, |
| 64 | 72 | ?string $nonce, |
| 65 | 73 | string $redirect_uri, |
| 66 | - ?string $return_url = null | |
| 74 | + ?string $return_url, | |
| 75 | + Resource_Indicator $resource_indicator | |
| 67 | 76 | ) { |
| 68 | 77 | if ( $code_verifier === '' || $state === '' || $redirect_uri === '' ) { |
| 69 | 78 | throw new InvalidArgumentException( 'Auth_Flow_State requires non-empty code_verifier, state, and redirect_uri.' ); |
| 70 | 79 | } |
| 71 | 80 | |
| 72 | - $this->code_verifier = $code_verifier; | |
| 73 | - $this->state = $state; | |
| 74 | - $this->nonce = $nonce; | |
| 75 | - $this->redirect_uri = $redirect_uri; | |
| 76 | - $this->return_url = $return_url; | |
| 81 | + $this->code_verifier = $code_verifier; | |
| 82 | + $this->state = $state; | |
| 83 | + $this->nonce = $nonce; | |
| 84 | + $this->redirect_uri = $redirect_uri; | |
| 85 | + $this->return_url = $return_url; | |
| 86 | + $this->resource_indicator = $resource_indicator; | |
| 77 | 87 | } |
| 78 | 88 | |
| 79 | 89 | /** |
| 80 | 90 | * Returns the PKCE code verifier. |
| @@ -121,8 +131,17 @@ | ||
| 121 | 131 | return $this->return_url; |
| 122 | 132 | } |
| 123 | 133 | |
| 124 | 134 | /** |
| 135 | + * Returns the RFC 8707 resource indicator this flow targets. | |
| 136 | + * | |
| 137 | + * @return Resource_Indicator | |
| 138 | + */ | |
| 139 | + public function get_resource_indicator(): Resource_Indicator { | |
| 140 | + return $this->resource_indicator; | |
| 141 | + } | |
| 142 | + | |
| 143 | + /** | |
| 125 | 144 | * Converts the state to an associative array for storage. |
| 126 | 145 | * |
| 127 | 146 | * @return array<string, string|null> |
| 128 | 147 | */ |
| @@ -127,13 +146,14 @@ | ||
| 127 | 146 | * @return array<string, string|null> |
| 128 | 147 | */ |
| 129 | 148 | public function to_array(): array { |
| 130 | 149 | return [ |
| 131 | - 'code_verifier' => $this->code_verifier, | |
| 132 | - 'state' => $this->state, | |
| 133 | - 'nonce' => $this->nonce, | |
| 134 | - 'redirect_uri' => $this->redirect_uri, | |
| 135 | - 'return_url' => $this->return_url, | |
| 150 | + 'code_verifier' => $this->code_verifier, | |
| 151 | + 'state' => $this->state, | |
| 152 | + 'nonce' => $this->nonce, | |
| 153 | + 'redirect_uri' => $this->redirect_uri, | |
| 154 | + 'return_url' => $this->return_url, | |
| 155 | + 'resource_indicator' => $this->resource_indicator->value(), | |
| 136 | 156 | ]; |
| 137 | 157 | } |
| 138 | 158 | |
| 139 | 159 | /** |
| @@ -152,9 +172,9 @@ | ||
| 152 | 172 | // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message. |
| 153 | 173 | throw new InvalidArgumentException( "Auth_Flow_State::from_array() requires a string value for '{$key}'." ); |
| 154 | 174 | } |
| 155 | 175 | } |
| 156 | - $optional_strings = [ 'nonce', 'return_url' ]; | |
| 176 | + $optional_strings = [ 'nonce', 'return_url', 'resource_indicator' ]; | |
| 157 | 177 | foreach ( $optional_strings as $key ) { |
| 158 | 178 | if ( isset( $data[ $key ] ) && ! \is_string( $data[ $key ] ) ) { |
| 159 | 179 | // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message. |
| 160 | 180 | throw new InvalidArgumentException( "Auth_Flow_State::from_array() requires '{$key}' to be a string or null." ); |
| @@ -160,8 +180,10 @@ | ||
| 160 | 180 | throw new InvalidArgumentException( "Auth_Flow_State::from_array() requires '{$key}' to be a string or null." ); |
| 161 | 181 | } |
| 162 | 182 | } |
| 163 | 183 | |
| 184 | + $stored_indicator = ( $data['resource_indicator'] ?? null ); | |
| 185 | + | |
| 164 | 186 | return new self( |
| 165 | 187 | $data['code_verifier'], |
| 166 | 188 | $data['state'], |
| 167 | 189 | ( $data['nonce'] ?? null ), |
| @@ -166,7 +188,8 @@ | ||
| 166 | 188 | $data['state'], |
| 167 | 189 | ( $data['nonce'] ?? null ), |
| 168 | 190 | $data['redirect_uri'], |
| 169 | 191 | ( $data['return_url'] ?? null ), |
| 192 | + new Resource_Indicator( ( \is_string( $stored_indicator ) && $stored_indicator !== '' ) ? $stored_indicator : null ), | |
| 170 | 193 | ); |
| 171 | 194 | } |
| 172 | 195 | } |