Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Provider
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 7
182
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 setHttpClient
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 createResourceOwner
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getResourceOwnerData
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
30
 getOptionsFromJsonFile
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getBasicOptionsFromJsonFile
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 readKeycloakConfig
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace BO\Slim\Middleware\OAuth\Keycloak;
4
5use Stevenmaguire\OAuth2\Client\Provider\Keycloak;
6use BO\Zmsclient\OAuthService;
7use BO\Zmsclient\Psr7\Client;
8use League\OAuth2\Client\Token\AccessToken;
9use BO\Zmsentities\Useraccount;
10
11/**
12 * @SuppressWarnings(PHPMD)
13 */
14class Provider extends Keycloak
15{
16    const string PROVIDERNAME = 'keycloak';
17
18    protected OAuthService $oauthService;
19
20    public function __construct(mixed $client = null, ?OAuthService $oauthService = null)
21    {
22        $this->oauthService = $oauthService ?? new OAuthService(\App::$http, \App::CONFIG_SECURE_TOKEN);
23        $client = $client ?? new Client();
24        $options = $this->getOptionsFromJsonFile();
25        parent::__construct($options, ['httpClient' => $client]);
26    }
27
28    #[\Override]
29    public function setHttpClient($client)
30    {
31        $this->httpClient = $client;
32        return $this;
33    }
34
35    #[\Override]
36    protected function createResourceOwner(array $response, AccessToken $token): ResourceOwner
37    {
38        return new ResourceOwner($response);
39    }
40
41    public function getResourceOwnerData(AccessToken $token): Useraccount
42    {
43        $resourceOwner = $this->getResourceOwner($token);
44        $config = $this->oauthService->readConfig();
45        $ownerData = [
46            'username' => ($resourceOwner->getName() ?? '') . '@' . static::PROVIDERNAME,
47        ];
48        if (1 == $config->getPreference('oidc', 'onlyVerifiedMail')) {
49            $email = $resourceOwner->getEmail();
50            $ownerArray = $resourceOwner->toArray();
51            $emailVerified = $ownerArray['email_verified'] ?? false;
52            if (is_string($email) && $email !== '' && $emailVerified === true) {
53                $ownerData['email'] = $email;
54            }
55        } else {
56            $ownerData['email'] = $resourceOwner->getEmail();
57        }
58        return new Useraccount($ownerData);
59    }
60
61    private function getOptionsFromJsonFile(): array
62    {
63        $configData = $this->readKeycloakConfig();
64        $realmData = $this->getBasicOptionsFromJsonFile();
65        $realmData['clientSecret'] = $configData['credentials']['secret'] ?? '';
66        $realmData['authServerUrl'] = $configData['auth-server-url'] ?? '';
67        $realmData['verify'] = $configData['ssl-verify'] ?? true;
68        return $realmData;
69    }
70
71    public function getBasicOptionsFromJsonFile(): array
72    {
73        $configData = $this->readKeycloakConfig();
74        return [
75            'realm' => $configData['realm'] ?? '',
76            'clientId' => $configData['clientId'] ?? '',
77            'clientName' => $configData['clientName'] ?? '',
78            'redirectUri' => $configData['auth-redirect-url'] ?? '',
79            'logoutUri' => $configData['logout-redirect-url'] ?? '',
80            'version' => $configData['version'] ?? '',
81            'accessRole' => $configData['access-role'] ?? '',
82        ];
83    }
84
85    /**
86     * @return array<string, mixed>
87     */
88    private function readKeycloakConfig(): array
89    {
90        $configJson = file_get_contents(\App::APP_PATH . '/' . static::PROVIDERNAME . '.json');
91        if (!is_string($configJson)) {
92            throw new \RuntimeException('Unable to read keycloak.json');
93        }
94        $configData = json_decode($configJson, true);
95        if (!is_array($configData)) {
96            throw new \RuntimeException('Invalid keycloak.json');
97        }
98        return $configData;
99    }
100}