Skip to content

Commit

Permalink
Merge branch 'wip-version-6' into wip-version-6-federation
Browse files Browse the repository at this point in the history
  • Loading branch information
cicnavi committed May 20, 2024
2 parents 66c00db + 89f5941 commit 84610fc
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 35 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ["8.1", "8.2"]
php-versions: ["8.1", "8.2", "8.3"]

steps:
- name: Setup PHP, with composer and extensions
Expand Down Expand Up @@ -45,7 +45,7 @@ jobs:
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}"
restore-keys: ${{ runner.os }}-composer-

- name: Validate composer.json and composer.lock
Expand Down Expand Up @@ -93,10 +93,10 @@ jobs:
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Cache composer dependencies
uses: actions/cache@v1
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}"
restore-keys: ${{ runner.os }}-composer-

- name: Install Composer dependencies
Expand Down Expand Up @@ -137,7 +137,7 @@ jobs:
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}"
restore-keys: ${{ runner.os }}-composer-

- name: Install Composer dependencies
Expand Down Expand Up @@ -169,7 +169,7 @@ jobs:
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}"
restore-keys: ${{ runner.os }}-composer-

- name: Install Composer dependencies
Expand Down
2 changes: 1 addition & 1 deletion UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ this module as a library or extending from it, you will probably encounter break
has been refactored:

- TODO upgrade to v9 of oauth2-server https://github.com/thephpleague/oauth2-server/releases/tag/9.0.0
- TODO upgrade to v5 of lcobucci/jwt https://github.com/lcobucci/jwt
- upgraded to v5 of lcobucci/jwt https://github.com/lcobucci/jwt
- TODO move checkers to templates (generics) for proper static type handling
- TODO move to SSP (symfony) container
- TODO remove dependency on laminas/laminas-diactoros
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"guzzlehttp/guzzle": "^7.0",
"laminas/laminas-diactoros": "^2.25.2",
"laminas/laminas-httphandlerrunner": "^2",
"lcobucci/jwt": "^4.1",
"lcobucci/jwt": "^5.3",
"league/oauth2-server": "^8.5.3",
"nette/forms": "^3",
"psr/container": "^2.0",
Expand Down
2 changes: 1 addition & 1 deletion conformance-tests/conformance-rp-initiated-logout-ci.json
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@
"xpath",
"//*",
10,
"Token signer mismatch",
"The JWT string is missing the Signature part",
"update-image-placeholder"
]
]
Expand Down
2 changes: 1 addition & 1 deletion src/Entities/AccessTokenEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public function toString(): ?string
protected function convertToJWT(): Token
{
$jwtBuilderService = new JsonWebTokenBuilderService();

/** @psalm-suppress ArgumentTypeCoercion */
$jwtBuilder = $jwtBuilderService->getDefaultJwtTokenBuilder()
->permittedFor($this->getClient()->getIdentifier())
->identifiedBy((string)$this->getIdentifier())
Expand Down
2 changes: 1 addition & 1 deletion src/Server/Validators/BearerTokenValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public function validateAuthorization(ServerRequestInterface $request): ServerRe
$jwt = $parsedBody['access_token'];
}

