Passed
Push — master ( 5e96c0...23583c )
by Angel Fernando Quiroz
08:21
created

AzureAuthenticator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 7
dl 0
loc 16
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
declare(strict_types=1);
6
7
namespace Chamilo\CoreBundle\Security\Authenticator\OAuth2;
8
9
use Chamilo\CoreBundle\Entity\User;
10
use Chamilo\CoreBundle\Entity\UserAuthSource;
11
use Chamilo\CoreBundle\Helpers\AccessUrlHelper;
12
use Chamilo\CoreBundle\Helpers\AuthenticationConfigHelper;
13
use Chamilo\CoreBundle\Helpers\AzureAuthenticatorHelper;
14
use Chamilo\CoreBundle\Repository\Node\UserRepository;
15
use Chamilo\CoreBundle\Security\Badge\OAuth2Badge;
16
use Doctrine\ORM\EntityManagerInterface;
17
use Doctrine\ORM\NonUniqueResultException;
18
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
19
use League\OAuth2\Client\Token\AccessToken;
20
use Symfony\Component\HttpFoundation\Request;
21
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
22
use Symfony\Component\Routing\RouterInterface;
23
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
24
use TheNetworg\OAuth2\Client\Provider\Azure;
25
26
class AzureAuthenticator extends AbstractAuthenticator
27
{
28
    protected string $providerName = 'azure';
29
30
    public function __construct(
31
        ClientRegistry $clientRegistry,
32
        RouterInterface $router,
33
        UserRepository $userRepository,
34
        AuthenticationConfigHelper $authenticationConfigHelper,
35
        AccessUrlHelper $urlHelper,
36
        EntityManagerInterface $entityManager,
37
        private readonly AzureAuthenticatorHelper $azureHelper,
38
    ) {
39
        parent::__construct(
40
            $clientRegistry,
41
            $router,
42
            $userRepository,
43
            $authenticationConfigHelper,
44
            $urlHelper,
45
            $entityManager
46
        );
47
    }
48
49
    public function supports(Request $request): ?bool
50
    {
51
        return 'chamilo.oauth2_azure_check' === $request->attributes->get('_route');
52
    }
53
54
    /**
55
     * @throws NonUniqueResultException
56
     */
57
    protected function userLoader(AccessToken $accessToken): User
58
    {
59
        /** @var Azure $provider */
60
        $provider = $this->client->getOAuth2Provider();
61
62
        $me = $provider->get(
63
            \sprintf('/v1.0/me?$select=%s', implode(',', AzureAuthenticatorHelper::QUERY_USER_FIELDS)),
64
            $accessToken
65
        );
66
67
        if (empty($me['mail'])) {
68
            throw new UnauthorizedHttpException('The mail field is empty in Azure AD and is needed to set the organisation email for this user.');
69
        }
70
71
        if (empty($me['mailNickname'])) {
72
            throw new UnauthorizedHttpException('The mailNickname field is empty in Azure AD and is needed to set the unique username for this user.');
73
        }
74
75
        if (empty($me['id'])) {
76
            throw new UnauthorizedHttpException('The id field is empty in Azure AD and is needed to set the unique Azure ID for this user.');
77
        }
78
79
        $providerParams = $this->authenticationConfigHelper->getProviderConfig($this->providerName);
80
81
        $user = $this->azureHelper->registerUser($me);
82
83
        $roleActions = $this->azureHelper->getUpdateActionByRole();
84
85
        if ($roleActions) {
0 ignored issues
show
introduced by
$roleActions is a non-empty array, thus is always true.
Loading history...
Bug Best Practice introduced by
The expression $roleActions of type array<string,callable> is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
86
            $azureGroups = $provider->get('/v1.0/me/memberOf', $accessToken);
87
88
            foreach ($providerParams['group_id'] as $userRole => $groupUid) {
89
                if (empty($groupUid)) {
90
                    continue;
91
                }
92
93
                foreach ($azureGroups as $azureGroup) {
94
                    $azureGroupUid = $azureGroup['id'];
95
                    if ($azureGroupUid === $groupUid) {
96
                        $roleActions[$userRole]($user);
97
98
                        break 2;
99
                    }
100
                }
101
            }
102
103
            $this->entityManager->flush();
104
        }
105
106
        return $user;
107
    }
108
109
    protected function getCustomBadge(): ?BadgeInterface
110
    {
111
        return new Oauth2Badge(UserAuthSource::AZURE);
112
    }
113
}
114