updated plugin WP Mail SMTP
version 2.5.0
This commit is contained in:
@ -119,7 +119,7 @@ class ApplicationDefaultCredentials
|
||||
* If supplied, $scope is used to in creating the credentials instance if
|
||||
* this does not fallback to the Compute Engine defaults.
|
||||
*
|
||||
* @param string|array scope the scope of the access request, expressed
|
||||
* @param string|array $scope the scope of the access request, expressed
|
||||
* either as an Array or as a space-delimited String.
|
||||
* @param callable $httpHandler callback which delivers psr7 request
|
||||
* @param array $cacheConfig configuration for the cache when it's present
|
||||
@ -127,14 +127,18 @@ class ApplicationDefaultCredentials
|
||||
* provided if you have one already available for use.
|
||||
* @param string $quotaProject specifies a project to bill for access
|
||||
* charges associated with the request.
|
||||
* @param string|array $defaultScope The default scope to use if no
|
||||
* user-defined scopes exist, expressed either as an Array or as a
|
||||
* space-delimited string.
|
||||
*
|
||||
* @return CredentialsLoader
|
||||
* @throws DomainException if no implementation can be obtained.
|
||||
*/
|
||||
public static function getCredentials($scope = null, callable $httpHandler = null, array $cacheConfig = null, \WPMailSMTP\Vendor\Psr\Cache\CacheItemPoolInterface $cache = null, $quotaProject = null)
|
||||
public static function getCredentials($scope = null, callable $httpHandler = null, array $cacheConfig = null, \WPMailSMTP\Vendor\Psr\Cache\CacheItemPoolInterface $cache = null, $quotaProject = null, $defaultScope = null)
|
||||
{
|
||||
$creds = null;
|
||||
$jsonKey = \WPMailSMTP\Vendor\Google\Auth\CredentialsLoader::fromEnv() ?: \WPMailSMTP\Vendor\Google\Auth\CredentialsLoader::fromWellKnownFile();
|
||||
$anyScope = $scope ?: $defaultScope;
|
||||
if (!$httpHandler) {
|
||||
if (!($client = \WPMailSMTP\Vendor\Google\Auth\HttpHandler\HttpClientCache::getHttpClient())) {
|
||||
$client = new \WPMailSMTP\Vendor\GuzzleHttp\Client();
|
||||
@ -146,11 +150,11 @@ class ApplicationDefaultCredentials
|
||||
if ($quotaProject) {
|
||||
$jsonKey['quota_project_id'] = $quotaProject;
|
||||
}
|
||||
$creds = \WPMailSMTP\Vendor\Google\Auth\CredentialsLoader::makeCredentials($scope, $jsonKey);
|
||||
$creds = \WPMailSMTP\Vendor\Google\Auth\CredentialsLoader::makeCredentials($scope, $jsonKey, $defaultScope);
|
||||
} elseif (\WPMailSMTP\Vendor\Google\Auth\Credentials\AppIdentityCredentials::onAppEngine() && !\WPMailSMTP\Vendor\Google\Auth\Credentials\GCECredentials::onAppEngineFlexible()) {
|
||||
$creds = new \WPMailSMTP\Vendor\Google\Auth\Credentials\AppIdentityCredentials($scope);
|
||||
$creds = new \WPMailSMTP\Vendor\Google\Auth\Credentials\AppIdentityCredentials($anyScope);
|
||||
} elseif (self::onGce($httpHandler, $cacheConfig, $cache)) {
|
||||
$creds = new \WPMailSMTP\Vendor\Google\Auth\Credentials\GCECredentials(null, $scope, null, $quotaProject);
|
||||
$creds = new \WPMailSMTP\Vendor\Google\Auth\Credentials\GCECredentials(null, $anyScope, null, $quotaProject);
|
||||
}
|
||||
if (\is_null($creds)) {
|
||||
throw new \DomainException(self::notFound());
|
||||
|
@ -138,6 +138,10 @@ class GCECredentials extends \WPMailSMTP\Vendor\Google\Auth\CredentialsLoader im
|
||||
* @var string|null
|
||||
*/
|
||||
private $quotaProject;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $serviceAccountIdentity;
|
||||
/**
|
||||
* @param Iam $iam [optional] An IAM instance.
|
||||
* @param string|array $scope [optional] the scope of the access request,
|
||||
@ -145,14 +149,16 @@ class GCECredentials extends \WPMailSMTP\Vendor\Google\Auth\CredentialsLoader im
|
||||
* @param string $targetAudience [optional] The audience for the ID token.
|
||||
* @param string $quotaProject [optional] Specifies a project to bill for access
|
||||
* charges associated with the request.
|
||||
* @param string $serviceAccountIdentity [optional] Specify a service
|
||||
* account identity name to use instead of "default".
|
||||
*/
|
||||
public function __construct(\WPMailSMTP\Vendor\Google\Auth\Iam $iam = null, $scope = null, $targetAudience = null, $quotaProject = null)
|
||||
public function __construct(\WPMailSMTP\Vendor\Google\Auth\Iam $iam = null, $scope = null, $targetAudience = null, $quotaProject = null, $serviceAccountIdentity = null)
|
||||
{
|
||||
$this->iam = $iam;
|
||||
if ($scope && $targetAudience) {
|
||||
throw new \InvalidArgumentException('Scope and targetAudience cannot both be supplied');
|
||||
}
|
||||
$tokenUri = self::getTokenUri();
|
||||
$tokenUri = self::getTokenUri($serviceAccountIdentity);
|
||||
if ($scope) {
|
||||
if (\is_string($scope)) {
|
||||
$scope = \explode(' ', $scope);
|
||||
@ -160,31 +166,61 @@ class GCECredentials extends \WPMailSMTP\Vendor\Google\Auth\CredentialsLoader im
|
||||
$scope = \implode(',', $scope);
|
||||
$tokenUri = $tokenUri . '?scopes=' . $scope;
|
||||
} elseif ($targetAudience) {
|
||||
$tokenUri = \sprintf('http://%s/computeMetadata/%s?audience=%s', self::METADATA_IP, self::ID_TOKEN_URI_PATH, $targetAudience);
|
||||
$tokenUri = self::getIdTokenUri($serviceAccountIdentity);
|
||||
$tokenUri = $tokenUri . '?audience=' . $targetAudience;
|
||||
$this->targetAudience = $targetAudience;
|
||||
}
|
||||
$this->tokenUri = $tokenUri;
|
||||
$this->quotaProject = $quotaProject;
|
||||
$this->serviceAccountIdentity = $serviceAccountIdentity;
|
||||
}
|
||||
/**
|
||||
* The full uri for accessing the default token.
|
||||
*
|
||||
* @param string $serviceAccountIdentity [optional] Specify a service
|
||||
* account identity name to use instead of "default".
|
||||
* @return string
|
||||
*/
|
||||
public static function getTokenUri()
|
||||
public static function getTokenUri($serviceAccountIdentity = null)
|
||||
{
|
||||
$base = 'http://' . self::METADATA_IP . '/computeMetadata/';
|
||||
return $base . self::TOKEN_URI_PATH;
|
||||
$base .= self::TOKEN_URI_PATH;
|
||||
if ($serviceAccountIdentity) {
|
||||
return \str_replace('/default/', '/' . $serviceAccountIdentity . '/', $base);
|
||||
}
|
||||
return $base;
|
||||
}
|
||||
/**
|
||||
* The full uri for accessing the default service account.
|
||||
*
|
||||
* @param string $serviceAccountIdentity [optional] Specify a service
|
||||
* account identity name to use instead of "default".
|
||||
* @return string
|
||||
*/
|
||||
public static function getClientNameUri()
|
||||
public static function getClientNameUri($serviceAccountIdentity = null)
|
||||
{
|
||||
$base = 'http://' . self::METADATA_IP . '/computeMetadata/';
|
||||
return $base . self::CLIENT_ID_URI_PATH;
|
||||
$base .= self::CLIENT_ID_URI_PATH;
|
||||
if ($serviceAccountIdentity) {
|
||||
return \str_replace('/default/', '/' . $serviceAccountIdentity . '/', $base);
|
||||
}
|
||||
return $base;
|
||||
}
|
||||
/**
|
||||
* The full uri for accesesing the default identity token.
|
||||
*
|
||||
* @param string $serviceAccountIdentity [optional] Specify a service
|
||||
* account identity name to use instead of "default".
|
||||
* @return string
|
||||
*/
|
||||
private static function getIdTokenUri($serviceAccountIdentity = null)
|
||||
{
|
||||
$base = 'http://' . self::METADATA_IP . '/computeMetadata/';
|
||||
$base .= self::ID_TOKEN_URI_PATH;
|
||||
if ($serviceAccountIdentity) {
|
||||
return \str_replace('/default/', '/' . $serviceAccountIdentity . '/', $base);
|
||||
}
|
||||
return $base;
|
||||
}
|
||||
/**
|
||||
* The full uri for accessing the default project ID.
|
||||
@ -275,9 +311,9 @@ class GCECredentials extends \WPMailSMTP\Vendor\Google\Auth\CredentialsLoader im
|
||||
if (null === ($json = \json_decode($response, \true))) {
|
||||
throw new \Exception('Invalid JSON response');
|
||||
}
|
||||
$json['expires_at'] = \time() + $json['expires_in'];
|
||||
// store this so we can retrieve it later
|
||||
$this->lastReceivedToken = $json;
|
||||
$this->lastReceivedToken['expires_at'] = \time() + $json['expires_in'];
|
||||
return $json;
|
||||
}
|
||||
/**
|
||||
@ -318,7 +354,7 @@ class GCECredentials extends \WPMailSMTP\Vendor\Google\Auth\CredentialsLoader im
|
||||
if (!$this->isOnGce) {
|
||||
return '';
|
||||
}
|
||||
$this->clientName = $this->getFromMetadata($httpHandler, self::getClientNameUri());
|
||||
$this->clientName = $this->getFromMetadata($httpHandler, self::getClientNameUri($this->serviceAccountIdentity));
|
||||
return $this->clientName;
|
||||
}
|
||||
/**
|
||||
|
@ -76,6 +76,10 @@ class ServiceAccountCredentials extends \WPMailSMTP\Vendor\Google\Auth\Credentia
|
||||
* @var string|null
|
||||
*/
|
||||
protected $projectId;
|
||||
/*
|
||||
* @var array|null
|
||||
*/
|
||||
private $lastReceivedJwtAccessToken;
|
||||
/**
|
||||
* Create a new ServiceAccountCredentials.
|
||||
*
|
||||
@ -146,7 +150,9 @@ class ServiceAccountCredentials extends \WPMailSMTP\Vendor\Google\Auth\Credentia
|
||||
*/
|
||||
public function getLastReceivedToken()
|
||||
{
|
||||
return $this->auth->getLastReceivedToken();
|
||||
// If self-signed JWTs are being used, fetch the last received token
|
||||
// from memory. Else, fetch it from OAuth2
|
||||
return $this->useSelfSignedJwt() ? $this->lastReceivedJwtAccessToken : $this->auth->getLastReceivedToken();
|
||||
}
|
||||
/**
|
||||
* Get the project ID from the service account keyfile.
|
||||
@ -171,14 +177,18 @@ class ServiceAccountCredentials extends \WPMailSMTP\Vendor\Google\Auth\Credentia
|
||||
public function updateMetadata($metadata, $authUri = null, callable $httpHandler = null)
|
||||
{
|
||||
// scope exists. use oauth implementation
|
||||
$scope = $this->auth->getScope();
|
||||
if (!\is_null($scope)) {
|
||||
if (!$this->useSelfSignedJwt()) {
|
||||
return parent::updateMetadata($metadata, $authUri, $httpHandler);
|
||||
}
|
||||
// no scope found. create jwt with the auth uri
|
||||
$credJson = array('private_key' => $this->auth->getSigningKey(), 'client_email' => $this->auth->getIssuer());
|
||||
$jwtCreds = new \WPMailSMTP\Vendor\Google\Auth\Credentials\ServiceAccountJwtAccessCredentials($credJson);
|
||||
return $jwtCreds->updateMetadata($metadata, $authUri, $httpHandler);
|
||||
$updatedMetadata = $jwtCreds->updateMetadata($metadata, $authUri, $httpHandler);
|
||||
if ($lastReceivedToken = $jwtCreds->getLastReceivedToken()) {
|
||||
// Keep self-signed JWTs in memory as the last received token
|
||||
$this->lastReceivedJwtAccessToken = $lastReceivedToken;
|
||||
}
|
||||
return $updatedMetadata;
|
||||
}
|
||||
/**
|
||||
* @param string $sub an email address account to impersonate, in situations when
|
||||
@ -209,4 +219,8 @@ class ServiceAccountCredentials extends \WPMailSMTP\Vendor\Google\Auth\Credentia
|
||||
{
|
||||
return $this->quotaProject;
|
||||
}
|
||||
private function useSelfSignedJwt()
|
||||
{
|
||||
return \is_null($this->auth->getScope());
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +106,8 @@ class ServiceAccountJwtAccessCredentials extends \WPMailSMTP\Vendor\Google\Auth\
|
||||
return null;
|
||||
}
|
||||
$access_token = $this->auth->toJwt();
|
||||
// Set the self-signed access token in OAuth2 for getLastReceivedToken
|
||||
$this->auth->setAccessToken($access_token);
|
||||
return array('access_token' => $access_token);
|
||||
}
|
||||
/**
|
||||
|
@ -119,18 +119,24 @@ abstract class CredentialsLoader implements \WPMailSMTP\Vendor\Google\Auth\Fetch
|
||||
* @param string|array $scope the scope of the access request, expressed
|
||||
* either as an Array or as a space-delimited String.
|
||||
* @param array $jsonKey the JSON credentials.
|
||||
* @param string|array $defaultScope The default scope to use if no
|
||||
* user-defined scopes exist, expressed either as an Array or as a
|
||||
* space-delimited string.
|
||||
*
|
||||
* @return ServiceAccountCredentials|UserRefreshCredentials
|
||||
*/
|
||||
public static function makeCredentials($scope, array $jsonKey)
|
||||
public static function makeCredentials($scope, array $jsonKey, $defaultScope = null)
|
||||
{
|
||||
if (!\array_key_exists('type', $jsonKey)) {
|
||||
throw new \InvalidArgumentException('json key is missing the type field');
|
||||
}
|
||||
if ($jsonKey['type'] == 'service_account') {
|
||||
// Do not pass $defaultScope to ServiceAccountCredentials
|
||||
return new \WPMailSMTP\Vendor\Google\Auth\Credentials\ServiceAccountCredentials($scope, $jsonKey);
|
||||
}
|
||||
if ($jsonKey['type'] == 'authorized_user') {
|
||||
return new \WPMailSMTP\Vendor\Google\Auth\Credentials\UserRefreshCredentials($scope, $jsonKey);
|
||||
$anyScope = $scope ?: $defaultScope;
|
||||
return new \WPMailSMTP\Vendor\Google\Auth\Credentials\UserRefreshCredentials($anyScope, $jsonKey);
|
||||
}
|
||||
throw new \InvalidArgumentException('invalid value in the type field');
|
||||
}
|
||||
@ -188,7 +194,7 @@ abstract class CredentialsLoader implements \WPMailSMTP\Vendor\Google\Auth\Fetch
|
||||
{
|
||||
if (isset($metadata[self::AUTH_METADATA_KEY])) {
|
||||
// Auth metadata has already been set
|
||||
return $metdadata;
|
||||
return $metadata;
|
||||
}
|
||||
$result = $this->fetchAuthToken($httpHandler);
|
||||
if (!isset($result['access_token'])) {
|
||||
|
@ -60,29 +60,11 @@ class FetchAuthTokenCache implements \WPMailSMTP\Vendor\Google\Auth\FetchAuthTok
|
||||
*/
|
||||
public function fetchAuthToken(callable $httpHandler = null)
|
||||
{
|
||||
// Use the cached value if its available.
|
||||
//
|
||||
// TODO: correct caching; update the call to setCachedValue to set the expiry
|
||||
// to the value returned with the auth token.
|
||||
//
|
||||
// TODO: correct caching; enable the cache to be cleared.
|
||||
$cacheKey = $this->fetcher->getCacheKey();
|
||||
$cached = $this->getCachedValue($cacheKey);
|
||||
if (\is_array($cached)) {
|
||||
if (empty($cached['expires_at'])) {
|
||||
// If there is no expiration data, assume token is not expired.
|
||||
// (for JwtAccess and ID tokens)
|
||||
return $cached;
|
||||
}
|
||||
if (\time() < $cached['expires_at']) {
|
||||
// access token is not expired
|
||||
return $cached;
|
||||
}
|
||||
if ($cached = $this->fetchAuthTokenFromCache()) {
|
||||
return $cached;
|
||||
}
|
||||
$auth_token = $this->fetcher->fetchAuthToken($httpHandler);
|
||||
if (isset($auth_token['access_token']) || isset($auth_token['id_token'])) {
|
||||
$this->setCachedValue($cacheKey, $auth_token);
|
||||
}
|
||||
$this->saveAuthTokenInCache($auth_token);
|
||||
return $auth_token;
|
||||
}
|
||||
/**
|
||||
@ -169,12 +151,51 @@ class FetchAuthTokenCache implements \WPMailSMTP\Vendor\Google\Auth\FetchAuthTok
|
||||
if (!$this->fetcher instanceof \WPMailSMTP\Vendor\Google\Auth\UpdateMetadataInterface) {
|
||||
throw new \RuntimeException('Credentials fetcher does not implement ' . 'Google\\Auth\\UpdateMetadataInterface');
|
||||
}
|
||||
// Set the `Authentication` header from the cache, so it is not set
|
||||
// again by the fetcher
|
||||
$result = $this->fetchAuthToken($httpHandler);
|
||||
if (isset($result['access_token'])) {
|
||||
$metadata[self::AUTH_METADATA_KEY] = ['Bearer ' . $result['access_token']];
|
||||
$cached = $this->fetchAuthTokenFromCache($authUri);
|
||||
if ($cached) {
|
||||
// Set the access token in the `Authorization` metadata header so
|
||||
// the downstream call to updateMetadata know they don't need to
|
||||
// fetch another token.
|
||||
if (isset($cached['access_token'])) {
|
||||
$metadata[self::AUTH_METADATA_KEY] = ['Bearer ' . $cached['access_token']];
|
||||
}
|
||||
}
|
||||
$newMetadata = $this->fetcher->updateMetadata($metadata, $authUri, $httpHandler);
|
||||
if (!$cached && ($token = $this->fetcher->getLastReceivedToken())) {
|
||||
$this->saveAuthTokenInCache($token, $authUri);
|
||||
}
|
||||
return $newMetadata;
|
||||
}
|
||||
private function fetchAuthTokenFromCache($authUri = null)
|
||||
{
|
||||
// Use the cached value if its available.
|
||||
//
|
||||
// TODO: correct caching; update the call to setCachedValue to set the expiry
|
||||
// to the value returned with the auth token.
|
||||
//
|
||||
// TODO: correct caching; enable the cache to be cleared.
|
||||
// if $authUri is set, use it as the cache key
|
||||
$cacheKey = $authUri ? $this->getFullCacheKey($authUri) : $this->fetcher->getCacheKey();
|
||||
$cached = $this->getCachedValue($cacheKey);
|
||||
if (\is_array($cached)) {
|
||||
if (empty($cached['expires_at'])) {
|
||||
// If there is no expiration data, assume token is not expired.
|
||||
// (for JwtAccess and ID tokens)
|
||||
return $cached;
|
||||
}
|
||||
if (\time() < $cached['expires_at']) {
|
||||
// access token is not expired
|
||||
return $cached;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private function saveAuthTokenInCache($authToken, $authUri = null)
|
||||
{
|
||||
if (isset($authToken['access_token']) || isset($authToken['id_token'])) {
|
||||
// if $authUri is set, use it as the cache key
|
||||
$cacheKey = $authUri ? $this->getFullCacheKey($authUri) : $this->fetcher->getCacheKey();
|
||||
$this->setCachedValue($cacheKey, $authToken);
|
||||
}
|
||||
return $this->fetcher->updateMetadata($metadata, $authUri, $httpHandler);
|
||||
}
|
||||
}
|
||||
|
@ -1096,14 +1096,28 @@ class OAuth2 implements \WPMailSMTP\Vendor\Google\Auth\FetchAuthTokenInterface
|
||||
/**
|
||||
* The expiration of the last received token.
|
||||
*
|
||||
* @return array
|
||||
* @return array|null
|
||||
*/
|
||||
public function getLastReceivedToken()
|
||||
{
|
||||
if ($token = $this->getAccessToken()) {
|
||||
return ['access_token' => $token, 'expires_at' => $this->getExpiresAt()];
|
||||
// the bare necessity of an auth token
|
||||
$authToken = ['access_token' => $token, 'expires_at' => $this->getExpiresAt()];
|
||||
} elseif ($idToken = $this->getIdToken()) {
|
||||
$authToken = ['id_token' => $idToken, 'expires_at' => $this->getExpiresAt()];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
if ($expiresIn = $this->getExpiresIn()) {
|
||||
$authToken['expires_in'] = $expiresIn;
|
||||
}
|
||||
if ($issuedAt = $this->getIssuedAt()) {
|
||||
$authToken['issued_at'] = $issuedAt;
|
||||
}
|
||||
if ($refreshToken = $this->getRefreshToken()) {
|
||||
$authToken['refresh_token'] = $refreshToken;
|
||||
}
|
||||
return $authToken;
|
||||
}
|
||||
/**
|
||||
* Get the client ID.
|
||||
|
Reference in New Issue
Block a user