Skip to content

Commit

Permalink
Finished GNP Auth and SimSwap MVP implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
SecondeJK committed May 22, 2024
1 parent 438dfc0 commit 8b7f957
Show file tree
Hide file tree
Showing 45 changed files with 644 additions and 90 deletions.
6 changes: 6 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
<testsuite name="verify2">
<directory>test/Verify2</directory>
</testsuite>
<testsuite name="client">
<directory>test/Client</directory>
</testsuite>
<testsuite name="proactive_connect">
<directory>test/ProactiveConnect</directory>
</testsuite>
Expand All @@ -38,6 +41,9 @@
<testsuite name="sms">
<directory>test/SMS</directory>
</testsuite>
<testsuite name="simswap">
<directory>test/SimSwap</directory>
</testsuite>
<testsuite name="subaccount">
<directory>test/Subaccount</directory>
</testsuite>
Expand Down
2 changes: 1 addition & 1 deletion src/Account/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function __invoke(ContainerInterface $container): Client
->setBaseUrl($accountApi->getClient()->getRestUrl())
->setIsHAL(false)
->setBaseUri('/account')
->setAuthHandler(new BasicQueryHandler())
->setAuthHandlers(new BasicQueryHandler())
;

return new Client($accountApi);
Expand Down
2 changes: 1 addition & 1 deletion src/Application/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function __invoke(ContainerInterface $container): Client
$api
->setBaseUri('/v2/applications')
->setCollectionName('applications')
->setAuthHandler(new BasicHandler());
->setAuthHandlers(new BasicHandler());

