Skip to content

Commit

Permalink
Added cache error handling (#11)
Browse files Browse the repository at this point in the history
* Added better cache error handling
* Support symfomy/cache 4.4 and 5.x
  • Loading branch information
alancting authored Apr 11, 2021
1 parent c4047a6 commit 23fe443
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 143 deletions.
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"ad",
"microsoft"
],
"version": "1.2.0",
"version": "1.2.1",
"authors": [
{
"name": "Neuman Vong",
Expand All @@ -28,8 +28,8 @@
],
"license": "BSD-3-Clause",
"require": {
"php": ">=7.0",
"symfony/cache": "^4.4"
"php": ">=7.1.3",
"symfony/cache": "^4.4 || ^5.0"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.3",
Expand Down
30 changes: 15 additions & 15 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>

<phpunit xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="PHP JSON Web Token Test Suite">
<directory>./tests</directory>
<exclude>./tests/JWKTest.php</exclude>
<exclude>./tests/JWTTest.php</exclude>
</testsuite>
</testsuites>
<testsuites>
<testsuite name="PHP JSON Web Token Test Suite">
<directory>./tests</directory>
<exclude>./tests/JWKTest.php</exclude>
<exclude>./tests/JWTTest.php</exclude>
</testsuite>
</testsuites>

<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory>./src</directory>
</whitelist>
</filter>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory>./src</directory>
</whitelist>
</filter>

<logging>
<log type="coverage-clover" target="build/logs/clover.xml" />
</logging>
<logging>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
</phpunit>
52 changes: 38 additions & 14 deletions src/Base/MicrosoftConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,23 +195,18 @@ private function _load()
$cache_item_configs = $this->cache->getItem(self::CACHE_KEY_CONFIGS);
if (!$cache_item_configs->isHit()) {
$cache_item_configs = $this->setCacheFromUrlOrFile(self::CACHE_KEY_CONFIGS, $this->config_uri);
} else {
try {
$this->parseOpenIdConfigsFromJson($cache_item_configs->get());
} catch (\Exception $e) {
$cache_item_configs = $this->setCacheFromUrlOrFile(self::CACHE_KEY_CONFIGS, $this->config_uri);
}
}
$json = $cache_item_configs->get();
$this->parseOpenIdConfigsFromJson($cache_item_configs->get());
} else {
$json = $this->getFromUrlOrFile($this->config_uri);
$configs_json = $this->getFromUrlOrFile($this->config_uri);
$this->parseOpenIdConfigsFromJson($configs_json);
}
$data = json_decode($json, true);

$this->authorization_endpoint = $data['authorization_endpoint'];
$this->token_endpoint = $data['token_endpoint'];
$this->userinfo_endpoint = $data['userinfo_endpoint'];
$this->device_authorization_endpoint = $data['device_authorization_endpoint'];
$this->end_session_endpoint = $data['end_session_endpoint'];
$this->jwks_uri = $data['jwks_uri'];
$this->issuer = $data['issuer'];
$this->access_token_issuer = (isset($data['access_token_issuer'])) ? $data['access_token_issuer'] : $this->issuer;
$this->id_token_signing_alg_values_supported = isset($data['id_token_signing_alg_values_supported']) ? $data['id_token_signing_alg_values_supported'] : $this->getDefaultSigningAlgValues();
$this->token_endpoint_auth_signing_alg_values_supported = isset($data['token_endpoint_auth_signing_alg_values_supported']) ? $data['token_endpoint_auth_signing_alg_values_supported'] : $this->getDefaultSigningAlgValues();

if ($this->cache !== false) {
$cache_item_jwks = $this->cache->getItem(self::CACHE_KEY_JWKS);
Expand All @@ -236,6 +231,35 @@ private function _load()
}
}

