Passed
Push — master ( 106006...c1ddb5 )
by Thomas Mauro
06:38 queued 11s
created

ClientSecretJwt::getJwsBuilder()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 4.125

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 3
nop 0
dl 0
loc 11
ccs 3
cts 6
cp 0.5
crap 4.125
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace TMV\OpenIdClient\AuthMethod;
6
7
use function array_merge;
8
use function class_exists;
9
use Jose\Component\Core\AlgorithmManager;
10
use Jose\Component\Signature\Algorithm\HS256;
11
use Jose\Component\Signature\JWSBuilder;
12
use Jose\Component\Signature\Serializer\CompactSerializer;
13
use Jose\Component\Signature\Serializer\JWSSerializer;
14
use function json_encode;
15
use function random_bytes;
16
use function time;
17
use function TMV\OpenIdClient\base64url_encode;
18
use TMV\OpenIdClient\Client\ClientInterface as OpenIDClient;
19
use TMV\OpenIdClient\Exception\InvalidArgumentException;
20
use TMV\OpenIdClient\Exception\LogicException;
21
use function TMV\OpenIdClient\jose_secret_key;
22
23
final class ClientSecretJwt extends AbstractJwtAuth
24
{
25
    /** @var null|JWSBuilder */
26
    private $jwsBuilder;
27
28
    /** @var JWSSerializer */
29
    private $jwsSerializer;
30
31
    /**
32
     * ClientSecretJwt constructor.
33
     *
34
     * @param null|JWSBuilder $jwsBuilder
35
     * @param null|JWSSerializer $jwsSerializer
36
     */
37 4
    public function __construct(
38
        ?JWSBuilder $jwsBuilder = null,
39
        ?JWSSerializer $jwsSerializer = null
40
    ) {
41 4
        $this->jwsBuilder = $jwsBuilder;
42 4
        $this->jwsSerializer = $jwsSerializer ?: new CompactSerializer();
43 4
    }
44
45 3
    public function getSupportedMethod(): string
46
    {
47 3
        return 'client_secret_jwt';
48
    }
49
50 1
    private function getJwsBuilder(): JWSBuilder
51
    {
52 1
        if (null !== $this->jwsBuilder) {
53 1
            return $this->jwsBuilder;
54
        }
55
56
        if (! class_exists(HS256::class)) {
57
            throw new LogicException('To use the client_secret_jwt auth method you should install web-token/jwt-signature-algorithm-hmac package');
58
        }
59
60
        return $this->jwsBuilder = new JWSBuilder(new AlgorithmManager([new HS256()]));
61
    }
62
63 2
    protected function createAuthJwt(OpenIDClient $client, array $claims = []): string
64
    {
65 2
        $clientSecret = $client->getMetadata()->getClientSecret();
66
67 2
        if (null === $clientSecret) {
68 1
            throw new InvalidArgumentException($this->getSupportedMethod() . ' cannot be used without client_secret metadata');
69
        }
70
71 1
        $clientId = $client->getMetadata()->getClientId();
72 1
        $issuer = $client->getIssuer();
73 1
        $issuerMetadata = $issuer->getMetadata();
74
75 1
        $jwk = jose_secret_key($clientSecret);
76
77 1
        $time = time();
78 1
        $jti = base64url_encode(random_bytes(32));
79
80
        /** @var string $payload */
81 1
        $payload = json_encode(array_merge(
82 1
            $claims,
83
            [
84 1
                'iss' => $clientId,
85 1
                'sub' => $clientId,
86 1
                'aud' => $issuerMetadata->getIssuer(),
87 1
                'iat' => $time,
88 1
                'exp' => $time + 60,
89 1
                'jti' => $jti,
90
            ]
91
        ));
92
93 1
        $jws = $this->getJwsBuilder()->create()
94 1
            ->withPayload($payload)
95 1
            ->addSignature($jwk, ['alg' => 'HS256', 'jti' => $jti])
96 1
            ->build();
97
98 1
        return $this->jwsSerializer->serialize($jws, 0);
99
    }
100
}
101