| @@ -79,10 +79,22 @@ | ||
| 79 | 79 | if ( empty( $return_url ) ) { |
| 80 | 80 | $return_url = admin_url( 'admin.php?page=templately' ); |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | + // Unique random state — doubles as cache busting and as the CSRF token the | |
| 84 | + // callback validates. Only minted into a transient for a logged-in user: | |
| 85 | + // this endpoint is public, and an anonymous caller could otherwise flood | |
| 86 | + // wp_options with tokens that can never authorize anything. | |
| 87 | + $state = wp_generate_password( 32, false ); | |
| 88 | + $state_owner = get_current_user_id(); | |
| 89 | + | |
| 90 | + if ( $state_owner > 0 ) { | |
| 91 | + Database::set_transient( 'google_state_' . $state, $state_owner, 15 * MINUTE_IN_SECONDS ); | |
| 92 | + } | |
| 93 | + | |
| 83 | 94 | $return_params = [ |
| 84 | 95 | 'templately_google_login' => '1', |
| 96 | + 'templately_state' => $state, | |
| 85 | 97 | ]; |
| 86 | 98 | |
| 87 | 99 | // Add redirect-to parameter if provided |
| 88 | 100 | if (!empty($redirect_to)) { |
| @@ -93,9 +105,9 @@ | ||
| 93 | 105 | |
| 94 | 106 | $query_params = [ |
| 95 | 107 | 'site_url' => urlencode($site_url_with_params), |
| 96 | 108 | 'site_ip' => Helper::get_ip(), |
| 97 | - 'state' => wp_generate_password(32, false) // Add unique random state for cache busting | |
| 109 | + 'state' => $state, | |
| 98 | 110 | ]; |
| 99 | 111 | |
| 100 | 112 | return add_query_arg($query_params, $auth_url); |
| 101 | 113 | } |
| @@ -180,8 +192,9 @@ | ||
| 180 | 192 | } |
| 181 | 193 | |
| 182 | 194 | $headers = [ |
| 183 | 195 | 'Content-Type' => 'application/json', |
| 196 | + 'Accept' => 'application/json', | |
| 184 | 197 | 'x-templately-ip' => Helper::get_ip(), |
| 185 | 198 | 'x-templately-url' => home_url( '/' ), |
| 186 | 199 | 'x-templately-version' => TEMPLATELY_VERSION, |
| 187 | 200 | ]; |