-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJwtTokenizer.php
99 lines (84 loc) · 3.32 KB
/
JwtTokenizer.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?php
// SPDX-License-Identifier: BSD-3-Clause
declare(strict_types=1);
namespace SingleA\Bundles\Jwt;
use Jose\Bundle\JoseFramework\Services\JWSBuilderFactory;
use Jose\Bundle\JoseFramework\Services\NestedTokenBuilderFactory;
use Jose\Component\Signature;
use SingleA\Bundles\Jwt\FeatureConfig\JwtTokenizerConfig;
use SingleA\Contracts\Tokenization\TokenizerConfigInterface;
use SingleA\Contracts\Tokenization\TokenizerInterface;
final class JwtTokenizer implements TokenizerInterface
{
private Signature\Serializer\CompactSerializer $jwsSerializer;
public function __construct(
private readonly string $issuer,
private readonly JWSBuilderFactory $jwsBuilderFactory,
private readonly NestedTokenBuilderFactory $nestedTokenBuilderFactory,
) {
$this->jwsSerializer = new Signature\Serializer\CompactSerializer();
}
public function supports(string|TokenizerConfigInterface $config): bool
{
return is_a($config, JwtTokenizerConfig::class, true);
}
/**
* @psalm-suppress MixedAssignment
*/
public function tokenize(string $subject, array $payload, TokenizerConfigInterface $config): string
{
if (!($config instanceof JwtTokenizerConfig)) {
throw new \InvalidArgumentException('Unsupported config specified.');
}
// Add standard JWT payload fields unless its specified.
$payload['sub'] ??= $subject;
$payload['iat'] ??= time();
$payload['nbf'] ??= time();
$payload['exp'] ??= time() + ($config->getTtl() ?? 0);
$payload['iss'] ??= $this->issuer;
if ($config->getAudience()) {
$payload['aud'] ??= $config->getAudience();
}
$jwsConfig = $config->getJwsConfig();
$jweConfig = $config->getJweConfig();
if ($jweConfig === null) {
$jws = $this->jwsBuilderFactory->create([$jwsConfig->getAlgorithm()])
->withPayload(json_encode($payload, \JSON_THROW_ON_ERROR)) // @phan-suppress-current-line PhanPossiblyFalseTypeArgument
->addSignature($jwsConfig->getJwk(), [
'alg' => $jwsConfig->getAlgorithm(),
'typ' => 'JWT',
])
->build()
;
return $this->jwsSerializer->serialize($jws);
}
$builder = $this->nestedTokenBuilderFactory->create(
['jwe_compact'],
[$jweConfig->getKeyAlgorithm()],
[$jweConfig->getContentAlgorithm()],
$jweConfig->getCompression() !== null ? [$jweConfig->getCompression()] : [],
['jws_compact'],
[$jwsConfig->getAlgorithm()],
);
return $builder->create(
json_encode($payload, \JSON_THROW_ON_ERROR), // @phan-suppress-current-line PhanPossiblyFalseTypeArgument
[[
'key' => $jwsConfig->getJwk(),
'protected_header' => [
'alg' => $jwsConfig->getAlgorithm(),
'typ' => 'JWT',
],
]],
'jws_compact',
[
'alg' => $jweConfig->getKeyAlgorithm(),
'enc' => $jweConfig->getContentAlgorithm(),
],
[],
[[
'key' => $jweConfig->getRecipientJwk(),
]],
'jwe_compact',
);
}
}