Remove unused HS256 signing algorithm

This commit is contained in:
ErickSkrauch 2024-06-14 03:21:00 +02:00
parent 0a666e1e12
commit 17109f8eb5
No known key found for this signature in database
GPG Key ID: 669339FCBB30EE0E
7 changed files with 25 additions and 23 deletions

View File

@ -7,7 +7,6 @@ AUTHSERVER_HOST=authserver.ely.by
EMAILS_RENDERER_HOST=http://emails-renderer:3000 EMAILS_RENDERER_HOST=http://emails-renderer:3000
## Security params ## Security params
JWT_USER_SECRET=replace_me_for_production
JWT_ENCRYPTION_KEY=thisisadummyvalue32latterslength JWT_ENCRYPTION_KEY=thisisadummyvalue32latterslength
JWT_PRIVATE_KEY_PATH= JWT_PRIVATE_KEY_PATH=
JWT_PRIVATE_KEY_PASS= JWT_PRIVATE_KEY_PASS=

View File

@ -6,6 +6,11 @@ namespace api\components\Tokens;
use api\components\Tokens\Algorithms\AlgorithmInterface; use api\components\Tokens\Algorithms\AlgorithmInterface;
use Webmozart\Assert\Assert; use Webmozart\Assert\Assert;
/**
* This class is used to hold multiple keys signing mechanisms.
* This may be useful when we change the key signing algorithm to allow during the transition period
* the keys with both algorithms to work simultaneously.
*/
final class AlgorithmsManager { final class AlgorithmsManager {
/** /**

View File

@ -16,15 +16,6 @@ class Component extends BaseComponent {
private const PREFERRED_ALGORITHM = 'ES256'; private const PREFERRED_ALGORITHM = 'ES256';
/**
* @var string
* @deprecated In earlier versions of the application, JWT were signed by a synchronous encryption algorithm.
* Now asynchronous encryption is used instead, and this logic is saved for a transitional period.
* I think it can be safely removed, but I'll not do it yet, because at the time of writing the comment
* there were enough changes in the code already.
*/
public $hmacKey;
/** /**
* @var string * @var string
*/ */
@ -44,7 +35,6 @@ class Component extends BaseComponent {
public function init(): void { public function init(): void {
parent::init(); parent::init();
Assert::notEmpty($this->hmacKey, 'hmacKey must be set');
Assert::notEmpty($this->privateKeyPath, 'privateKeyPath must be set'); Assert::notEmpty($this->privateKeyPath, 'privateKeyPath must be set');
Assert::notEmpty($this->encryptionKey, 'encryptionKey must be set'); Assert::notEmpty($this->encryptionKey, 'encryptionKey must be set');
} }
@ -121,7 +111,6 @@ class Component extends BaseComponent {
private function getAlgorithmManager(): AlgorithmsManager { private function getAlgorithmManager(): AlgorithmsManager {
if ($this->algorithmManager === null) { if ($this->algorithmManager === null) {
$this->algorithmManager = new AlgorithmsManager([ $this->algorithmManager = new AlgorithmsManager([
new Algorithms\HS256($this->hmacKey),
new Algorithms\ES256("file://{$this->privateKeyPath}", $this->privateKeyPass), new Algorithms\ES256("file://{$this->privateKeyPath}", $this->privateKeyPass),
]); ]);
} }

View File

@ -2,7 +2,6 @@
return [ return [
'components' => [ 'components' => [
'tokens' => [ 'tokens' => [
'hmacKey' => 'tests-secret-key',
'privateKeyPath' => codecept_data_dir('certs/private.pem'), 'privateKeyPath' => codecept_data_dir('certs/private.pem'),
'privateKeyPass' => null, 'privateKeyPass' => null,
'encryptionKey' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'encryptionKey' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',

View File

@ -31,7 +31,6 @@ return [
], ],
'tokens' => [ 'tokens' => [
'class' => api\components\Tokens\Component::class, 'class' => api\components\Tokens\Component::class,
'hmacKey' => getenv('JWT_USER_SECRET'),
'privateKeyPath' => getenv('JWT_PRIVATE_KEY_PATH') ?: __DIR__ . '/../../data/certs/private.pem', 'privateKeyPath' => getenv('JWT_PRIVATE_KEY_PATH') ?: __DIR__ . '/../../data/certs/private.pem',
'privateKeyPass' => getenv('JWT_PRIVATE_KEY_PASS') ?: null, 'privateKeyPass' => getenv('JWT_PRIVATE_KEY_PASS') ?: null,
'encryptionKey' => getenv('JWT_ENCRYPTION_KEY'), 'encryptionKey' => getenv('JWT_ENCRYPTION_KEY'),

View File

@ -95,6 +95,25 @@ class GetCest {
} }
public function testGetInfoWithExpiredToken(FunctionalTester $I) { public function testGetInfoWithExpiredToken(FunctionalTester $I) {
// We're setting up a known expired token
$I->amBearerAuthenticated(
'eyJhbGciOiJFUzI1NiJ9.eyJpYXQiOjE0NjQ2Mjc1NDUsImV4cCI6MTQ2NDYzMTE0NSwic3ViIjoiZWx5fDEiLCJlbHktc2NvcGVzIjoi' .
'YWNjb3VudHNfd2ViX3VzZXIifQ.m9Di3MC1SkF0dwKP0zIw1Hl0H2mB3PqwoRCXfoF0VuIQnnMurkmJoxa3A02B1zolmCPy3Wd1wKvJz3' .
'TMpKJY2g',
);
$this->route->get(1);
$I->canSeeResponseCodeIs(401);
$I->canSeeResponseIsJson();
$I->canSeeResponseContainsJson([
'name' => 'Unauthorized',
'message' => 'Token expired',
'code' => 0,
'status' => 401,
]);
}
public function testGetInfoWithTokenWithOutdatedAlg(FunctionalTester $I) {
// We're setting up a known expired token // We're setting up a known expired token
$I->amBearerAuthenticated( $I->amBearerAuthenticated(
'eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NjQ2Mjc1NDUsImV4cCI6MTQ2NDYzMTE0NSwic3ViIjoiZWx5fDEiLCJlbHktc' . 'eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NjQ2Mjc1NDUsImV4cCI6MTQ2NDYzMTE0NSwic3ViIjoiZWx5fDEiLCJlbHktc' .
@ -106,7 +125,7 @@ class GetCest {
$I->canSeeResponseIsJson(); $I->canSeeResponseIsJson();
$I->canSeeResponseContainsJson([ $I->canSeeResponseContainsJson([
'name' => 'Unauthorized', 'name' => 'Unauthorized',
'message' => 'Token expired', 'message' => 'Incorrect token',
'code' => 0, 'code' => 0,
'status' => 401, 'status' => 401,
]); ]);

View File

@ -40,10 +40,6 @@ class ComponentTest extends TestCase {
} }
public function testParse() { public function testParse() {
// Valid token signed with HS256
$token = $this->component->parse('eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1NjQ1Mjc0NzYsImV4cCI6MTU2NDUzMTA3Niwic3ViIjoiZWx5fDEiLCJqdGkiOjMwNjk1OTJ9.ixapBbhaUCejbcPTnFi5nqk75XKd1_lQJd1ZPgGTLEc');
$this->assertValidParsedToken($token, 'HS256');
// Valid token signed with ES256 // Valid token signed with ES256
$token = $this->component->parse('eyJhbGciOiJFUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1NjQ1Mjc0NzYsImV4cCI6MTU2NDUzMTA3Niwic3ViIjoiZWx5fDEiLCJqdGkiOjMwNjk1OTJ9.M8Kam9bv0BXui3k7Posq_vc0I95Kb_Tw7L2vPdEPlwsHqh1VJHoWtlQc32_SlsotttL7j6RYbffBkRFX2wDGFQ'); $token = $this->component->parse('eyJhbGciOiJFUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1NjQ1Mjc0NzYsImV4cCI6MTU2NDUzMTA3Niwic3ViIjoiZWx5fDEiLCJqdGkiOjMwNjk1OTJ9.M8Kam9bv0BXui3k7Posq_vc0I95Kb_Tw7L2vPdEPlwsHqh1VJHoWtlQc32_SlsotttL7j6RYbffBkRFX2wDGFQ');
$this->assertValidParsedToken($token, 'ES256'); $this->assertValidParsedToken($token, 'ES256');
@ -65,10 +61,6 @@ class ComponentTest extends TestCase {
} }
public function getVerifyCases() { public function getVerifyCases() {
yield 'HS256' => [
(new Parser())->parse('eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1NjQ1Mjc0NzYsImV4cCI6MTU2NDUzMTA3Niwic3ViIjoiZWx5fDEiLCJqdGkiOjMwNjk1OTJ9.ixapBbhaUCejbcPTnFi5nqk75XKd1_lQJd1ZPgGTLEc'),
true,
];
yield 'ES256' => [ yield 'ES256' => [
(new Parser())->parse('eyJhbGciOiJFUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1NjQ1Mjc0NzYsImV4cCI6MTU2NDUzMTA3Niwic3ViIjoiZWx5fDEiLCJqdGkiOjMwNjk1OTJ9.M8Kam9bv0BXui3k7Posq_vc0I95Kb_Tw7L2vPdEPlwsHqh1VJHoWtlQc32_SlsotttL7j6RYbffBkRFX2wDGFQ'), (new Parser())->parse('eyJhbGciOiJFUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1NjQ1Mjc0NzYsImV4cCI6MTU2NDUzMTA3Niwic3ViIjoiZWx5fDEiLCJqdGkiOjMwNjk1OTJ9.M8Kam9bv0BXui3k7Posq_vc0I95Kb_Tw7L2vPdEPlwsHqh1VJHoWtlQc32_SlsotttL7j6RYbffBkRFX2wDGFQ'),
true, true,