]> BookStack Code Mirror - bookstack/blob - app/Access/Oidc/OidcUserDetails.php
OIDC: Extracted user detail handling to own OidcUserDetails class
[bookstack] / app / Access / Oidc / OidcUserDetails.php
1 <?php
2
3 namespace BookStack\Access\Oidc;
4
5 use Illuminate\Support\Arr;
6
7 class OidcUserDetails
8 {
9     public function __construct(
10         public ?string $externalId = null,
11         public ?string $email = null,
12         public ?string $name = null,
13         public ?array $groups = null,
14     ) {
15     }
16
17     /**
18      * Check if the user details are fully populated for our usage.
19      */
20     public function isFullyPopulated(bool $groupSyncActive): bool
21     {
22         $hasEmpty = empty($this->externalId)
23             || empty($this->email)
24             || empty($this->name)
25             || ($groupSyncActive && empty($this->groups));
26
27         return !$hasEmpty;
28     }
29
30     /**
31      * Populate user details from OidcIdToken data.
32      */
33     public static function fromToken(
34         OidcIdToken $token,
35         string $idClaim,
36         string $displayNameClaims,
37         string $groupsClaim,
38     ): static {
39         $id = $token->getClaim($idClaim);
40
41         return new self(
42             externalId: $id,
43             email: $token->getClaim('email'),
44             name: static::getUserDisplayName($displayNameClaims, $token, $id),
45             groups: static::getUserGroups($groupsClaim, $token),
46         );
47     }
48
49     protected static function getUserDisplayName(string $displayNameClaims, OidcIdToken $token, string $defaultValue): string
50     {
51         $displayNameClaimParts = explode('|', $displayNameClaims);
52
53         $displayName = [];
54         foreach ($displayNameClaimParts as $claim) {
55             $component = $token->getClaim(trim($claim)) ?? '';
56             if ($component !== '') {
57                 $displayName[] = $component;
58             }
59         }
60
61         if (count($displayName) === 0) {
62             $displayName[] = $defaultValue;
63         }
64
65         return implode(' ', $displayName);
66     }
67
68     protected static function getUserGroups(string $groupsClaim, OidcIdToken $token): array
69     {
70         if (empty($groupsClaim)) {
71             return [];
72         }
73
74         $groupsList = Arr::get($token->getAllClaims(), $groupsClaim);
75         if (!is_array($groupsList)) {
76             return [];
77         }
78
79         return array_values(array_filter($groupsList, function ($val) {
80             return is_string($val);
81         }));
82     }
83 }