OAuth2AuthentificationProvider::checkUser()   A
last analyzed

Complexity

Conditions 3
Paths 5

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
c 0
b 0
f 0
rs 9.4285
cc 3
eloc 8
nc 5
nop 1
1
<?php
2
3
namespace TH\OAuth2;
4
5
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
6
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
7
use Symfony\Component\Security\Core\User\UserCheckerInterface;
8
use Symfony\Component\Security\Core\User\UserInterface;
9
use Symfony\Component\Security\Core\User\UserProviderInterface;
10
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
11
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
12
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
13
use Symfony\Component\Security\Core\Role\SwitchUserRole;
14
15
class OAuth2AuthentificationProvider implements AuthenticationProviderInterface
16
{
17
    /** @var UserProviderInterface  */
18
    private $userProvider;
19
20
    /** @var  UserCheckerInterface */
21
    private $userChecker;
22
23
    private $providerKey;
24
25
    private $hideUserNotFoundExceptions;
26
27
    public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, $hideUserNotFoundExceptions = true)
28
    {
29
        $this->userProvider = $userProvider;
30
        $this->userChecker = $userChecker;
31
        $this->providerKey = $providerKey;
32
        $this->hideUserNotFoundExceptions = $hideUserNotFoundExceptions;
33
    }
34
35
    public function supports(TokenInterface $token)
36
    {
37
        return $token instanceof OAuth2Token && $token->getProviderKey() == $this->providerKey;
38
    }
39
40
    public function authenticate(TokenInterface $token)
41
    {
42
        $user = null;
43
        if (!$this->supports($token)) {
44
            return;
45
        }
46
47
        $username = $token->getUsername();
48
        if (!empty($username)) {
49
50
            $user = $this->retrieveUser($username, $token);
51
52
            if (!$user instanceof UserInterface) {
53
                throw new AuthenticationServiceException('retrieveUser() must return a UserInterface.');
54
            }
55
56
            $this->checkUser($user);
57
        }
58
59
        return $this->authenticatedToken($token, $user);
60
    }
61
62
    private function authenticatedToken(TokenInterface $token, UserInterface $user = null)
63
    {
64
        if (!$token instanceof OAuth2Token) {
65
            throw new Exception ("token should be instance of OAuth2Token");
66
        }
67
68
        $authenticatedToken = new OAuth2Token(
69
            $token->getClient(),
70
            $user,
71
            $token->getCredentials(),
72
            $this->providerKey,
73
            $this->getRoles($token, $user),
74
            $token->hasAttribute('scopes') ? $token->getAttribute('scopes') : []
75
        );
76
        $authenticatedToken->setAttributes($token->getAttributes());
77
78
        return $authenticatedToken;
79
    }
80
81
    /**
82
     * @param string $username
83
     */
84
    private function retrieveUser($username, TokenInterface $token)
85
    {
86
        $user = $token->getUser();
87
        if ($user instanceof UserInterface) {
88
            return $user;
89
        }
90
91
        try {
92
            return $this->getUser($username);
93
        } catch (UsernameNotFoundException $notFound) {
94
            $this->hideUserNotFoundExceptions($notFound, $username);
95
        } catch (\Exception $repositoryProblem) {
96
            $ex = new AuthenticationServiceException($repositoryProblem->getMessage(), 0, $repositoryProblem);
97
            $ex->setToken($token);
98
            throw $ex;
99
        }
100
    }
101
102
    /**
103
     * @param string $username
104
     */
105
    private function hideUserNotFoundExceptions(UsernameNotFoundException $notFound, $username)
106
    {
107
        if ($this->hideUserNotFoundExceptions) {
108
            throw new BadCredentialsException('Bad credentials.', 0, $notFound);
109
        }
110
        $notFound->setUsername($username);
111
        throw $notFound;
112
    }
113
114
    private function getRoles(TokenInterface $token, UserInterface $user = null)
115
    {
116
        if (null === $user) {
117
            return [];
118
        }
119
120
        $roles = $user->getRoles();
121
122
        foreach ($token->getRoles() as $role) {
123
            if ($role instanceof SwitchUserRole) {
124
                $roles[] = $role;
125
126
                break;
127
            }
128
        }
129
130
        return $roles;
131
    }
132
133
    /**
134
     * @param string $username
135
     */
136
    private function getUser($username)
137
    {
138
        $user = $this->userProvider->loadUserByUsername($username);
139
140
        if (!$user instanceof UserInterface) {
141
            throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
142
        }
143
144
        return $user;
145
    }
146
147
148
    private function checkUser(UserInterface $user)
149
    {
150
        try {
151
            $this->userChecker->checkPreAuth($user);
152
            $this->userChecker->checkPostAuth($user);
153
        } catch (BadCredentialsException $e) {
154
            if ($this->hideUserNotFoundExceptions) {
155
                throw new BadCredentialsException('Bad credentials.', 0, $e);
156
            }
157
158
            throw $e;
159
        }
160
    }
161
162
}
163