private function parseOpenIdConfigsFromJson($config_json)
{

try {
$data = json_decode($config_json, true);
if (!array_key_exists('authorization_endpoint', $data) ||
!array_key_exists('token_endpoint', $data) ||
!array_key_exists('userinfo_endpoint', $data) ||
!array_key_exists('device_authorization_endpoint', $data) ||
!array_key_exists('end_session_endpoint', $data) ||
!array_key_exists('jwks_uri', $data) ||
!array_key_exists('issuer', $data)) {
throw new \Exception('Invalid configuration');
}
$this->authorization_endpoint = $data['authorization_endpoint'];
$this->token_endpoint = $data['token_endpoint'];
$this->userinfo_endpoint = $data['userinfo_endpoint'];
$this->device_authorization_endpoint = $data['device_authorization_endpoint'];
$this->end_session_endpoint = $data['end_session_endpoint'];
$this->jwks_uri = $data['jwks_uri'];
$this->issuer = $data['issuer'];
$this->access_token_issuer = (isset($data['access_token_issuer'])) ? $data['access_token_issuer'] : $this->issuer;
$this->id_token_signing_alg_values_supported = isset($data['id_token_signing_alg_values_supported']) ? $data['id_token_signing_alg_values_supported'] : $this->getDefaultSigningAlgValues();
$this->token_endpoint_auth_signing_alg_values_supported = isset($data['token_endpoint_auth_signing_alg_values_supported']) ? $data['token_endpoint_auth_signing_alg_values_supported'] : $this->getDefaultSigningAlgValues();
} catch (\Exception $e) {
throw new \Exception('Invalid configuration');
}
}

private function getFromUrlOrFile($uri)
{
$targetUri = $uri;
Expand Down
131 changes: 76 additions & 55 deletions tests/Adfs/AdfsConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,7 @@ public function testConstructorWithFileCacheNotExists()
'path' => 'any_file_path'
];

$this->mockCacheConfig(
'FilesystemAdapter',
false,
false);

$this->mockCacheConfig('FilesystemAdapter', false);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}
Expand All @@ -202,16 +198,12 @@ public function testConstructorWithFileCacheExists()
'path' => 'any_file_path'
];

$this->mockCacheConfig(
'FilesystemAdapter',
true,
false);

$this->mockCacheConfig('FilesystemAdapter', true);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}

public function testConstructorWithFileCacheExistsWithError()
public function testConstructorWithFileCacheExistsWithConfigError()
{
\DG\BypassFinals::enable();

Expand All @@ -220,11 +212,21 @@ public function testConstructorWithFileCacheExistsWithError()
'path' => 'any_file_path'
];

$this->mockCacheConfig(
'FilesystemAdapter',
true,
true);
$this->mockCacheConfig('FilesystemAdapter', true, true, false);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}

public function testConstructorWithFileCacheExistsWithJwkError()
{
\DG\BypassFinals::enable();

($this->default_configs)['cache'] = [
'type' => 'file',
'path' => 'any_file_path'
];

$this->mockCacheConfig('FilesystemAdapter', true, false, true);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}
Expand All @@ -238,11 +240,7 @@ public function testConstructorWithRedisCacheNotExists()
'client' => $this->createStub(\Redis::class)
];

$this->mockCacheConfig(
'RedisAdapter',
false,
false);

$this->mockCacheConfig('RedisAdapter', false);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}
Expand All @@ -256,16 +254,12 @@ public function testConstructorWithRedisCacheExists()
'client' => $this->createStub(\Redis::class)
];

$this->mockCacheConfig(
'RedisAdapter',
true,
false);

$this->mockCacheConfig('RedisAdapter', true);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}

public function testConstructorWithRedisCacheExistsWithError()
public function testConstructorWithRedisCacheExistsWithConfigsError()
{
\DG\BypassFinals::enable();

Expand All @@ -274,11 +268,21 @@ public function testConstructorWithRedisCacheExistsWithError()
'client' => $this->createStub(\Redis::class)
];

$this->mockCacheConfig(
'RedisAdapter',
true,
true);
$this->mockCacheConfig('RedisAdapter', true, true, false);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}

public function testConstructorWithRedisCacheExistsWithJwkError()
{
\DG\BypassFinals::enable();

($this->default_configs)['cache'] = [
'type' => 'redis',
'client' => $this->createStub(\Redis::class)
];

$this->mockCacheConfig('RedisAdapter', true, false, true);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}
Expand All @@ -292,11 +296,7 @@ public function testConstructorWithMemcachedCacheNotExists()
'client' => $this->createStub(\Memcached::class)
];