return new Client($api, new Hydrator());
}
Expand Down
4 changes: 4 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
use Vonage\Numbers\ClientFactory as NumbersClientFactory;
use Vonage\Redact\ClientFactory as RedactClientFactory;
use Vonage\Secrets\ClientFactory as SecretsClientFactory;
use Vonage\SimSwap\ClientFactory as SimSwapClientFactory;
use Vonage\SMS\ClientFactory as SMSClientFactory;
use Vonage\Subaccount\ClientFactory as SubaccountClientFactory;
use Vonage\Messages\ClientFactory as MessagesClientFactory;
Expand Down Expand Up @@ -77,6 +78,7 @@
* @method Numbers\Client numbers()
* @method Redact\Client redact()
* @method Secrets\Client secrets()
* @method SimSwap\Client simswap()
* @method SMS\Client sms()
* @method Subaccount\Client subaccount()
* @method Users\Client users()
Expand Down Expand Up @@ -216,6 +218,7 @@ public function __construct(
'messages' => MessagesClientFactory::class,
'redact' => RedactClientFactory::class,
'secrets' => SecretsClientFactory::class,
'simswap' => SimSwapClientFactory::class,
'sms' => SMSClientFactory::class,
'subaccount' => SubaccountClientFactory::class,
'users' => UsersClientFactory::class,
Expand All @@ -225,6 +228,7 @@ public function __construct(

// Additional utility classes
APIResource::class => APIResource::class,
Client::class => function() { return $this; }
];

if (class_exists('Vonage\Video\ClientFactory')) {
Expand Down
29 changes: 15 additions & 14 deletions src/Client/APIResource.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

declare(strict_types=1);

namespace Vonage\Client;
Expand Down Expand Up @@ -28,7 +29,7 @@ class APIResource implements ClientAwareInterface
/**
* @var HandlerInterface[]
*/
protected array $authHandler = [];
protected array $authHandlers = [];

/**
* Base URL that we will hit. This can be overridden from the underlying
Expand Down Expand Up @@ -68,8 +69,8 @@ public function addAuth(RequestInterface $request): RequestInterface
{
$credentials = $this->getClient()->getCredentials();

if (is_array($this->getAuthHandler())) {
foreach ($this->getAuthHandler() as $handler) {
if (is_array($this->getAuthHandlers())) {
foreach ($this->getAuthHandlers() as $handler) {
try {
$request = $handler($request, $credentials);
break;
Expand All @@ -84,7 +85,7 @@ public function addAuth(RequestInterface $request): RequestInterface
return $request;
}

return $this->getAuthHandler()($request, $credentials);
return $this->getAuthHandlers()($request, $credentials);
}

/**
Expand All @@ -106,7 +107,7 @@ public function create(array $body, string $uri = '', array $headers = []): ?arr

$request->getBody()->write(json_encode($body));

if ($this->getAuthHandler()) {
if ($this->getAuthHandlers()) {
$request = $this->addAuth($request);
}

Expand Down Expand Up @@ -154,7 +155,7 @@ public function delete(string $id, array $headers = []): ?array
$headers
);

if ($this->getAuthHandler()) {
if ($this->getAuthHandlers()) {
$request = $this->addAuth($request);
}

Expand Down Expand Up @@ -207,7 +208,7 @@ public function get($id, array $query = [], array $headers = [], bool $jsonRespo
$headers
);

if ($this->getAuthHandler()) {
if ($this->getAuthHandlers()) {
$request = $this->addAuth($request);
}

Expand All @@ -231,10 +232,10 @@ public function get($id, array $query = [], array $headers = [], bool $jsonRespo
return json_decode($response->getBody()->getContents(), true);
}

public function getAuthHandler()
public function getAuthHandlers()
{
// If we have not set a handler, default to Basic and issue warning.
if (!$this->authHandler) {
if (!$this->authHandlers) {
$this->log(
LogLevel::WARNING,
'Warning: no authorisation handler set for this Client. Defaulting to Basic which might not be
Expand All @@ -244,7 +245,7 @@ public function getAuthHandler()
return new BasicHandler();
}

return $this->authHandler;
return $this->authHandlers;
}

public function getBaseUrl(): ?string
Expand Down Expand Up @@ -352,12 +353,12 @@ public function search(?FilterInterface $filter = null, string $uri = ''): Itera
*
* @return $this
*/
public function setAuthHandler($handler): self
public function setAuthHandlers($handler): self
{
if (!is_array($handler)) {
$handler = [$handler];
}
$this->authHandler = $handler;
$this->authHandlers = $handler;

return $this;
}
Expand Down Expand Up @@ -430,7 +431,7 @@ public function submit(array $formData = [], string $uri = '', array $headers =
$headers
);

if ($this->getAuthHandler()) {
if ($this->getAuthHandlers()) {
$request = $this->addAuth($request);
}

Expand Down Expand Up @@ -473,7 +474,7 @@ protected function updateEntity(string $method, string $id, array $body, array $
$headers
);

if ($this->getAuthHandler()) {
if ($this->getAuthHandlers()) {
$request = $this->addAuth($request);
}

Expand Down
25 changes: 25 additions & 0 deletions src/Client/Credentials/Gnp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Vonage\Client\Credentials;

class Gnp extends Keypair
{
public function __construct(protected string $msisdn, protected string $key, $application = null)
{
parent::__construct($key, $application);
}

public function getMsisdn(): string
{
return $this->msisdn;
}

public function setMsisdn(string $msisdn): Gnp
{
$this->msisdn = $msisdn;

return $this;
}
}
2 changes: 1 addition & 1 deletion src/Client/Credentials/Handler/AbstractHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

abstract class AbstractHandler implements HandlerInterface
{
abstract function __invoke(RequestInterface $request, CredentialsInterface $credentials): RequestInterface;
abstract public function __invoke(RequestInterface $request, CredentialsInterface $credentials): RequestInterface;

protected function extract(string $class, CredentialsInterface $credentials): CredentialsInterface
{
Expand Down
60 changes: 60 additions & 0 deletions src/Client/Credentials/Handler/GnpHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Vonage\Client\Credentials\Handler;

use Psr\Http\Message\RequestInterface;
use Vonage\Client;
use Vonage\Client\APIResource;
use Vonage\Client\Credentials\CredentialsInterface;
use Vonage\Client\Credentials\Gnp;

/**
* This handler is for Vonage GNP APIs that require the CAMARA standard OAuth Flow
*/
class GnpHandler extends AbstractHandler
{
use Client\ClientAwareTrait;
use Client\ScopeAwareTrait;

protected const VONAGE_GNP_AUTH_BACKEND_URL = 'https://api-eu.vonage.com/oauth2/bc-authorize';
protected const VONAGE_GNP_AUTH_TOKEN_URL = 'https://api-eu.vonage.com/oauth2/token';
protected const VONAGE_GNP_AUTH_TOKEN_GRANT_TYPE = 'urn:openid:params:grant-type:ciba';

public function __invoke(RequestInterface $request, CredentialsInterface $credentials): RequestInterface
{
/** @var Gnp $credentials */
$credentials = $this->extract(Gnp::class, $credentials);
$msisdn = $credentials->getMsisdn();

// Request OIDC, returns Auth Request ID
// Reconfigure new client for GNP Auth
$api = new APIResource();
$api->setAuthHandlers(new KeypairHandler());
$api->setClient($this->getClient());
$api->setBaseUrl(self::VONAGE_GNP_AUTH_BACKEND_URL);

// This handler requires an injected client configured with a Gnp credentials object and a configured scope
$response = $api->submit([
'login_hint' => $msisdn,
'scope' => $this->getScope()
]);

$decoded = json_decode($response, true, 512, JSON_THROW_ON_ERROR);

$authReqId = $decoded['auth_req_id'];

// CAMARA Access Token
$api->setBaseUrl(self::VONAGE_GNP_AUTH_TOKEN_URL);
$response = $api->submit([
'grant_type' => self::VONAGE_GNP_AUTH_TOKEN_GRANT_TYPE,
'auth_req_id' => $authReqId
]);

$decoded = json_decode($response, true, 512, JSON_THROW_ON_ERROR);

$token = $decoded['access_token'];

// Add CAMARA Access Token to request and return to make API call
return $request->withHeader('Authorization', 'Bearer ' . $token);
}
}
7 changes: 0 additions & 7 deletions src/Client/Credentials/Keypair.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,13 @@

namespace Vonage\Client\Credentials;

use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Encoding\JoseEncoder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use Lcobucci\JWT\Token;
use Vonage\Application\Application;
use Vonage\Client\Exception\Validation;
use Vonage\JWT\TokenGenerator;

use function base64_encode;
use function mt_rand;
use function time;

/**
* @property mixed application
*/
Expand Down
25 changes: 25 additions & 0 deletions src/Client/ScopeAwareTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Vonage\Client;

use RuntimeException;
use Vonage\Client;

trait ScopeAwareTrait
{
protected ?string $scope = null;

public function setScope(string $scope): self
{
$this->scope = $scope;

return $this;
}

public function getScope(): ?string
{
return $this->scope;
}
}
2 changes: 1 addition & 1 deletion src/Conversion/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function __invoke(ContainerInterface $container): Client
/** @var APIResource $api */
$api = $container->make(APIResource::class);
$api->setBaseUri('/conversions/');
$api->setAuthHandler(new BasicHandler());
$api->setAuthHandlers(new BasicHandler());

return new Client($api);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Entity/IterableAPICollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ protected function fetchPage($absoluteUri): void

$request = new Request($requestUri, 'GET');

if ($this->getApiResource()->getAuthHandler()) {
if ($this->getApiResource()->getAuthHandlers()) {
$request = $this->getApiResource()->addAuth($request);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Insights/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public function __invoke(ContainerInterface $container): Client
/** @var APIResource $api */
$api = $container->make(APIResource::class);
$api->setIsHAL(false);
$api->setAuthHandler(new BasicQueryHandler());
$api->setAuthHandlers(new BasicQueryHandler());

return new Client($api);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Meetings/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function __invoke(ContainerInterface $container): Client
$api
->setBaseUrl('https://api-eu.vonage.com/v1/meetings/')
->setExceptionErrorHandler(new ExceptionErrorHandler())
->setAuthHandler(new KeypairHandler());
->setAuthHandlers(new KeypairHandler());

return new Client($api);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Messages/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ public function getAPIResource(): APIResource

public function send(BaseMessage $message): ?array
{
return $this->api->create($message->toArray());
return $this->getAPIResource()->create($message->toArray());
}
}
2 changes: 1 addition & 1 deletion src/Messages/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function __invoke(ContainerInterface $container): Client
->setBaseUrl($api->getClient()->getApiUrl() . '/v1/messages')
->setIsHAL(false)
->setErrorsOn200(false)
->setAuthHandler([new KeypairHandler(), new BasicHandler()])
->setAuthHandlers([new KeypairHandler(), new BasicHandler()])
->setExceptionErrorHandler(new ExceptionErrorHandler());

return new Client($api);
Expand Down
2 changes: 1 addition & 1 deletion src/Numbers/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function __invoke(ContainerInterface $container): Client
$api
->setBaseUrl($api->getClient()->getRestUrl())
->setIsHAL(false)
->setAuthHandler(new BasicHandler());
->setAuthHandlers(new BasicHandler());

return new Client($api);
}
Expand Down
Loading

0 comments on commit 8b7f957

Please sign in to comment.