Issues (28)

src/Security/GitlabAuthenticator.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace App\Security;
4
5
use Doctrine\ODM\MongoDB\DocumentManager;
6
use Omines\OAuth2\Client\Provider\Gitlab;
7
use Omines\OAuth2\Client\Provider\GitlabResourceOwner;
8
use Symfony\Component\HttpFoundation\RedirectResponse;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\Routing\RouterInterface;
11
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
12
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
13
use Symfony\Component\Security\Core\Exception\AuthenticationException;
14
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
15
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
16
use Symfony\Component\Security\Core\User\UserInterface;
17
use Symfony\Component\Security\Core\User\UserProviderInterface;
18
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
19
use Symfony\Component\Security\Http\Util\TargetPathTrait;
20
21
class GitlabAuthenticator extends AbstractGuardAuthenticator
22
{
23
    use TargetPathTrait;
24
25
    /**
26
     * @var Gitlab
27
     */
28
    private $gitlab;
29
30
    /**
31
     * @var RouterInterface
32
     */
33
    private $router;
34
35
    /**
36
     * @var DocumentManager
37
     */
38
    private $manager;
39
40
    /**
41
     * @var string
42
     */
43
    private $gitlabDefaultRole;
44
45
    public function __construct(RouterInterface $router, DocumentManager $manager, $gitlabDomain, $gitlabClientId, $gitlabClientSecret, $gitlabDefaultRole)
46
    {
47
        $this->router = $router;
48
        $this->manager = $manager;
49
        $this->gitlabDefaultRole = $gitlabDefaultRole;
50
        $this->gitlab = new Gitlab([
51
            'clientId' => $gitlabClientId,
52
            'clientSecret' => $gitlabClientSecret,
53
            'redirectUri' => $this->router->generate('gitlab_login', [], RouterInterface::ABSOLUTE_URL),
54
            'domain' => $gitlabDomain,
55
        ]);
56
    }
57
58
    public function start(Request $request, AuthenticationException $authException = null)
59
    {
60
    }
61
62
    public function supports(Request $request)
63
    {
64
        return 'gitlab_login' === $request->attributes->get('_route')
65
            && $this->gitlab->domain;
66
    }
67
68
    public function getCredentials(Request $request)
69
    {
70
        $code = $request->query->get('code');
71
72
        if (!$code) {
73
            throw new AuthenticationCredentialsNotFoundException();
74
        }
75
76
        $state = $request->query->get('state');
77
        if (!$state || $state !== $request->getSession()->get('oauth2state')) {
78
            throw new CustomUserMessageAuthenticationException('Invalid state.');
79
        }
80
81
        return ['code' => $code];
82
    }
83
84
    public function getUser($credentials, UserProviderInterface $userProvider)
85
    {
86
        $token = $this->gitlab->getAccessToken('authorization_code', [
87
            'code' => $credentials['code'],
88
        ]);
89
90
        try {
91
            /** @var GitlabResourceOwner $gitlabUser */
92
            $gitlabUser = $this->gitlab->getResourceOwner($token);
93
        } catch (\Exception $e) {
94
            throw new CustomUserMessageAuthenticationException('Gitlab error.');
95
        }
96
97
        try {
98
            $user = $userProvider->loadUserByUsername($gitlabUser->getUsername());
99
        } catch (UsernameNotFoundException $e) {
100
            $user = $this->manager->getRepository('App:User')->createFromGitlab($gitlabUser, $this->gitlabDefaultRole);
101
        }
102
103
        return $user;
104
    }
105
106
    public function checkCredentials($credentials, UserInterface $user)
107
    {
108
        return true;
109
    }
110
111
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
112
    {
113
        if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
0 ignored issues
show
It seems like $request->getSession() can also be of type null; however, parameter $session of App\Security\GitlabAuthenticator::getTargetPath() does only seem to accept Symfony\Component\HttpFo...ession\SessionInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

113
        if ($targetPath = $this->getTargetPath(/** @scrutinizer ignore-type */ $request->getSession(), $providerKey)) {
Loading history...
114
            return new RedirectResponse($targetPath);
115
        }
116
117
        return new RedirectResponse($this->router->generate('home'));
118
    }
119
120
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
121
    {
122
        if ($exception instanceof AuthenticationCredentialsNotFoundException) {
123
            $url = $this->gitlab->getAuthorizationUrl();
124
            $request->getSession()->set('oauth2state', $this->gitlab->getState());
125
126
            return new RedirectResponse($url);
127
        }
128
129
        throw $exception;
130
    }
131
132
    public function supportsRememberMe()
133
    {
134
        return false;
135
    }
136
}
137