Skip to content

Commit 8c1cd8b

Browse files
committed
WIP
1 parent dcdf2f0 commit 8c1cd8b

17 files changed

Lines changed: 225 additions & 170 deletions

src/Codebooks/ClaimsEnum.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ enum ClaimsEnum: string
173173

174174
case Expiration_Date = 'expirationDate';
175175

176+
case Entities = 'entities';
177+
178+
case EntityId = 'entity_id';
179+
176180
case EntityTypes = 'entity_types';
177181

178182
case FederationCollectionEndpoint = 'federation_collection_endpoint';
@@ -257,6 +261,8 @@ enum ClaimsEnum: string
257261

258262
case Keys = 'keys';
259263

264+
case LastUpdated = 'last_updated';
265+
260266
case Length = 'length';
261267

262268
case Locale = 'locale';
@@ -276,6 +282,8 @@ enum ClaimsEnum: string
276282

277283
case Name = 'name';
278284

285+
case Next = 'next';
286+
279287
case Nonce = 'nonce';
280288

281289
case NonceEndpoint = 'nonce_endpoint';
@@ -434,6 +442,9 @@ enum ClaimsEnum: string
434442
// TransactionCode
435443
case TxCode = 'tx_code';
436444

445+
// UI Infos
446+
case UiInfos = 'ui_infos';
447+
437448
// UserInterfaceLocalesSupported
438449
case UiLocalesSupported = 'ui_locales_supported';
439450

src/Federation.php

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919
use SimpleSAML\OpenID\Factories\DateIntervalDecoratorFactory;
2020
use SimpleSAML\OpenID\Factories\HttpClientDecoratorFactory;
2121
use SimpleSAML\OpenID\Factories\JwsSerializerManagerDecoratorFactory;
22-
use SimpleSAML\OpenID\Federation\CacheEntityCollectionStore;
23-
use SimpleSAML\OpenID\Federation\EntityCollectionBuilder;
24-
use SimpleSAML\OpenID\Federation\EntityCollectionFetcher;
25-
use SimpleSAML\OpenID\Federation\EntityCollectionFilter;
26-
use SimpleSAML\OpenID\Federation\EntityCollectionPaginator;
27-
use SimpleSAML\OpenID\Federation\EntityCollectionSorter;
28-
use SimpleSAML\OpenID\Federation\EntityCollectionStoreInterface;
22+
use SimpleSAML\OpenID\Federation\EntityCollection\CacheEntityCollectionStore;
23+
use SimpleSAML\OpenID\Federation\EntityCollection\EntityCollectionFetcher;
24+
use SimpleSAML\OpenID\Federation\EntityCollection\EntityCollectionFilter;
25+
use SimpleSAML\OpenID\Federation\EntityCollection\EntityCollectionPaginator;
26+
use SimpleSAML\OpenID\Federation\EntityCollection\EntityCollectionResponseFactory;
27+
use SimpleSAML\OpenID\Federation\EntityCollection\EntityCollectionSorter;
28+
use SimpleSAML\OpenID\Federation\EntityCollection\EntityCollectionStoreInterface;
29+
use SimpleSAML\OpenID\Federation\EntityCollection\InMemoryEntityCollectionStore;
2930
use SimpleSAML\OpenID\Federation\EntityStatementFetcher;
3031
use SimpleSAML\OpenID\Federation\Factories\EntityStatementFactory;
3132
use SimpleSAML\OpenID\Federation\Factories\RequestObjectFactory;
@@ -35,15 +36,13 @@
3536
use SimpleSAML\OpenID\Federation\Factories\TrustMarkFactory;
3637
use SimpleSAML\OpenID\Federation\Factories\TrustMarkStatusResponseFactory;
3738
use SimpleSAML\OpenID\Federation\FederationDiscovery;
38-
use SimpleSAML\OpenID\Federation\InMemoryEntityCollectionStore;
3939
use SimpleSAML\OpenID\Federation\MetadataPolicyApplicator;
4040
use SimpleSAML\OpenID\Federation\MetadataPolicyResolver;
4141
use SimpleSAML\OpenID\Federation\SubordinateListingFetcher;
4242
use SimpleSAML\OpenID\Federation\TrustChainResolver;
4343
use SimpleSAML\OpenID\Federation\TrustMarkFetcher;
4444
use SimpleSAML\OpenID\Federation\TrustMarkStatusResponseFetcher;
4545
use SimpleSAML\OpenID\Federation\TrustMarkValidator;
46-
use SimpleSAML\OpenID\Helpers;
4746
use SimpleSAML\OpenID\Jwks\Factories\JwksDecoratorFactory;
4847
use SimpleSAML\OpenID\Jws\Factories\JwsDecoratorBuilderFactory;
4948
use SimpleSAML\OpenID\Jws\Factories\JwsVerifierDecoratorFactory;
@@ -85,7 +84,7 @@ class Federation
8584

