PluginProbe ʕ •ᴥ•ʔ
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More / 4.0.7
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More v4.0.7
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 trunk 1.0.0 2.0.0 2.0.1 2.0.2 2.0.3 3.0 3.0.1 3.0.2 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 3.2.0 3.2.1 3.2.2 3.2.4 3.2.5 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1
superb-blocks / src / gutenberg / form / class-form-google-auth.php
superb-blocks / src / gutenberg / form Last commit date
class-form-access-control.php 4 days ago class-form-captcha-handler.php 4 days ago class-form-controller.php 4 days ago class-form-email-config-check.php 4 days ago class-form-email-handler.php 4 days ago class-form-encryption.php 4 days ago class-form-exporter.php 4 days ago class-form-field-validator.php 4 days ago class-form-file-handler.php 4 days ago class-form-google-auth.php 4 days ago class-form-integration-handler.php 4 days ago class-form-math-parser.php 4 days ago class-form-permissions.php 4 days ago class-form-registry.php 4 days ago class-form-settings.php 4 days ago class-form-submission-cpt.php 4 days ago class-form-submission-handler.php 4 days ago
class-form-google-auth.php
120 lines
1 <?php
2
3 namespace SuperbAddons\Gutenberg\Form;
4
5 defined('ABSPATH') || exit();
6
7 class FormGoogleAuth
8 {
9 const TRANSIENT_KEY = 'spb_google_token';
10 const TOKEN_URL = 'https://oauth2.googleapis.com/token';
11 const SCOPE = 'https://www.googleapis.com/auth/spreadsheets';
12
13 /**
14 * Get a valid access token, using cached transient or fetching a new one.
15 *
16 * @return string|\WP_Error Access token string or WP_Error on failure.
17 */
18 public static function GetAccessToken()
19 {
20 $cached = get_transient(self::TRANSIENT_KEY);
21 if (!empty($cached)) {
22 return $cached;
23 }
24
25 $client_email = FormSettings::Get(FormSettings::OPTION_GOOGLE_SHEETS_CLIENT_EMAIL);
26 $private_key = FormSettings::Get(FormSettings::OPTION_GOOGLE_SHEETS_PRIVATE_KEY);
27
28 if (empty($client_email) || empty($private_key)) {
29 return new \WP_Error('no_credentials', __('Google Sheets credentials are not configured.', 'superb-blocks'));
30 }
31
32 $jwt = self::CreateJWT($client_email, $private_key, self::SCOPE);
33 if (is_wp_error($jwt)) {
34 return $jwt;
35 }
36
37 $response = wp_remote_post(self::TOKEN_URL, array(
38 'body' => array(
39 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
40 'assertion' => $jwt,
41 ),
42 'timeout' => 15,
43 ));
44
45 if (is_wp_error($response)) {
46 return new \WP_Error('token_request_failed', $response->get_error_message());
47 }
48
49 $code = wp_remote_retrieve_response_code($response);
50 if ($code !== 200) {
51 $body = json_decode(wp_remote_retrieve_body($response), true);
52 $msg = isset($body['error_description']) ? $body['error_description'] : sprintf('HTTP %d', $code);
53 return new \WP_Error('token_error', $msg);
54 }
55
56 $body = json_decode(wp_remote_retrieve_body($response), true);
57 $access_token = isset($body['access_token']) ? $body['access_token'] : '';
58 if (empty($access_token)) {
59 return new \WP_Error('no_token', __('No access token in response.', 'superb-blocks'));
60 }
61
62 // Cache for 50 minutes (tokens last 60 min)
63 set_transient(self::TRANSIENT_KEY, $access_token, 50 * 60);
64
65 return $access_token;
66 }
67
68 /**
69 * Create a signed JWT for Google Service Account authentication.
70 *
71 * @param string $client_email Service account email.
72 * @param string $private_key PEM-encoded private key.
73 * @param string $scopes Space-separated scopes.
74 * @return string|\WP_Error The signed JWT or WP_Error on failure.
75 */
76 private static function CreateJWT($client_email, $private_key, $scopes)
77 {
78 $now = time();
79 $header = array('alg' => 'RS256', 'typ' => 'JWT');
80 $claims = array(
81 'iss' => $client_email,
82 'scope' => $scopes,
83 'aud' => self::TOKEN_URL,
84 'exp' => $now + 3600,
85 'iat' => $now,
86 );
87
88 $segments = array();
89 $segments[] = self::Base64UrlEncode(wp_json_encode($header));
90 $segments[] = self::Base64UrlEncode(wp_json_encode($claims));
91
92 $signing_input = implode('.', $segments);
93
94 if (!function_exists('openssl_sign')) {
95 return new \WP_Error('no_openssl', __('The OpenSSL PHP extension is required for Google Sheets.', 'superb-blocks'));
96 }
97
98 $signature = '';
99 $sign_result = openssl_sign($signing_input, $signature, $private_key, 'sha256WithRSAEncryption');
100 if (!$sign_result) {
101 return new \WP_Error('jwt_sign_failed', __('Failed to sign JWT. Check that the private key is valid.', 'superb-blocks'));
102 }
103
104 $segments[] = self::Base64UrlEncode($signature);
105
106 return implode('.', $segments);
107 }
108
109 /**
110 * Base64 URL-safe encode.
111 *
112 * @param string $data Raw data.
113 * @return string Base64url encoded string.
114 */
115 private static function Base64UrlEncode($data)
116 {
117 return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
118 }
119 }
120