Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
75.56% covered (warning)
75.56%
34 / 45
53.85% covered (warning)
53.85%
7 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
AuthenticatedUser
75.56% covered (warning)
75.56%
34 / 45
53.85% covered (warning)
53.85%
7 / 13
27.44
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 base64UrlDecode
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 fromJwtPayload
94.12% covered (success)
94.12%
16 / 17
0.00% covered (danger)
0.00%
0 / 1
7.01
 getExternalUserId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setExternalUserId
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getEmail
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setEmail
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getGivenName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setGivenName
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getFamilyName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setFamilyName
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 toArray
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 jsonSerialize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace BO\Zmscitizenapi\Models;
6
7use BO\Zmscitizenapi\Exceptions\InvalidAuthTokenException;
8use JsonSerializable;
9
10class AuthenticatedUser implements JsonSerializable
11{
12    private ?string $externalUserId;
13    private ?string $email;
14    private ?string $givenName;
15    private ?string $familyName;
16
17    public function __construct(
18        ?string $externalUserId = null,
19        ?string $email = null,
20        ?string $givenName = null,
21        ?string $familyName = null,
22    ) {
23        $this->externalUserId = $externalUserId;
24        $this->email = $email;
25        $this->givenName = $givenName;
26        $this->familyName = $familyName;
27    }
28
29    private static function base64UrlDecode(string $data): string
30    {
31        $replaced = strtr($data, '-_', '+/');
32        $pad = strlen($replaced) % 4;
33        if ($pad) {
34            $replaced .= str_repeat('=', 4 - $pad);
35        }
36        return base64_decode($replaced) ?: '';
37    }
38
39    public static function fromJwtPayload(?string $token): ?self
40    {
41        // Token is validated in API gateway
42        if (is_null($token)) {
43            return null;
44        }
45        $tokenParts = explode('.', $token);
46        if (count($tokenParts) !== 3) {
47            throw new InvalidAuthTokenException('authKeyMismatch', 'Invalid JWT payload.');
48        }
49        $payload = json_decode(self::base64UrlDecode($tokenParts[1]), true);
50
51        $instance = new self();
52        if (empty($payload[\App::ZMS_CITIZENLOGIN_EXTERNALUSERID_CLAIM_NAME])) {
53            throw new InvalidAuthTokenException('authKeyMismatch', 'Property `' . \App::ZMS_CITIZENLOGIN_EXTERNALUSERID_CLAIM_NAME . '` is missing from the JWT payload.');
54        }
55        $instance->setExternalUserId($payload[\App::ZMS_CITIZENLOGIN_EXTERNALUSERID_CLAIM_NAME]);
56        if (!empty($payload['email'])) {
57            $instance->setEmail($payload['email']);
58        }
59        if (!empty($payload['given_name'])) {
60            $instance->setGivenName($payload['given_name']);
61        }
62        if (!empty($payload['family_name'])) {
63            $instance->setFamilyName($payload['family_name']);
64        }
65        return $instance;
66    }
67
68    public function getExternalUserId(): ?string
69    {
70        return $this->externalUserId;
71    }
72
73    public function setExternalUserId(?string $externalUserId): self
74    {
75        $this->externalUserId = $externalUserId;
76        return $this;
77    }
78
79    public function getEmail(): ?string
80    {
81        return $this->email;
82    }
83
84    public function setEmail(?string $email): self
85    {
86        $this->email = $email;
87        return $this;
88    }
89
90    public function getGivenName(): ?string
91    {
92        return $this->givenName;
93    }
94
95    public function setGivenName(?string $givenName): self
96    {
97        $this->givenName = $givenName;
98        return $this;
99    }
100
101    public function getFamilyName(): ?string
102    {
103        return $this->familyName;
104    }
105
106    public function setFamilyName(?string $familyName): self
107    {
108        $this->familyName = $familyName;
109        return $this;
110    }
111
112    public function toArray(): array
113    {
114        return [
115            'external_user_id' => $this->externalUserId,
116            'email' => $this->email,
117            'given_name' => $this->givenName,
118            'family_name' => $this->familyName,
119        ];
120    }
121
122    public function jsonSerialize(): mixed
123    {
124        return $this->toArray();
125    }
126}