]> BookStack Code Mirror - bookstack/blob - app/Access/Oidc/OidcUserDetails.php
Add optional OIDC avatar fetching from the “picture” claim
[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         public ?string $picture = null,
15     ) {
16     }
17
18     /**
19      * Check if the user details are fully populated for our usage.
20      */
21     public function isFullyPopulated(bool $groupSyncActive): bool
22     {
23         $hasEmpty = empty($this->externalId)
24             || empty($this->email)
25             || empty($this->name)
26             || ($groupSyncActive && $this->groups === null);
27
28         return !$hasEmpty;
29     }
30
31     /**
32      * Populate user details from the given claim data.
33      */
34     public function populate(
35         ProvidesClaims $claims,
36         string $idClaim,
37         string $displayNameClaims,
38         string $groupsClaim,
39     ): void {
40         $this->externalId = $claims->getClaim($idClaim) ?? $this->externalId;
41         $this->email = $claims->getClaim('email') ?? $this->email;
42         $this->name = static::getUserDisplayName($displayNameClaims, $claims) ?? $this->name;
43         $this->groups = static::getUserGroups($groupsClaim, $claims) ?? $this->groups;
44         $this->picture    = $claims->getClaim('picture') ?: $this->picture;
45     }
46
47     protected static function getUserDisplayName(string $displayNameClaims, ProvidesClaims $token): string
48     {
49         $displayNameClaimParts = explode('|', $displayNameClaims);
50
51         $displayName = [];
52         foreach ($displayNameClaimParts as $claim) {
53             $component = $token->getClaim(trim($claim)) ?? '';
54             if ($component !== '') {
55                 $displayName[] = $component;
56             }
57         }
58
59         return implode(' ', $displayName);
60     }
61
62     protected static function getUserGroups(string $groupsClaim, ProvidesClaims $token): ?array
63     {
64         if (empty($groupsClaim)) {
65             return null;
66         }
67
68         $groupsList = Arr::get($token->getAllClaims(), $groupsClaim);
69         if (!is_array($groupsList)) {
70             return null;
71         }
72
73         return array_values(array_filter($groupsList, function ($val) {
74             return is_string($val);
75         }));
76     }
77 }