8685
protected ?EntityCollectionPaginator $entityCollectionPaginator = null;
8786

88-
protected ?EntityCollectionBuilder $entityCollectionBuilder = null;
87+
protected ?EntityCollectionResponseFactory $entityCollectionBuilder = null;
8988

9089
protected ?EntityStatementFetcher $entityStatementFetcher = null;
9190

@@ -154,6 +153,7 @@ public function __construct(
154153
// phpcs:ignore
155154
protected readonly TrustMarkStatusEndpointUsagePolicyEnum $defaultTrustMarkStatusEndpointUsagePolicyEnum = TrustMarkStatusEndpointUsagePolicyEnum::NotUsed,
156155
int $maxDiscoveryDepth = 10,
156+
protected ?EntityCollectionStoreInterface $entityCollectionStore = null,
157157
) {
158158
$this->maxCacheDurationDecorator = $this->dateIntervalDecoratorFactory()->build($maxCacheDuration);
159159
$this->timestampValidationLeewayDecorator = $this->dateIntervalDecoratorFactory()
@@ -360,17 +360,30 @@ public function subordinateListingFetcher(): SubordinateListingFetcher
360360
}
361361

362362

363-
public function federationDiscovery(?EntityCollectionStoreInterface $store = null): FederationDiscovery
363+
public function entityCollectionStore(): EntityCollectionStoreInterface
364364
{
365-
if (!$this->federationDiscovery instanceof \SimpleSAML\OpenID\Federation\FederationDiscovery) {
366-
$effectiveStore = $store ?? ($this->cacheDecorator() instanceof \SimpleSAML\OpenID\Decorators\CacheDecorator
367-
? new CacheEntityCollectionStore($this->cacheDecorator())
368-
: new InMemoryEntityCollectionStore());
365+
if ($this->entityCollectionStore instanceof Federation\EntityCollection\EntityCollectionStoreInterface) {
366+
return $this->entityCollectionStore;
367+
}
368+
369+
return $this->entityCollectionStore =
370+
$this->cacheDecorator() instanceof \SimpleSAML\OpenID\Decorators\CacheDecorator ?
371+
new CacheEntityCollectionStore(
372+
$this->cacheDecorator(),
373+
$this->helpers(),
374+
$this->logger,
375+
) :
376+
new InMemoryEntityCollectionStore();
377+
}
378+
369379

380+
public function federationDiscovery(): FederationDiscovery
381+
{
382+
if (!$this->federationDiscovery instanceof \SimpleSAML\OpenID\Federation\FederationDiscovery) {
370383
$this->federationDiscovery = new FederationDiscovery(
371384
$this->entityStatementFetcher(),
372385
$this->subordinateListingFetcher(),
373-
$effectiveStore,
386+
$this->entityCollectionStore(),
374387
$this->maxCacheDurationDecorator(),
375388
$this->logger,
376389
$this->maxDiscoveryDepth,
@@ -405,18 +418,16 @@ public function entityCollectionSorter(): EntityCollectionSorter
405418

406419
public function entityCollectionPaginator(): EntityCollectionPaginator
407420
{
408-
return $this->entityCollectionPaginator ??= new EntityCollectionPaginator();
421+
return $this->entityCollectionPaginator ??= new EntityCollectionPaginator(
422+
$this->helpers(),
423+
);
409424
}
410425

411426

412-
/**
413-
* @param \SimpleSAML\OpenID\Federation\EntityCollectionStoreInterface|null $store Forwarded to
414-
* federationDiscovery()
415-
*/
416-
public function entityCollectionBuilder(?EntityCollectionStoreInterface $store = null): EntityCollectionBuilder
427+
public function entityCollectionResponseFactory(): EntityCollectionResponseFactory
417428
{
418-
return $this->entityCollectionBuilder ??= new EntityCollectionBuilder(
419-
$this->federationDiscovery($store),
429+
return $this->entityCollectionBuilder ??= new EntityCollectionResponseFactory(
430+
$this->federationDiscovery(),
420431
$this->entityCollectionFilter(),
421432
$this->entityCollectionSorter(),
422433
$this->entityCollectionPaginator(),

src/Federation/CacheEntityCollectionStore.php

Lines changed: 0 additions & 64 deletions
This file was deleted.

src/Federation/EntityCollection.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,16 @@ class EntityCollection
1010
* @param array<string, \SimpleSAML\OpenID\Federation\EntityStatement> $entities Keyed by entity ID
1111
*/
1212
public function __construct(
13-
public readonly array $entities,
13+
protected readonly array $entities,
1414
) {
1515
}
16+
17+
18+
/**
19+
* @return array<string, \SimpleSAML\OpenID\Federation\EntityStatement>
20+
*/
21+
public function all(): array
22+
{
23+
return $this->entities;
24+
}
1625
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\OpenID\Federation\EntityCollection;
6+
7+
use Psr\Log\LoggerInterface;
8+
use SimpleSAML\OpenID\Decorators\CacheDecorator;
9+
use SimpleSAML\OpenID\Helpers;
10+
use Throwable;
11+
12+
class CacheEntityCollectionStore implements EntityCollectionStoreInterface
13+
{
14+
protected const PREFIX = 'federation_entity_ids';
15+
16+
17+
public function __construct(
18+
protected readonly CacheDecorator $cacheDecorator,
19+
protected readonly Helpers $helpers,
20+
protected readonly ?LoggerInterface $logger,
21+
) {
22+
}
23+
24+
25+
public function storeEntityIds(string $trustAnchorId, array $entityIds, int $ttl): void
26+
{
27+
try {
28+
$this->cacheDecorator->set(
29+
$this->helpers->json()->encode($entityIds),
30+
$ttl,
31+
self::PREFIX,
32+
$trustAnchorId,
33+
);
34+
} catch (Throwable $throwable) {
35+
$this->logger?->error('Unable to store entity IDs in cache.', [
36+
'trustAnchorId' => $trustAnchorId,
37+
'entityIds' => $entityIds,
38+
'exception_message' => $throwable->getMessage(),
39+
]);
40+
}
41+
}
42+
43+
44+
public function getEntityIds(string $trustAnchorId): ?array
45+
{
46+
try {
47+
/** @var ?string $cached */
48+
$cached = $this->cacheDecorator->get(null, self::PREFIX, $trustAnchorId);
49+
50+
if (is_null($cached)) {
51+
return null;
52+
}
53+
54+
$decoded = $this->helpers->json()->decode($cached);
55+
return $this->helpers->type()->ensureArrayWithValuesAsNonEmptyStrings($decoded);
56+
} catch (Throwable $throwable) {
57+
$this->logger?->error('Unable to retrieve entity IDs from cache.', [
58+
'trustAnchorId' => $trustAnchorId,
59+
'exception_message' => $throwable->getMessage(),
60+
]);
61+
return null;
62+
}
63+
}
64+
65+
66+
public function clearEntityIds(string $trustAnchorId): void
67+
{
68+
try {
69+
$this->cacheDecorator->delete(self::PREFIX, $trustAnchorId);
70+
} catch (Throwable $throwable) {
71+
$this->logger?->error('Unable to clear entity IDs from cache.', [
72+
'trustAnchorId' => $trustAnchorId,
73+
'exception_message' => $throwable->getMessage(),
74+
]);
75+
}
76+
}
77+
}

src/Federation/EntityCollectionEntry.php renamed to src/Federation/EntityCollection/EntityCollectionEntry.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,23 @@
22

33
declare(strict_types=1);
44

5-
namespace SimpleSAML\OpenID\Federation;
5+
namespace SimpleSAML\OpenID\Federation\EntityCollection;
66

77
use JsonSerializable;
88
use SimpleSAML\OpenID\Codebooks\ClaimsEnum;
99

1010
class EntityCollectionEntry implements JsonSerializable
1111
{
1212
/**
13-
* @param non-empty-string $entityId
14-
* @param non-empty-string[] $entityTypes
15-
* @param array<string,mixed>|null $uiInfo Logo, display name, etc.
13+
* @param non-empty-string $entityId
14+
* @param non-empty-string[] $entityTypes
15+
* @param array<string,mixed>|null $uiInfos Logo, display name, etc.
1616
* @param array<array<mixed>>|null $trustMarks
1717
*/
1818
public function __construct(
1919
public readonly string $entityId,
2020
public readonly array $entityTypes,
21-
public readonly ?array $uiInfo = null,
21+
public readonly ?array $uiInfos = null,
2222
public readonly ?array $trustMarks = null,
2323
) {
2424
}
@@ -28,19 +28,19 @@ public function __construct(
2828
* @return array{
2929
* entity_id: non-empty-string,
3030
* entity_types: non-empty-string[],
31-
* ui_info?: array<string,mixed>,
31+
* ui_infos?: array<string,mixed>,
3232
* trust_marks?: array<array<mixed>>
3333
* }
3434
*/
3535
public function jsonSerialize(): array
3636
{
3737
$data = [
38-
'entity_id' => $this->entityId,
38+
ClaimsEnum::EntityId->value => $this->entityId,
3939
ClaimsEnum::EntityTypes->value => $this->entityTypes,
4040
];
4141

42-
if (!is_null($this->uiInfo)) {
43-
$data['ui_info'] = $this->uiInfo;
42+
if (!is_null($this->uiInfos)) {
43+
$data[ClaimsEnum::UiInfos->value] = $this->uiInfos;
4444
}
4545

4646
if (!is_null($this->trustMarks)) {

0 commit comments

Comments
 (0)