Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ PHP version requirement changes in minor releases for SimpleSAMLphp.

| OIDC module | Tested SimpleSAMLphp | PHP | Note |
|:------------|:---------------------|:------:|-----------------------------|
| v6.\* | v2.2.\* | \>=8.2 | Recommended |
| v6.\* | v2.3.\* | \>=8.2 | Recommended |
| v5.\* | v2.1.\* | \>=8.1 | |
| v4.\* | v2.0.\* | \>=8.0 | |
| v3.\* | v2.0.\* | \>=7.4 | Abandoned from August 2023. |
Expand Down Expand Up @@ -329,7 +329,7 @@ docker run --name ssp-oidc-dev \
--mount type=bind,source="$(pwd)/docker/ssp/oidc_module.crt",target=/var/simplesamlphp/cert/oidc_module.crt,readonly \
--mount type=bind,source="$(pwd)/docker/ssp/oidc_module.key",target=/var/simplesamlphp/cert/oidc_module.key,readonly \
--mount type=bind,source="$(pwd)/docker/apache-override.cf",target=/etc/apache2/sites-enabled/ssp-override.cf,readonly \
-p 443:443 cirrusid/simplesamlphp:v2.2.2
-p 443:443 cirrusid/simplesamlphp:v2.3.5
```

Visit https://localhost/simplesaml/ and confirm you get the default page.
Expand Down
2 changes: 1 addition & 1 deletion UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ has been refactored:

- upgraded to v5 of lcobucci/jwt https://github.com/lcobucci/jwt
- upgraded to v3 of laminas/laminas-diactoros https://github.com/laminas/laminas-diactoros
- SimpleSAMLphp version used during development was bumped to v2.2
- SimpleSAMLphp version used during development was bumped to v2.3
- In Authorization Code Flow, a new validation was added which checks for 'openid' value in 'scope' parameter. Up to
now, 'openid' value was dynamically added if not present. In Implicit Code Flow this validation was already present.

Expand Down
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"friendsofphp/php-cs-fixer": "^3",
"phpunit/phpunit": "^10",
"rector/rector": "^0.18.3",
"simplesamlphp/simplesamlphp": "2.2.*",
"simplesamlphp/simplesamlphp": "2.3.*",
"simplesamlphp/simplesamlphp-test-framework": "^1.5",
"squizlabs/php_codesniffer": "^3",
"vimeo/psalm": "^5",
Expand All @@ -56,9 +56,10 @@
},
"sort-packages": true,
"allow-plugins": {
"simplesamlphp/composer-module-installer": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"phpstan/extension-installer": true
"phpstan/extension-installer": true,
"simplesamlphp/composer-module-installer": true,
"simplesamlphp/composer-xmlprovider-installer": true
},
"cache-dir": "build/composer"
},
Expand Down
27 changes: 27 additions & 0 deletions config-templates/module_oidc.php
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,33 @@
// 'eyJ...GHg',
],

// (optional) Federation participation limit by Trust Marks. This is an array with the following format:
// [
// 'trust-anchor-id' => [
// 'limit-id' => [
// 'trust-mark-id',
// 'trust-mark-id-2',
// ],
// ],
// ],
// Check example below on how this can be used. If federation participation limit is configured for particular
// Trust Anchor ID, at least one combination of "limit ID" => "trust mark list" should be defined.
ModuleConfig::OPTION_FEDERATION_PARTICIPATION_LIMIT_BY_TRUST_MARKS => [
// We are limiting federation participation using Trust Marks for 'https://ta.example.org/'.
'https://ta.example.org/' => [
// Entities must have (at least) one Trust Mark from the list below.
\SimpleSAML\Module\oidc\Codebooks\LimitsEnum::OneOf->value => [
'trust-mark-id',
'trust-mark-id-2',
],
// Entities must have all Trust Marks from the list below.
\SimpleSAML\Module\oidc\Codebooks\LimitsEnum::AllOf->value => [
'trust-mark-id-3',
'trust-mark-id-4',
],
],
],

// (optional) Dedicated federation cache adapter, used to cache federation artifacts like trust chains, entity
// statements, etc. It will also be used for token reuse check in federation context. Setting this option is
// recommended in production environments. If set to null, no caching will be used. Can be set to any
Expand Down
4 changes: 2 additions & 2 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#FROM cirrusid/simplesamlphp:v2.2.2
FROM cicnavi/simplesamlphp:dev
FROM cirrusid/simplesamlphp:v2.3.5
#FROM cicnavi/simplesamlphp:dev

RUN apt-get update && apt-get install -y sqlite3
# Prepopulate the DB with items needed for testing
Expand Down
7 changes: 7 additions & 0 deletions routing/routes/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use SimpleSAML\Module\oidc\Controllers\AccessTokenController;
use SimpleSAML\Module\oidc\Controllers\Admin\ClientController;
use SimpleSAML\Module\oidc\Controllers\Admin\ConfigController;
use SimpleSAML\Module\oidc\Controllers\Admin\TestController;
use SimpleSAML\Module\oidc\Controllers\AuthorizationController;
use SimpleSAML\Module\oidc\Controllers\ConfigurationDiscoveryController;
use SimpleSAML\Module\oidc\Controllers\EndSessionController;
Expand Down Expand Up @@ -57,6 +58,12 @@
->controller([ClientController::class, 'delete'])
->methods([HttpMethodsEnum::POST->value]);

// Testing

$routes->add(RoutesEnum::AdminTestTrustChainResolution->name, RoutesEnum::AdminTestTrustChainResolution->value)
->controller([TestController::class, 'trustChainResolution'])
->methods([HttpMethodsEnum::GET->value, HttpMethodsEnum::POST->value]);

/*****************************************************************************************************************
* OpenID Connect
****************************************************************************************************************/
Expand Down
2 changes: 2 additions & 0 deletions routing/services/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ services:
factory: ['@SimpleSAML\Module\oidc\Factories\ResourceServerFactory', 'build']

# Utils
SimpleSAML\Module\oidc\Utils\Debug\ArrayLogger: ~
SimpleSAML\Module\oidc\Utils\FederationParticipationValidator: ~
SimpleSAML\Module\oidc\Utils\Routes: ~
SimpleSAML\Module\oidc\Utils\RequestParamsResolver: ~
SimpleSAML\Module\oidc\Utils\ClassInstanceBuilder: ~
Expand Down
2 changes: 1 addition & 1 deletion src/Admin/Menu.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function __construct(Item ...$items)
array_push($this->items, ...$items);
}

public function addItem(Item $menuItem, int $offset = null): void
public function addItem(Item $menuItem, ?int $offset = null): void
{
$offset ??= count($this->items);

Expand Down
11 changes: 11 additions & 0 deletions src/Codebooks/LimitsEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\Module\oidc\Codebooks;

enum LimitsEnum: string
{
case OneOf = 'one_of';
case AllOf = 'all_of';
}
4 changes: 4 additions & 0 deletions src/Codebooks/RoutesEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ enum RoutesEnum: string
case AdminClientsResetSecret = 'admin/clients/reset-secret';
case AdminClientsDelete = 'admin/clients/delete';

// Testing
case AdminTestTrustChainResolution = 'admin/test/trust-chain-resolution';


/*****************************************************************************************************************
* OpenID Connect
****************************************************************************************************************/
Expand Down
111 changes: 111 additions & 0 deletions src/Controllers/Admin/TestController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\Module\oidc\Controllers\Admin;

use SimpleSAML\Module\oidc\Admin\Authorization;
use SimpleSAML\Module\oidc\Codebooks\RoutesEnum;
use SimpleSAML\Module\oidc\Exceptions\OidcException;
use SimpleSAML\Module\oidc\Factories\TemplateFactory;
use SimpleSAML\Module\oidc\Helpers;
use SimpleSAML\Module\oidc\ModuleConfig;
use SimpleSAML\Module\oidc\Utils\Debug\ArrayLogger;
use SimpleSAML\OpenID\Codebooks\EntityTypesEnum;
use SimpleSAML\OpenID\Exceptions\TrustChainException;
use SimpleSAML\OpenID\Federation;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class TestController
{
public function __construct(

Check warning on line 22 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L22

Added line #L22 was not covered by tests
protected readonly ModuleConfig $moduleConfig,
protected readonly TemplateFactory $templateFactory,
protected readonly Authorization $authorization,
protected readonly Federation $federation,
protected readonly Helpers $helpers,
protected readonly ArrayLogger $arrayLogger,
) {
$this->authorization->requireAdmin(true);

Check warning on line 30 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L30

Added line #L30 was not covered by tests
}

/**
* @throws \SimpleSAML\Error\ConfigurationError
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
* @throws \SimpleSAML\Module\oidc\Exceptions\OidcException
*/
public function trustChainResolution(Request $request): Response

Check warning on line 38 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L38

Added line #L38 was not covered by tests
{
$this->arrayLogger->setWeight(ArrayLogger::WEIGHT_WARNING);

Check warning on line 40 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L40

Added line #L40 was not covered by tests
// Let's create new Federation instance so we can inject our debug logger and go without cache.
$federation = new Federation(
supportedAlgorithms: $this->federation->supportedAlgorithms(),
cache: null,
logger: $this->arrayLogger,
);

Check warning on line 46 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L42-L46

Added lines #L42 - L46 were not covered by tests

$leafEntityId = $this->moduleConfig->getIssuer();
$trustChainBag = null;
$resolvedMetadata = [];
$isFormSubmitted = false;

Check warning on line 51 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L48-L51

Added lines #L48 - L51 were not covered by tests

try {
$trustAnchorIds = $this->moduleConfig->getFederationTrustAnchorIds();
} catch (\Throwable $exception) {
$this->arrayLogger->error('Module config error: ' . $exception->getMessage());
$trustAnchorIds = [];

Check warning on line 57 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L54-L57

Added lines #L54 - L57 were not covered by tests
}

if ($request->isMethod(Request::METHOD_POST)) {
$isFormSubmitted = true;

Check warning on line 61 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L60-L61

Added lines #L60 - L61 were not covered by tests

!empty($leafEntityId = $request->request->getString('leafEntityId')) ||
throw new OidcException('Empty leaf entity ID.');
!empty($rawTrustAnchorIds = $request->request->getString('trustAnchorIds')) ||
throw new OidcException('Empty Trust Anchor IDs.');

Check warning on line 66 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L63-L66

Added lines #L63 - L66 were not covered by tests

/** @var non-empty-array<non-empty-string> $trustAnchorIds */
$trustAnchorIds = $this->helpers->str()->convertTextToArray($rawTrustAnchorIds);

Check warning on line 69 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L69

Added line #L69 was not covered by tests

try {
$trustChainBag = $federation->trustChainResolver()->for($leafEntityId, $trustAnchorIds);

Check warning on line 72 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L72

Added line #L72 was not covered by tests

foreach ($trustChainBag->getAll() as $index => $trustChain) {
$metadataEntries = [];
foreach (EntityTypesEnum::cases() as $entityTypeEnum) {

Check warning on line 76 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L74-L76

Added lines #L74 - L76 were not covered by tests
try {
$metadataEntries[$entityTypeEnum->value] =
$trustChain->getResolvedMetadata($entityTypeEnum);
} catch (\Throwable $exception) {
$this->arrayLogger->error(
'Metadata resolving error: ' . $exception->getMessage(),
compact('index', 'entityTypeEnum'),
);
continue;

Check warning on line 85 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L78-L85

Added lines #L78 - L85 were not covered by tests
}
}
$resolvedMetadata[$index] = array_filter($metadataEntries);

Check warning on line 88 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L88

Added line #L88 was not covered by tests
}
} catch (TrustChainException $exception) {
$this->arrayLogger->error('Trust chain error: ' . $exception->getMessage());

Check warning on line 91 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L90-L91

Added lines #L90 - L91 were not covered by tests
}
}

$trustAnchorIds = implode("\n", $trustAnchorIds);
$logMessages = $this->arrayLogger->getEntries();

Check warning on line 96 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L95-L96

Added lines #L95 - L96 were not covered by tests
//dd($this->arrayLogger->getEntries());
return $this->templateFactory->build(
'oidc:tests/trust-chain-resolution.twig',
compact(
'leafEntityId',
'trustAnchorIds',
'trustChainBag',
'resolvedMetadata',
'logMessages',
'isFormSubmitted',
),
RoutesEnum::AdminTestTrustChainResolution->value,
);

Check warning on line 109 in src/Controllers/Admin/TestController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/TestController.php#L98-L109

Added lines #L98 - L109 were not covered by tests
}
}
16 changes: 8 additions & 8 deletions src/Controllers/Federation/Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,25 +65,25 @@
// $requestObject = $requestObjectFactory->fromToken($unprotectedJws);

// dd($requestObject, $requestObject->getPayload(), $requestObject->getHeader());
// $cache->clear();
$this->federationCache?->cache->clear();

Check warning on line 68 in src/Controllers/Federation/Test.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Federation/Test.php#L68

Added line #L68 was not covered by tests

$trustChain = $this->federation
->trustChainResolver()
->for(
'https://08-dap.localhost.markoivancic.from.hr/openid/entities/ALeaf/',
// 'https://08-dap.localhost.markoivancic.from.hr/openid/entities/ALeaf/',
// 'https://trust-anchor.testbed.oidcfed.incubator.geant.org/oidc/rp/',
// 'https://relying-party-php.testbed.oidcfed.incubator.geant.org/',
// 'https://gorp.testbed.oidcfed.incubator.geant.org',
'https://gorp.testbed.oidcfed.incubator.geant.org',

Check warning on line 76 in src/Controllers/Federation/Test.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Federation/Test.php#L76

Added line #L76 was not covered by tests
// 'https://maiv1.incubator.geant.org',
[
// 'https://trust-anchor.testbed.oidcfed.incubator.geant.org/',
'https://trust-anchor.testbed.oidcfed.incubator.geant.org/',

Check warning on line 79 in src/Controllers/Federation/Test.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Federation/Test.php#L79

Added line #L79 was not covered by tests
'https://08-dap.localhost.markoivancic.from.hr/openid/entities/ABTrustAnchor/',
// 'https://08-dap.localhost.markoivancic.from.hr/openid/entities/CTrustAnchor/',
'https://08-dap.localhost.markoivancic.from.hr/openid/entities/CTrustAnchor/',

Check warning on line 81 in src/Controllers/Federation/Test.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Federation/Test.php#L81

Added line #L81 was not covered by tests
],
);

)->getAll();
dd($trustChain);

Check warning on line 84 in src/Controllers/Federation/Test.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Federation/Test.php#L83-L84

Added lines #L83 - L84 were not covered by tests
$leaf = $trustChain->getResolvedLeaf();
// dd($leaf);
dd($leaf->getPayload());

Check warning on line 86 in src/Controllers/Federation/Test.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Federation/Test.php#L86

Added line #L86 was not covered by tests
$leafFederationJwks = $leaf->getJwks();
// dd($leafFederationJwks);
// /** @psalm-suppress PossiblyNullArgument */
Expand Down
10 changes: 5 additions & 5 deletions src/Entities/AccessTokenEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ public function __construct(
DateTimeImmutable $expiryDateTime,
CryptKey $privateKey,
protected JsonWebTokenBuilderService $jsonWebTokenBuilderService,
int|string $userIdentifier = null,
string $authCodeId = null,
array $requestedClaims = null,
bool $isRevoked = false,
Configuration $jwtConfiguration = null,
int|string|null $userIdentifier = null,
?string $authCodeId = null,
?array $requestedClaims = null,
?bool $isRevoked = false,
?Configuration $jwtConfiguration = null,
) {
$this->setIdentifier($id);
$this->setClient($clientEntity);
Expand Down
6 changes: 3 additions & 3 deletions src/Entities/AuthCodeEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ public function __construct(
OAuth2ClientEntityInterface $client,
array $scopes,
DateTimeImmutable $expiryDateTime,
string $userIdentifier = null,
string $redirectUri = null,
string $nonce = null,
?string $userIdentifier = null,
?string $redirectUri = null,
?string $nonce = null,
bool $isRevoked = false,
) {
$this->identifier = $id;
Expand Down
8 changes: 4 additions & 4 deletions src/Factories/Entities/AccessTokenEntityFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ public function fromData(
OAuth2ClientEntityInterface $clientEntity,
array $scopes,
DateTimeImmutable $expiryDateTime,
int|string $userIdentifier = null,
string $authCodeId = null,
array $requestedClaims = null,
bool $isRevoked = false,
int|string|null $userIdentifier = null,
?string $authCodeId = null,
?array $requestedClaims = null,
?bool $isRevoked = false,
): AccessTokenEntity {
return new AccessTokenEntity(
$id,
Expand Down
6 changes: 3 additions & 3 deletions src/Factories/Entities/AuthCodeEntityFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ public function fromData(
OAuth2ClientEntityInterface $client,
array $scopes,
DateTimeImmutable $expiryDateTime,
string $userIdentifier = null,
string $redirectUri = null,
string $nonce = null,
?string $userIdentifier = null,
?string $redirectUri = null,
?string $nonce = null,
bool $isRevoked = false,
): AuthCodeEntity {
return new AuthCodeEntity(
Expand Down
4 changes: 2 additions & 2 deletions src/Factories/Entities/ScopeEntityFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class ScopeEntityFactory
*/
public function fromData(
string $identifier,
string $description = null,
string $icon = null,
?string $description = null,
?string $icon = null,
array $claims = [],
): ScopeEntity {
return new ScopeEntity(
Expand Down
3 changes: 3 additions & 0 deletions src/Factories/RequestRulesManagerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\ClaimTranslatorExtractor;
use SimpleSAML\Module\oidc\Utils\FederationCache;
use SimpleSAML\Module\oidc\Utils\FederationParticipationValidator;
use SimpleSAML\Module\oidc\Utils\JwksResolver;
use SimpleSAML\Module\oidc\Utils\ProtocolCache;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
Expand All @@ -58,6 +59,7 @@
private readonly Federation $federation,
private readonly Helpers $helpers,
private readonly JwksResolver $jwksResolver,
private readonly FederationParticipationValidator $federationParticipationValidator,
private readonly ?FederationCache $federationCache = null,
private readonly ?ProtocolCache $protocolCache = null,
) {
Expand Down Expand Up @@ -88,6 +90,7 @@
$this->federation,
$this->helpers,
$this->jwksResolver,
$this->federationParticipationValidator,

Check warning on line 93 in src/Factories/RequestRulesManagerFactory.php

View check run for this annotation

Codecov / codecov/patch

src/Factories/RequestRulesManagerFactory.php#L93

Added line #L93 was not covered by tests
$this->federationCache,
),
new RedirectUriRule($this->requestParamsResolver),
Expand Down
Loading
Loading