PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 27.7
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v27.7
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / src / myyoast-client / domain / auth-flow-state.php

auth-flow-state.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 27.7, at src/myyoast-client/domain/auth-flow-state.php

173 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yoast\WP\SEO\MyYoast_Client\Domain;
4
5 use InvalidArgumentException;
6
7 /**
8 * Immutable value object representing the state of an in-progress authorization code flow.
9 *
10 * Stores the PKCE code verifier, CSRF state, nonce, redirect URI, and optional
11 * return URL for post-authorization redirect.
12 */
13 class Auth_Flow_State {
14
15 /**
16 * The PKCE code verifier.
17 *
18 * @var string
19 */
20 private $code_verifier;
21
22 /**
23 * The CSRF state parameter.
24 *
25 * @var string
26 */
27 private $state;
28
29 /**
30 * The nonce for ID token replay protection (only set when openid scope is requested).
31 *
32 * @var string|null
33 */
34 private $nonce;
35
36 /**
37 * The callback redirect URI.
38 *
39 * @var string
40 */
41 private $redirect_uri;
42
43 /**
44 * The URL to return the user to after authorization completes.
45 *
46 * @var string|null
47 */
48 private $return_url;
49
50 /**
51 * Auth_Flow_State constructor.
52 *
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.
58 *
59 * @throws InvalidArgumentException If required fields are empty.
60 */
61 public function __construct(
62 string $code_verifier,
63 string $state,
64 ?string $nonce,
65 string $redirect_uri,
66 ?string $return_url = null
67 ) {
68 if ( $code_verifier === '' || $state === '' || $redirect_uri === '' ) {
69 throw new InvalidArgumentException( 'Auth_Flow_State requires non-empty code_verifier, state, and redirect_uri.' );
70 }
71
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;
77 }
78
79 /**
80 * Returns the PKCE code verifier.
81 *
82 * @return string
83 */
84 public function get_code_verifier(): string {
85 return $this->code_verifier;
86 }
87
88 /**
89 * Returns the CSRF state parameter.
90 *
91 * @return string
92 */
93 public function get_state(): string {
94 return $this->state;
95 }
96
97 /**
98 * Returns the nonce.
99 *
100 * @return string|null
101 */
102 public function get_nonce(): ?string {
103 return $this->nonce;
104 }
105
106 /**
107 * Returns the callback redirect URI.
108 *
109 * @return string
110 */
111 public function get_redirect_uri(): string {
112 return $this->redirect_uri;
113 }
114
115 /**
116 * Returns the post-authorization return URL.
117 *
118 * @return string|null
119 */
120 public function get_return_url(): ?string {
121 return $this->return_url;
122 }
123
124 /**
125 * Converts the state to an associative array for storage.
126 *
127 * @return array<string, string|null>
128 */
129 public function to_array(): array {
130 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,
136 ];
137 }
138
139 /**
140 * Creates an Auth_Flow_State from a stored array.
141 *
142 * @param array<string, string|null> $data The stored array data.
143 *
144 * @return self
145 *
146 * @throws InvalidArgumentException If required fields are missing or have invalid types.
147 */
148 public static function from_array( array $data ): self {
149 $required = [ 'code_verifier', 'state', 'redirect_uri' ];
150 foreach ( $required as $key ) {
151 if ( ! isset( $data[ $key ] ) || ! \is_string( $data[ $key ] ) ) {
152 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
153 throw new InvalidArgumentException( "Auth_Flow_State::from_array() requires a string value for '{$key}'." );
154 }
155 }
156 $optional_strings = [ 'nonce', 'return_url' ];
157 foreach ( $optional_strings as $key ) {
158 if ( isset( $data[ $key ] ) && ! \is_string( $data[ $key ] ) ) {
159 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Internal exception message.
160 throw new InvalidArgumentException( "Auth_Flow_State::from_array() requires '{$key}' to be a string or null." );
161 }
162 }
163
164 return new self(
165 $data['code_verifier'],
166 $data['state'],
167 ( $data['nonce'] ?? null ),
168 $data['redirect_uri'],
169 ( $data['return_url'] ?? null ),
170 );
171 }
172 }
173