-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'craft-4' of https://github.com/verbb/auth into craft-5
# Conflicts: # CHANGELOG.md # composer.json
- Loading branch information
Showing
8 changed files
with
369 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
<?php | ||
|
||
namespace verbb\auth\clients\xero\provider; | ||
|
||
use verbb\auth\clients\xero\provider\exception\XeroProviderException; | ||
use League\OAuth2\Client\Provider\AbstractProvider; | ||
use League\OAuth2\Client\Provider\ResourceOwnerInterface; | ||
use League\OAuth2\Client\Token\AccessToken; | ||
use League\OAuth2\Client\Token\AccessTokenInterface; | ||
use Psr\Http\Message\ResponseInterface; | ||
|
||
/** | ||
* @package Calcinai\OAuth2\Client\Provider | ||
*/ | ||
class Xero extends AbstractProvider | ||
{ | ||
const METHOD_DELETE = 'DELETE'; | ||
|
||
/** | ||
* Returns the base URL for authorizing a client. | ||
* | ||
* @return string | ||
*/ | ||
public function getBaseAuthorizationUrl() | ||
{ | ||
return 'https://login.xero.com/identity/connect/authorize'; | ||
} | ||
|
||
/** | ||
* Returns the base URL for requesting an access token. | ||
* | ||
* @param array $params | ||
* | ||
* @return string | ||
*/ | ||
public function getBaseAccessTokenUrl(array $params) | ||
{ | ||
return 'https://identity.xero.com/connect/token'; | ||
} | ||
|
||
/** | ||
* @param null|array $params | ||
* @return string | ||
*/ | ||
public function getTenantsUrl(?array $params = null) | ||
{ | ||
if ($params) { | ||
$params = '?' . http_build_query($params); | ||
} | ||
|
||
return 'https://api.xero.com/connections' . $params; | ||
} | ||
|
||
/** | ||
* @param AccessTokenInterface $token | ||
* @param null|array $params | ||
* @return XeroTenant[] | ||
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException | ||
* @throws \Exception | ||
*/ | ||
public function getTenants(AccessTokenInterface $token, ?array $params = null) | ||
{ | ||
$request = $this->getAuthenticatedRequest( | ||
self::METHOD_GET, | ||
$this->getTenantsUrl($params), | ||
$token | ||
); | ||
|
||
$response = $this->getParsedResponse($request); | ||
$tenants = []; | ||
|
||
foreach ($response as $tenantData) { | ||
$tenants[] = XeroTenant::fromArray($tenantData); | ||
} | ||
|
||
return $tenants; | ||
} | ||
|
||
/** | ||
* @param AccessTokenInterface $token | ||
* @param $connectionId | ||
* @return mixed | ||
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException | ||
*/ | ||
public function disconnect(AccessTokenInterface $token, $connectionId) | ||
{ | ||
$url = sprintf('%s/%s', $this->getTenantsUrl(), $connectionId); | ||
|
||
$request = $this->getAuthenticatedRequest(self::METHOD_DELETE, $url, $token); | ||
|
||
$response = $this->getParsedResponse($request); | ||
return $response; | ||
} | ||
|
||
|
||
/** | ||
* Returns the URL for requesting the resource owner's details. | ||
* | ||
* @param AccessToken $token | ||
* | ||
* @return string | ||
*/ | ||
public function getResourceOwnerDetailsUrl(AccessToken $token) | ||
{ | ||
//This does not exist as it comes down in the JWT | ||
return ''; | ||
} | ||
|
||
/** | ||
* @param AccessToken $token | ||
* @return XeroResourceOwner | ||
*/ | ||
public function getResourceOwner(AccessToken $token) | ||
{ | ||
return XeroResourceOwner::fromJWT($token->getValues()['id_token']); | ||
} | ||
|
||
|
||
/** | ||
* Checks a provider response for errors. | ||
* | ||
* @param ResponseInterface $response | ||
* @param array|string $data Parsed response data | ||
* | ||
* @throws \Calcinai\OAuth2\Client\Provider\Exception\XeroProviderException | ||
*/ | ||
protected function checkResponse(ResponseInterface $response, $data) | ||
{ | ||
if ($response->getStatusCode() >= 400) { | ||
throw new XeroProviderException( | ||
isset($data['error']) ? $data['error'] : $response->getReasonPhrase(), | ||
$response->getStatusCode(), | ||
$response | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
protected function getDefaultScopes() | ||
{ | ||
return ['openid email profile']; | ||
} | ||
|
||
/** | ||
* Returns the string that should be used to separate scopes when building | ||
* the URL for requesting an access token. | ||
* | ||
* @return string Scope separator, defaults to ' ' | ||
*/ | ||
protected function getScopeSeparator() | ||
{ | ||
return ' '; | ||
} | ||
|
||
/** | ||
* Generates a resource owner object from a successful resource owner | ||
* details request. | ||
* | ||
* @param array $response | ||
* @param AccessToken $token | ||
* @return void|ResourceOwnerInterface | ||
*/ | ||
protected function createResourceOwner(array $response, AccessToken $token) | ||
{ | ||
// This does nothing as we get the resource owner from the token itself, don't need to make a request to get it. | ||
} | ||
|
||
/** | ||
* @param mixed|null $token | ||
* @return array | ||
*/ | ||
protected function getAuthorizationHeaders($token = null) | ||
{ | ||
return [ | ||
'Authorization' => 'Bearer ' . $token->getToken() | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
namespace verbb\auth\clients\xero\provider; | ||
|
||
use League\OAuth2\Client\Provider\AbstractProvider; | ||
|
||
/** | ||
* @package Calcinai\OAuth2\Client\Provider | ||
*/ | ||
class XeroPkce extends Xero | ||
{ | ||
/** | ||
* Enable the PKCE flow | ||
* | ||
* @return string PKCE Method S256 | ||
*/ | ||
protected function getPkceMethod() | ||
{ | ||
return AbstractProvider::PKCE_METHOD_S256; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?php | ||
|
||
namespace verbb\auth\clients\xero\provider; | ||
|
||
use Firebase\JWT\JWT; | ||
|
||
class XeroResourceOwner | ||
{ | ||
/** | ||
* Xero user's UUID | ||
* | ||
* @var string | ||
*/ | ||
public $xero_userid; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $preferred_username; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $email; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $given_name; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $family_name; | ||
|
||
/** | ||
* @param $token | ||
* @return static | ||
*/ | ||
public static function fromJWT($token) | ||
{ | ||
list($header, $body, $crypto) = explode('.', $token); | ||
//This needs to be done manually as we don't get a signed JWT | ||
$decoded = JWT::jsonDecode(JWT::urlsafeB64Decode($body)); | ||
|
||
$self = new static(); | ||
|
||
$self->xero_userid = $decoded->xero_userid; | ||
$self->preferred_username = $decoded->preferred_username; | ||
$self->email = $decoded->email; | ||
$self->given_name = $decoded->given_name; | ||
$self->family_name = $decoded->family_name; | ||
|
||
return $self; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
namespace verbb\auth\clients\xero\provider; | ||
|
||
class XeroTenant | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
public $id; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $authEventId; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $tenantId; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $tenantType; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $tenantName; | ||
|
||
/** | ||
* @var \DateTime | ||
*/ | ||
public $createdDateUtc; | ||
|
||
/** | ||
* @var \DateTime | ||
*/ | ||
public $updatedDateUtc; | ||
|
||
/** | ||
* @param $data | ||
* @return XeroTenant | ||
* @throws \Exception | ||
*/ | ||
public static function fromArray($data) | ||
{ | ||
$self = new static(); | ||
|
||
$self->id = $data['id']; | ||
$self->authEventId = $data['authEventId']; | ||
$self->tenantId = $data['tenantId']; | ||
$self->tenantType = $data['tenantType']; | ||
$self->tenantName = $data['tenantName']; | ||
$self->createdDateUtc = new \DateTime($data['createdDateUtc']); | ||
$self->updatedDateUtc = isset($data['updatedDateUtc']) ? new \DateTime($data['updatedDateUtc']) : null; | ||
|
||
return $self; | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
src/clients/xero/provider/exception/XeroProviderException.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
namespace verbb\auth\clients\xero\provider\exception; | ||
|
||
use League\OAuth2\Client\Provider\Exception\IdentityProviderException; | ||
use Psr\Http\Message\ResponseInterface; | ||
|
||
class XeroProviderException extends IdentityProviderException | ||
{ | ||
/** | ||
* @param ResponseInterface $response | ||
* @param string|null $message | ||
* | ||
* @throws XeroProviderException | ||
*/ | ||
public static function fromResponse(ResponseInterface $response, $message = null) | ||
{ | ||
throw new static($message, $response->getStatusCode(), (string)$response->getBody()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
namespace verbb\auth\providers; | ||
|
||
use verbb\auth\base\ProviderTrait; | ||
use verbb\auth\clients\xero\provider\Xero as XeroProvider; | ||
|
||
class Xero extends XeroProvider | ||
{ | ||
// Traits | ||
// ========================================================================= | ||
|
||
use ProviderTrait; | ||
|
||
|
||
// Public Methods | ||
// ========================================================================= | ||
|
||
public function getBaseApiUrl(): ?string | ||
{ | ||
return 'https://api.xero.com/'; | ||
} | ||
} |