This repository has been archived by the owner on Dec 5, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwp-google-service-account.php
188 lines (164 loc) · 4.94 KB
/
wp-google-service-account.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<?php
/**
* Library for accessing a Google Service Account on WordPress
*
* @package WP-API-Libraries\WP-Google-Service-Account
*/
/*
* Plugin Name: WP Google Service Account
* Plugin URI: https://wp-api-libraries.com/
* Description: Library that facilitates the authentication of service accounts on WordPress.
* Author: WP API Libraries
* Version: 1.0.0
* Author URI: https://wp-api-libraries.com
* GitHub Plugin URI: https://github.com/imforza
* GitHub Branch: master
*/
/* Exit if accessed directly */
if ( ! defined( 'ABSPATH' ) ) {
exit; }
if ( ! class_exists( 'WPGoogleServiceAccount' ) ) {
/**
* A WordPress API library for accessing a Google Service Account.
*
* @version 1.1.0
* @link https://developers.google.com/identity/protocols/OAuth2ServiceAccount Documentation
* @package WP-API-Libraries\WP-Google-Service-Account
* @author Santiago Garza <https://github.com/sfgarza>
* @author imFORZA <https://github.com/imforza>
*/
class WPGoogleServiceAccount {
/**
* Service Account key
*
* JSON decoded array of the service account credentials provided by google.
*
* @var string
*/
protected $service_account_key;
/**
* Auth Scope.
*
* @var string
*/
protected $scope;
/**
* The GCP Service token.
*
* @var array
*/
protected $gcp_service_token;
/**
* Authentication API Endpoint
*
* @var string
* @access protected
*/
protected $base_uri = 'https://www.googleapis.com/oauth2/v4/token';
/**
* Class constructor.
*
* @param string $api_key Auth token.
*/
public function __construct( array $service_account_key, $scope ) {
$this->service_account_key = $service_account_key;
$this->scope = $scope;
}
public function get_token() {
// Retrieve and return cached token or auth a new one.
if ( ( false === ( $this->gcp_service_token = get_transient( 'gcp_service_token' ) ) ) || $this->gcp_service_token['expiration'] < time() ) {
$this->gcp_service_token['access_token'] = $this->authenticate();
$this->gcp_service_token['expiration'] = $this->expiration;
set_transient( 'gcp_service_token', $this->gcp_service_token, HOUR_IN_SECONDS );
}
return $this->gcp_service_token['access_token'];
}
/**
* Build JWT assertion used for service account auth.
*
* @return string A Base64 URL encoded string used to auth account.
*/
protected function build_assertion() {
// {Base64url encoded JSON header}
$jwtHeader = $this->encode(
array(
'alg' => 'RS256',
'typ' => 'JWT',
),
true
);
// {Base64url encoded JSON claim set}
$now = time();
$this->expiration = $now + 3600;
$jwtClaim = $this->encode(
array(
'iss' => $this->service_account_key['client_email'],
'scope' => $this->scope,
'aud' => $this->base_uri,
'exp' => $this->expiration,
'iat' => $now,
),
true
);
// The base string for the signature: {Base64url encoded JSON header}.{Base64url encoded JSON claim set}
openssl_sign(
$jwtHeader . '.' . $jwtClaim,
$jwtSig,
$this->service_account_key['private_key'],
'sha256WithRSAEncryption'
);
$jwtSign = $this->encode( $jwtSig );
return $jwtHeader . '.' . $jwtClaim . '.' . $jwtSign;
}
/**
* Encode base64 URL encode data.
*
* @param array $data Data to be encoded.
* @param boolean $json_encode Whether to encode data to JSON as well.
* @return string Base64 url encoded string.
*/
protected function encode( $data, bool $json_encode = false ) {
$data = ( $json_encode ) ? json_encode( $data ) : $data;
return rtrim( strtr( base64_encode( $data ), '+/', '-_' ), '=' );
}
/**
* Fetch the request from the API.
*
* @access private
* @return array|WP_Error Request results or WP_Error on request failure.
*/
protected function authenticate() {
// Start building query.
$args = array(
'method' => 'POST',
'timeout' => 20,
'headers' => array(
'Content-Type' => 'application/x-www-form-urlencoded',
),
'body' => array(
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion' => $this->build_assertion(),
),
);
// Make the request.
$response = wp_remote_request( $this->base_uri, $args );
// Retrieve Status code & body.
$code = wp_remote_retrieve_response_code( $response );
$body = json_decode( wp_remote_retrieve_body( $response ) );
// Return WP_Error if request is not successful.
if ( ! $this->is_status_ok( $code ) ) {
return new WP_Error( 'response-error', sprintf( __( 'Status: %d', 'wp-google-service-account' ), $code ), $body );
}
return $body->access_token;
}
/**
* Check if HTTP status code is a success.
*
* @param int $code HTTP status code.
* @return boolean True if status is within valid range.
*/
protected function is_status_ok( $code ) {
return ( 200 <= $code && 300 > $code );
}
}
}