PluginProbe ʕ •ᴥ•ʔ
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More / 4.0.0
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More v4.0.0
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 2 months ago class-form-captcha-handler.php 2 months ago class-form-controller.php 2 months ago class-form-email-config-check.php 2 months ago class-form-email-handler.php 2 months ago class-form-encryption.php 2 months ago class-form-exporter.php 2 months ago class-form-field-validator.php 2 months ago class-form-file-handler.php 2 months ago class-form-google-auth.php 2 months ago class-form-integration-handler.php 2 months ago class-form-math-parser.php 2 months ago class-form-permissions.php 2 months ago class-form-registry.php 2 months ago class-form-settings.php 2 months ago class-form-submission-cpt.php 2 months ago class-form-submission-handler.php 2 months ago
class-form-google-auth.php
116 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 $signature = '';
95 $sign_result = openssl_sign($signing_input, $signature, $private_key, 'sha256WithRSAEncryption');
96 if (!$sign_result) {
97 return new \WP_Error('jwt_sign_failed', __('Failed to sign JWT. Check that the private key is valid.', 'superb-blocks'));
98 }
99
100 $segments[] = self::Base64UrlEncode($signature);
101
102 return implode('.', $segments);
103 }
104
105 /**
106 * Base64 URL-safe encode.
107 *
108 * @param string $data Raw data.
109 * @return string Base64url encoded string.
110 */
111 private static function Base64UrlEncode($data)
112 {
113 return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
114 }
115 }
116