Skip to content

Commit 352567d

Browse files
committed
implement small signature key tests
Signed-off-by: Julien Veyssier <julien-nc@posteo.net>
1 parent 21dcdae commit 352567d

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

lib/Controller/ApiController.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ public function deleteUser(string $userId): DataResponse {
9494
public function getJwks(): JSONResponse {
9595
try {
9696
$jwks = $this->jwkService->getJwks();
97-
return new JSONResponse(['keys' => $jwks]);
98-
// return new JSONResponse($this->jwkService->debug());
97+
// return new JSONResponse(['keys' => $jwks]);
98+
return new JSONResponse($this->jwkService->debug());
9999
} catch (\Exception|\Throwable $e) {
100100
return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
101101
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
/**
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
11+
use OCA\UserOIDC\Service\JwkService;
12+
use OCA\UserOIDC\Vendor\Firebase\JWT\JWK;
13+
use OCA\UserOIDC\Vendor\Firebase\JWT\JWT;
14+
use OCP\AppFramework\Services\IAppConfig;
15+
use PHPUnit\Framework\MockObject\MockObject;
16+
use PHPUnit\Framework\TestCase;
17+
18+
class JwkServiceTest extends TestCase {
19+
20+
/** @var IAppConfig|MockObject */
21+
private $appConfig;
22+
/** @var JwkService|MockObject */
23+
private $jwkService;
24+
25+
public function setUp(): void {
26+
parent::setUp();
27+
$this->appConfig = $this->createMock(IAppConfig::class);
28+
$this->jwkService = new JwkService($this->appConfig);
29+
}
30+
31+
public function testSignatureKeyAndJwt() {
32+
$myPemPrivateKey = $this->jwkService->getMyPemSignatureKey();
33+
$sslPrivateKey = openssl_pkey_get_private($myPemPrivateKey);
34+
$pubKey = openssl_pkey_get_details($sslPrivateKey);
35+
$pubKeyPem = $pubKey['key'];
36+
$this->assertStringContainsString('-----BEGIN PUBLIC KEY-----', $pubKeyPem);
37+
$this->assertStringContainsString('-----END PUBLIC KEY-----', $pubKeyPem);
38+
$this->assertStringContainsString('-----BEGIN PRIVATE KEY-----', $myPemPrivateKey);
39+
$this->assertStringContainsString('-----END PRIVATE KEY-----', $myPemPrivateKey);
40+
41+
$initialPayload = ['nice' => 'example'];
42+
$pemPrivateKeyExpiresAt = $this->appConfig->getAppValueInt(JwkService::PEM_SIG_KEY_EXPIRES_AT_SETTINGS_KEY, lazy: true);
43+
$jwkId = 'sig_key_' . $pemPrivateKeyExpiresAt;
44+
$signedJwtToken = $this->jwkService->createJwt($initialPayload, $sslPrivateKey, $jwkId, 'ES384');
45+
46+
// check JWK
47+
$jwk = $this->jwkService->getJwkFromSslKey($pubKey);
48+
$this->assertEquals('EC', $jwk['kty']);
49+
$this->assertEquals('sig', $jwk['use']);
50+
$this->assertEquals($jwkId, $jwk['kid']);
51+
$this->assertEquals('P-384', $jwk['crv']);
52+
$this->assertEquals('ES384', $jwk['alg']);
53+
54+
// check content of JWT
55+
$rawJwks = ['keys' => [$jwk]];
56+
$jwks = JWK::parseKeySet($rawJwks, 'ES384');
57+
$jwtPayload = JWT::decode($signedJwtToken, $jwks);
58+
$jwtPayloadArray = json_decode(json_encode($jwtPayload), true);
59+
$this->assertEquals($initialPayload, $jwtPayloadArray);
60+
61+
// check header of JWT
62+
$jwtParts = explode('.', $signedJwtToken, 3);
63+
$jwtHeader = json_decode(JWT::urlsafeB64Decode($jwtParts[0]), true);
64+
$this->assertEquals('JWT', $jwtHeader['typ']);
65+
$this->assertEquals('ES384', $jwtHeader['alg']);
66+
$this->assertEquals($jwkId, $jwtHeader['kid']);
67+
}
68+
}

0 commit comments

Comments
 (0)