Files
w4rpservices/vendor/eveseat/eseye/tests/Fetchers/GuzzleFetcherTest.php

386 lines
12 KiB
PHP

<?php
/*
* This file is part of SeAT
*
* Copyright (C) 2015, 2016, 2017 Leon Jacobs
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use Jose\Component\Core\JWK;
use Jose\Easy\Build;
use Seat\Eseye\Configuration;
use Seat\Eseye\Containers\EsiAuthentication;
use Seat\Eseye\Containers\EsiResponse;
use Seat\Eseye\Exceptions\InvalidAuthenticationException;
use Seat\Eseye\Exceptions\RequestFailedException;
use Seat\Eseye\Fetchers\GuzzleFetcher;
use Seat\Eseye\Log\NullLogger;
class GuzzleFetcherTest extends PHPUnit_Framework_TestCase
{
/**
* @var GuzzleFetcher
*/
protected $fetcher;
public function setUp()
{
// Remove logging
$configuration = Configuration::getInstance();
$configuration->logger = NullLogger::class;
$this->fetcher = new GuzzleFetcher;
}
public function testGuzzleFetcherInstantiation()
{
$this->assertInstanceOf(GuzzleFetcher::class, $this->fetcher);
}
public function testGuzzleGetsClientIfNoneSet()
{
$fetcher = new GuzzleFetcher;
$client = $fetcher->getClient();
$this->assertInstanceOf(Client::class, $client);
}
public function testGuzzleFetcherStripRefreshTokenFromUrl()
{
$url = 'https://esi.url/oauth?type=refresh_token&refresh_token=foo';
$stripped = $this->fetcher->stripRefreshTokenValue($url);
$this->assertEquals('https://esi.url/oauth?type=refresh_token', $stripped);
}
public function testGuzzleFetcherStripRefreshTokenFromUrlWithoutRefreshToken()
{
$url = 'https://esi.url/type=refresh_token';
$stripped = $this->fetcher->stripRefreshTokenValue($url);
$this->assertEquals('https://esi.url/type=refresh_token', $stripped);
}
public function testGuzzleFetcherStripRefreshTokenNoTokenMention()
{
$url = 'https://esi.url/foo=bar';
$stripped = $this->fetcher->stripRefreshTokenValue($url);
$this->assertEquals($url, $stripped);
}
public function testGuzzleFetcherMakeEsiResponseContainer()
{
$response = json_encode(['response' => 'ok']);
$container = $this->fetcher->makeEsiResponse($response, [], 'now', 200);
$this->assertInstanceOf(EsiResponse::class, $container);
}
public function testGuzzleFetcherGetAuthenticationWhenNoneSet()
{
$authentication = $this->fetcher->getAuthentication();
$this->assertNull($authentication);
}
public function testGuzzleFetcherGetAuthenticationWhenSettingAuthentication()
{
$fetcher = new GuzzleFetcher(new EsiAuthentication([
'client_id' => 'foo',
]));
$this->assertInstanceOf(EsiAuthentication::class, $fetcher->getAuthentication());
}
public function testGuzzleSetsAuthentication()
{
$this->fetcher->setAuthentication(new EsiAuthentication([
'client_id' => 'foo',
'secret' => 'bar',
'access_token' => '_',
'refresh_token' => 'baz',
'token_expires' => '1970-01-01 00:00:00',
'scopes' => ['public'],
]));
$this->assertInstanceOf(EsiAuthentication::class, $this->fetcher->getAuthentication());
}
public function testGuzzleFailsSettingInvalidAuthentication()
{
$this->expectException(InvalidAuthenticationException::class);
$this->fetcher->setAuthentication(new EsiAuthentication([
'client_id' => null,
]));
}
public function testGuzzleShouldFailGettingTokenWithoutAuthentication()
{
$this->expectException(InvalidAuthenticationException::class);
$get_token = self::getMethod('getToken');
$get_token->invokeArgs(new GuzzleFetcher, []);
}
/**
* Helper method to set private methods public.
*
* @param $name
*
* @return \ReflectionMethod
*/
protected static function getMethod($name)
{
$class = new ReflectionClass('Seat\Eseye\Fetchers\GuzzleFetcher');
$method = $class->getMethod($name);
$method->setAccessible(true);
return $method;
}
public function testGuzzleFetcherGetPublicScopeWithoutAuthentication()
{
$scopes = $this->fetcher->getAuthenticationScopes();
$this->assertEquals(1, count($scopes));
}
public function testGuzzleCallingWithoutAuthentication()
{
$mock = new MockHandler([
new Response(200, ['X-Foo' => 'Bar'], json_encode(['foo' => 'var'])),
]);
// Update the fetchers client
$this->fetcher->setClient(new Client([
'handler' => HandlerStack::create($mock),
]));
$response = $this->fetcher->call('get', '/foo', ['foo' => 'bar']);
$this->assertInstanceOf(EsiResponse::class, $response);
}
public function testGuzzleCallingWithAuthentication()
{
// init a JWK set
$jwk = $this->getJwkSet();
// generate a JWS Token mocking standard CCP format
$jws = $this->getJwsToken($jwk);
$mock = new MockHandler([
// RefreshToken response
new Response(200, ['X-Foo' => 'Bar'], json_encode([
'access_token' => $jws,
'expires_in' => 1200,
'token_type' => 'Bearer',
'refresh_token' => 'bar',
])),
// JWKS endpoint response
new Response(200, [], json_encode([
'jwks_uri' => 'https://login.eveonline.com/oauth/jwks',
])),
// JWK Sets response
new Response(200, [], json_encode([
'keys' => [
$jwk->jsonSerialize(),
],
'SkipUnresolvedJsonWebKeys' => true,
])),
// ESI response
new Response(200, ['X-Foo' => 'Bar'], json_encode(['foo' => 'var'])),
]);
// Update the fetchers client
$this->fetcher->setClient(new Client([
'handler' => HandlerStack::create($mock),
]));
// Update the fetchers authentication
$this->fetcher->setAuthentication(new EsiAuthentication([
'client_id' => 'foo',
'secret' => 'bar',
'access_token' => '_',
'refresh_token' => 'baz',
'token_expires' => '1970-01-01 00:00:00',
'scopes' => ['public'],
]));
$response = $this->fetcher->call('get', '/foo', ['foo' => 'bar']);
$this->assertInstanceOf(EsiResponse::class, $response);
}
public function testGuzzleCallingCatchesRequestAuthenticationFailure()
{
$this->expectException(RequestFailedException::class);
$mock = new MockHandler([
new Response(401),
]);
// Update the fetchers client
$this->fetcher->setClient(new Client([
'handler' => HandlerStack::create($mock),
]));
$this->fetcher->call('get', '/foo', ['foo' => 'bar']);
}
public function testGuzzleFetcherMakesHttpRequest()
{
$mock = new MockHandler([
new Response(200, ['X-Foo' => 'Bar'], json_encode(['foo' => 'var'])),
]);
// Update the fetchers client
$this->fetcher->setClient(new Client([
'handler' => HandlerStack::create($mock),
]));
$response = $this->fetcher->httpRequest('get', '/foo');
$this->assertInstanceOf(EsiResponse::class, $response);
}
public function testGuzzleConstructsWithClientAndGetsAuthenticationScopes()
{
// init a JWK Set
$jwk = $this->getJwkSet();
// init a JWS Token
$jws = $this->getJwsToken($jwk);
$mock = new MockHandler([
// JWK Endpoint
new Response(200, [], json_encode([
'jwks_uri' => 'https://login.eveonline.com/oauth/jwks',
])),
// JWK Sets response
new Response(200, [], json_encode([
'keys' => [
$jwk->jsonSerialize(),
],
'SkipUnresolvedJsonWebKeys' => true,
])),
]);
// Update the fetchers client
$client = new Client([
'handler' => HandlerStack::create($mock),
]);
// Update the fetchers authentication
$authentication = new EsiAuthentication([
'client_id' => 'foo',
'secret' => 'bar',
'access_token' => $jws,
'refresh_token' => 'baz',
'token_expires' => '1970-01-01 00:00:00',
]);
$fetcher = new GuzzleFetcher($authentication);
$fetcher->setClient($client);
$scopes = $fetcher->getAuthenticationScopes();
$this->assertEquals(['foo', 'bar', 'baz', 'public'], $scopes);
}
/**
* @return \Jose\Component\Core\JWK
*/
private function getJwkSet()
{
return new JWK([
"p" => "1UQV33bi2J-WJ9529sOTuXiAGCh_lcUAgRHayLbBSElC9O_kA8g2ipC0Qu58tpKdKjq2dD7_SfbESqEI0AJD7oMfP1i-Ispn31vjIb7fmnlddF2qflc9SEkWkrZPCntusTzIraxBDUwIlmdOdAI24xHHpGe-DISE4R1LYrQS0m0",
"kty" => "RSA",
"q" => "yaEesJOxfHkeYvlo8f1NVCrCyxfzDl3_-_qDm-bpdUDjemsvolYD6AEb0GGiyjFdMJg29iCke_8nzYIuwDf2QzFS96aU0IpxLwyNsXBdOr7K53WmDj7LU4xFfR-gaOQEp-o2KZ7-1EqpPRgeI12wVpfR3Mi4TZuXlgmeyYpt_BU",
"d" => "iZo3pjr-cegcZN2lk3I3qL8By-8bSO4DaZdih6BnHB-VJbhhmSky64wP34wpKe_G486C1o9IsVZ6zuhXrOJdEOIike3d0IKg6jNY24RsV-AX5hYn44Us8ePHQnhqtxf42GujloroctLkAJAlpnYg6-rWW7kAoCjrNxVIaJ4AOabIcpIQwNwqHNjWifik6WttpC_-u-4HmTLG6f-NrVqrSJkBTReRCjsSYz1GH_snBGx2SFS5XbEfvWe0g-Asu8kZPzYL7y5ahMZ3AT4qOjNA-UFkIzYW0BQjwMwTzRq_30bTDZXBLH8YbDCD6HwBhVThmX4k6AjWr4yG7-uJfvTAgQ",
"e" => "AQAB",
"use" => "sig",
"kid" => "JWK Signature Mock",
"qi" => "baoXJXUnqalu6CMibn1aILUhfDbjW_lVVk-b9ZAK7ZVi8vEKDpvFWTeB-R-kZMaQcYZKSOZshfXSOd8p_hpCY7nL5XuQPndR2jg23vnsddppT8dwOsiOPX1gQufwrtTQX9oibcDX1P5z942esrbHW5ttEkgM4i8Xo5G7tkKed8k",
"dp" => "d2kK8jdn5rDca3Blnd9-HFA7MMukPGC02o_7t3yUlnvm0KxtOCznVQiW1g8gpz1KYLXFKSuI14oi-EJYY9eQ38BtQ5PVyjcYl_ikIWX1X1HrINe9OcZxGsNJr1YCxbS9EuIc3xlexyo2eLhZNh1zTArNhOFNiUa9_Cnh5t861rU",
"alg" => "RS256",
"dq" => "rUXJGfXSkSWE94leppcH3UziGaZ7Od2OHv0qHNBT0G_zDUEPrnI86SQKwwkk3J2PeDNXCC0FLYoYqoM1qfptp1C7_BcrzAstOUGQguwNMm7D8CUqjxNnqGTjUqPbNki9t4-O_DWmyMlgpyASxlG9OK0_rHzR5d_QZR_fVVOhMQ",
"n" => "p_iuj0pLDqQsdtXl6cJ8Gqhtm8F5dUSbmNPYoNbB_uM0oQrBBxvKPH7GzDduFMtS6LfloH3hGryTum-lxU1yQ4PjaN3IEdrGpqS6_OWtqZ6mRWrDDNdgWmkFtq5kPwfR2EXdcygWREJ7w1376WWx9l3tVu6zygfCghTTUhVT65fjmnNUR6zWJn15pxTjnQ-zphKlgvWnCDwJEW9UFXK025ztMQFn8rkTxJV9O3Qu3QS-VRjVicPhV7oOMs2YhiqUAmnzu285nKTaG6N_83NIZ5W2N06JfMt6epvTiC-st2joQp4FCsiVPEEQ6wjZJTA7cpdmIoc05X7gMKdipxeO8Q"
]);
}
/**
* @param \Jose\Component\Core\JWK $jwk
* @return string
*/
private function getJwsToken(JWK $jwk): string
{
$time = time();
return Build::jws()
->exp($time + 1200)
->alg('RS256')
->payload([
'scp' => [
"foo",
"bar",
"baz",
"public",
],
"jti" => "7f64ea9f-ee6e-4c4a-9486-d668e8c79f25",
"kid" => "JWT-Signature-Key",
"sub" => "CHARACTER:EVE:90795931",
"azp" => "foo",
"name" => "Warlof Tutsimo",
"owner" => "svnSjVa1uGYyp/ZL3mfkIwkJYzQ=",
"exp" => $time + 3600,
"iss" => "login.eveonline.com",
])
->header('typ', 'JWT')
->header('kid', 'JWT-Signature-Key')
->sign($jwk);
}
}