$this->mockCacheConfig(
'MemcachedAdapter',
false,
false);

$this->mockCacheConfig('MemcachedAdapter', false);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}
Expand All @@ -310,16 +310,12 @@ public function testConstructorWithMemcachedCacheExists()
'client' => $this->createStub(\Memcached::class)
];

$this->mockCacheConfig(
'MemcachedAdapter',
true,
false);

$this->mockCacheConfig('MemcachedAdapter', true);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}

public function testConstructorWithMemcachedCacheExistsWithError()
public function testConstructorWithMemcachedCacheExistsWithConfigError()
{
\DG\BypassFinals::enable();

Expand All @@ -328,11 +324,21 @@ public function testConstructorWithMemcachedCacheExistsWithError()
'client' => $this->createStub(\Memcached::class)
];

$this->mockCacheConfig(
'MemcachedAdapter',
true,
true);
$this->mockCacheConfig('MemcachedAdapter', true, true, false);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}

public function testConstructorWithMemcachedCacheExistsWithJwkError()
{
\DG\BypassFinals::enable();

($this->default_configs)['cache'] = [
'type' => 'memcache',
'client' => $this->createStub(\Memcached::class)
];

$this->mockCacheConfig('MemcachedAdapter', true, false, true);
$config = new AdfsConfiguration($this->default_configs);
$this->commonConstructorAssert($config);
}
Expand Down Expand Up @@ -369,20 +375,28 @@ private function commonConstructorAssert($config)
$this->assertEquals($config->getEndSessionEndpoint(), 'https://your_domain/adfs/oauth2/logout');
}

private function mockCacheConfig($cache_class, $is_hit, $error = false)
private function mockCacheConfig($cache_class, $is_hit, $config_error = false, $jwk_error = false)
{
$mock_cach_item_configs = $this->getMockCachItem(
$is_hit,
file_get_contents(($this->default_configs)['config_uri']));
if (!$error) {
if (!$config_error) {
$mock_cach_item_configs = $this->getMockCachItem(
$is_hit,
file_get_contents(($this->default_configs)['config_uri']));
} else {
$mock_cach_item_configs = $this->getMockCachItem(
$is_hit,
file_get_contents(($this->default_configs)['config_uri']),
json_encode([]));
}

if (!$jwk_error) {
$mock_cach_item_jwks = $this->getMockCachItem(
$is_hit,
file_get_contents(__DIR__.'/../../tests/metadata/azure_ad/configuration/jwks_uri.json'));
} else {
$mock_cach_item_jwks = $this->getMockCachItem(
$is_hit,
file_get_contents(__DIR__.'/../../tests/metadata/azure_ad/configuration/jwks_uri.json'),
file_get_contents(($this->default_configs)['config_uri']));
json_encode([]));
}

$mock_cache = Mockery::mock(sprintf('overload:Symfony\Component\Cache\Adapter\%s', $cache_class));
Expand All @@ -392,9 +406,16 @@ private function mockCacheConfig($cache_class, $is_hit, $error = false)
->with(MicrosoftConfiguration::CACHE_KEY_CONFIGS)
->andReturn($mock_cach_item_configs);
if ($is_hit) {
$mock_cache
->shouldNotReceive('save')
->with($mock_cach_item_configs);
if (!$config_error) {
$mock_cache
->shouldNotReceive('save')
->with($mock_cach_item_configs);
} else {
$mock_cache
->shouldReceive('save')
->with($mock_cach_item_configs)
->andReturn($mock_cach_item_configs);
}
} else {
$mock_cache
->shouldReceive('save')
Expand All @@ -408,7 +429,7 @@ private function mockCacheConfig($cache_class, $is_hit, $error = false)
->andReturn($mock_cach_item_jwks);

if ($is_hit) {
if (!$error) {
if (!$jwk_error) {
$mock_cache
->shouldNotReceive('save')
->with($mock_cach_item_jwks);
Expand Down
Loading

0 comments on commit 23fe443

Please sign in to comment.