if (!is_string($jwt)) {
if (!is_string($jwt) || empty($jwt)) {
throw OidcServerException::accessDenied('Missing Authorization header or access_token request body param.');
}

Expand Down
18 changes: 9 additions & 9 deletions src/Services/DatabaseMigration.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ private function version20180425203400(): void
{
$clientTableName = $this->database->applyPrefix(ClientRepository::TABLE_NAME);
$this->database->write(<<< EOT
ALTER TABLE ${clientTableName}
ALTER TABLE {$clientTableName}
ADD is_enabled BOOLEAN NOT NULL DEFAULT true
EOT
);
Expand All @@ -228,7 +228,7 @@ private function version20200517071100(): void
{
$clientTableName = $this->database->applyPrefix(ClientRepository::TABLE_NAME);
$this->database->write(<<< EOT
ALTER TABLE ${clientTableName}
ALTER TABLE {$clientTableName}
ADD is_confidential BOOLEAN NOT NULL DEFAULT false
EOT
);
Expand All @@ -238,7 +238,7 @@ private function version20200901163000(): void
{
$clientTableName = $this->database->applyPrefix(AuthCodeRepository::TABLE_NAME);
$this->database->write(<<< EOT
ALTER TABLE ${clientTableName}
ALTER TABLE {$clientTableName}
ADD nonce TEXT NULL
EOT
);
Expand All @@ -248,7 +248,7 @@ private function version20210902113500(): void
{
$clientTableName = $this->database->applyPrefix(ClientRepository::TABLE_NAME);
$this->database->write(<<< EOT
ALTER TABLE ${clientTableName}
ALTER TABLE {$clientTableName}
ADD owner VARCHAR(191) NULL
EOT
);
Expand All @@ -261,14 +261,14 @@ protected function version20210714113000(): void
{
$tableName = $this->database->applyPrefix(AccessTokenRepository::TABLE_NAME);
$this->database->write(<<< EOT
ALTER TABLE ${tableName}
ALTER TABLE {$tableName}
ADD auth_code_id VARCHAR(191) NULL
EOT
);

$tableName = $this->database->applyPrefix(RefreshTokenRepository::TABLE_NAME);
$this->database->write(<<< EOT
ALTER TABLE ${tableName}
ALTER TABLE {$tableName}
ADD auth_code_id VARCHAR(191) NULL
EOT
);
Expand All @@ -281,7 +281,7 @@ protected function version20210823141300(): void
{
$tableName = $this->database->applyPrefix(AccessTokenRepository::TABLE_NAME);
$this->database->write(<<< EOT
ALTER TABLE ${tableName}
ALTER TABLE {$tableName}
ADD requested_claims TEXT NULL
EOT
);
Expand Down Expand Up @@ -316,7 +316,7 @@ protected function version20210908143500(): void
{
$clientTableName = $this->database->applyPrefix(ClientRepository::TABLE_NAME);
$this->database->write(<<< EOT
ALTER TABLE ${clientTableName}
ALTER TABLE {$clientTableName}
ADD post_logout_redirect_uri TEXT NULL
EOT
);
Expand All @@ -329,7 +329,7 @@ protected function version20210916153400(): void
{
$clientTableName = $this->database->applyPrefix(ClientRepository::TABLE_NAME);
$this->database->write(<<< EOT
ALTER TABLE ${clientTableName}
ALTER TABLE {$clientTableName}
ADD backchannel_logout_uri TEXT NULL
EOT
);
Expand Down
30 changes: 16 additions & 14 deletions src/Services/IdTokenBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function __construct(

/**
* @throws Exception
* @psalm-suppress ArgumentTypeCoercion
*/
public function build(
UserEntityInterface $userEntity,
Expand All @@ -48,15 +49,15 @@ public function build(
$builder = $this->getBuilder($accessToken, $userEntity);

if (null !== $nonce) {
$builder->withClaim('nonce', $nonce);
$builder = $builder->withClaim('nonce', $nonce);
}

if (null !== $authTime) {
$builder->withClaim('auth_time', $authTime);
$builder = $builder->withClaim('auth_time', $authTime);
}

if ($addAccessTokenHash) {
$builder->withClaim(
$builder = $builder->withClaim(
'at_hash',
$this->generateAccessTokenHash(
$accessToken,
Expand All @@ -66,11 +67,11 @@ public function build(
}

if (null !== $acr) {
$builder->withClaim('acr', $acr);
$builder = $builder->withClaim('acr', $acr);
}

if (null !== $sessionId) {
$builder->withClaim('sid', $sessionId);
$builder = $builder->withClaim('sid', $sessionId);
}

// Need a claim factory here to reduce the number of claims by provided scope.
Expand All @@ -92,36 +93,36 @@ public function build(
if (is_array($claimValue)) {
/** @psalm-suppress MixedAssignment */
foreach ($claimValue as $aud) {
$builder->permittedFor((string)$aud);
$builder = $builder->permittedFor((string)$aud);
}
} else {
$builder->permittedFor((string)$claimValue);
$builder = $builder->permittedFor((string)$claimValue);
}
break;
case RegisteredClaims::EXPIRATION_TIME:
/** @noinspection PhpUnnecessaryStringCastInspection */
$builder->expiresAt(new DateTimeImmutable('@' . (string)$claimValue));
$builder = $builder->expiresAt(new DateTimeImmutable('@' . (string)$claimValue));
break;
case RegisteredClaims::ID:
$builder->identifiedBy((string)$claimValue);
$builder = $builder->identifiedBy((string)$claimValue);
break;
case RegisteredClaims::ISSUED_AT:
/** @noinspection PhpUnnecessaryStringCastInspection */
$builder->issuedAt(new DateTimeImmutable('@' . (string)$claimValue));
$builder = $builder->issuedAt(new DateTimeImmutable('@' . (string)$claimValue));
break;
case RegisteredClaims::ISSUER:
$builder->issuedBy((string)$claimValue);
$builder = $builder->issuedBy((string)$claimValue);
break;
case RegisteredClaims::NOT_BEFORE:
/** @noinspection PhpUnnecessaryStringCastInspection */
$builder->canOnlyBeUsedAfter(new DateTimeImmutable('@' . (string)$claimValue));
$builder = $builder->canOnlyBeUsedAfter(new DateTimeImmutable('@' . (string)$claimValue));
break;
case RegisteredClaims::SUBJECT:
$builder->relatedTo((string)$claimValue);
$builder = $builder->relatedTo((string)$claimValue);
break;
default:
if ($addClaimsFromScopes || array_key_exists($claimName, $additionalClaims)) {
$builder->withClaim($claimName, $claimValue);
$builder = $builder->withClaim($claimName, $claimValue);
}
}
}
Expand All @@ -136,6 +137,7 @@ protected function getBuilder(
AccessTokenEntityInterface $accessToken,
UserEntityInterface $userEntity
): Builder {
/** @psalm-suppress ArgumentTypeCoercion */
return $this->jsonWebTokenBuilderService
->getDefaultJwtTokenBuilder()
->permittedFor($accessToken->getClient()->getIdentifier())
Expand Down
3 changes: 3 additions & 0 deletions src/Services/JsonWebTokenBuilderService.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class JsonWebTokenBuilderService
/**
* @throws ReflectionException
* @throws Exception
*
* @psalm-suppress ArgumentTypeCoercion
*/
public function __construct(
protected ModuleConfig $moduleConfig = new ModuleConfig()
Expand All @@ -44,6 +46,7 @@ public function __construct(
*/
public function getDefaultJwtTokenBuilder(): Builder
{
/** @psalm-suppress ArgumentTypeCoercion */
// Ignore microseconds when handling dates.
return $this->jwtConfig->builder(ChainedFormatter::withUnixTimestampDates())
->issuedBy($this->moduleConfig->getSimpleSAMLSelfURLHost())
Expand Down
3 changes: 2 additions & 1 deletion src/Services/LogoutTokenBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public function __construct(

/**
* @throws OAuthServerException|Exception
* @psalm-suppress ArgumentTypeCoercion
*/
public function forRelyingPartyAssociation(RelyingPartyAssociationInterface $relyingPartyAssociation): string
{
Expand All @@ -30,7 +31,7 @@ public function forRelyingPartyAssociation(RelyingPartyAssociationInterface $rel
;

if ($relyingPartyAssociation->getSessionId() !== null) {
$logoutTokenBuilder->withClaim('sid', $relyingPartyAssociation->getSessionId());
$logoutTokenBuilder = $logoutTokenBuilder->withClaim('sid', $relyingPartyAssociation->getSessionId());
}

return $this->jsonWebTokenBuilderService->getSignedJwtTokenFromBuilder($logoutTokenBuilder)->toString();
Expand Down
10 changes: 10 additions & 0 deletions src/Utils/Checker/Rules/IdTokenHintRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ public function checkRule(
InMemory::plainText($publicKey->getKeyContents())
);

if (empty($idTokenHintParam)) {
throw OidcServerException::invalidRequest(
'id_token_hint',
'Received empty id_token_hint',
null,
null,
$state
);
}

try {
/** @var UnencryptedToken $idTokenHint */
$idTokenHint = $jwtConfig->parser()->parse($idTokenHintParam);
Expand Down

0 comments on commit 84610fc

Please sign in to comment.