Completed
Push — master ( 54e145...229a32 )
by Artem
04:30
created

AbstractOAuth2Authenticator::supportsRememberMe()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
//----------------------------------------------------------------------
4
//
5
//  Copyright (C) 2017 Artem Rodygin
6
//
7
//  You should have received a copy of the MIT License along with
8
//  this file. If not, see <http://opensource.org/licenses/MIT>.
9
//
10
//----------------------------------------------------------------------
11
12
namespace Pignus\Authenticator;
13
14
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
15
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
16
use Symfony\Component\HttpFoundation\RedirectResponse;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\HttpFoundation\Session\SessionInterface;
20
use Symfony\Component\Routing\RouterInterface;
21
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
22
use Symfony\Component\Security\Core\Exception\AuthenticationException;
23
use Symfony\Component\Security\Core\User\UserInterface;
24
use Symfony\Component\Security\Core\User\UserProviderInterface;
25
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
26
27
/**
28
 * Authenticates user against OAuth2 server.
29
 */
30
abstract class AbstractOAuth2Authenticator extends AbstractGuardAuthenticator
31
{
32
    protected $router;
33
    protected $session;
34
    protected $firewalls;
35
36
    /**
37
     * Dependency Injection constructor.
38
     *
39
     * @param RouterInterface  $router
40
     * @param SessionInterface $session
41
     * @param FirewallMap      $firewalls
42
     */
43 14
    public function __construct(
44
        RouterInterface  $router,
45
        SessionInterface $session,
46
        FirewallMap      $firewalls)
47
    {
48 14
        $this->router    = $router;
49 14
        $this->session   = $session;
50 14
        $this->firewalls = $firewalls;
51 14
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56 2
    public function start(Request $request, AuthenticationException $authException = null)
57
    {
58
        // Do not redirect the user if it's an AJAX request.
59 2
        if ($request->isXmlHttpRequest()) {
60 1
            return new Response('Authentication required.', Response::HTTP_UNAUTHORIZED);
61
        }
62
63 1
        $firewall = $this->firewalls->getFirewallConfig($request)->getName();
64 1
        $statevar = $firewall . '@' . static::class;
65
66 1
        $provider = $this->getProvider($this->router, $firewall);
67 1
        $authUrl  = $provider->getAuthorizationUrl();
68
69 1
        $this->session->set($statevar, $provider->getState());
70
71 1
        return new RedirectResponse($authUrl);
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77 5
    public function getCredentials(Request $request)
78
    {
79 5
        $code  = $request->query->get('code');
80 5
        $state = $request->query->get('state');
81
82 5
        if (!$code && !$state) {
83 1
            return null;
84
        }
85
86 4
        if (!$code || !$state) {
87 2
            throw new AuthenticationException('Bad credentials.');
88
        }
89
90 2
        $firewall = $this->firewalls->getFirewallConfig($request)->getName();
91 2
        $statevar = $firewall . '@' . static::class;
92
93 2
        if ($state !== $this->session->get($statevar)) {
94 1
            $this->session->remove($statevar);
95
96 1
            return null;
97
        }
98
99
        return [
100 1
            'firewall' => $firewall,
101 1
            'code'     => $code,
102
        ];
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108 2
    public function getUser($credentials, UserProviderInterface $userProvider)
109
    {
110
        try {
111 2
            $provider = $this->getProvider($this->router, $credentials['firewall']);
112
113 2
            $token = $provider->getAccessToken('authorization_code', [
114 2
                'code' => $credentials['code'],
115
            ]);
116
117 2
            $owner = $provider->getResourceOwner($token);
118 2
            $user  = $this->getUserFromResourceOwner($owner);
119
120 2
            if ($user === null) {
121 1
                throw new AuthenticationException('Bad credentials.');
122
            }
123
124 1
            return $user;
125
        }
126 1
        catch (\Exception $e) {
127 1
            throw new AuthenticationException($e->getMessage());
128
        }
129
    }
130
131
    /**
132
     * {@inheritdoc}
133
     */
134 1
    public function checkCredentials($credentials, UserInterface $user)
135
    {
136 1
        return true;
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142 2
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
143
    {
144
        // An URL the user was trying to reach before authentication.
145 2
        $targetPath = sprintf('_security.%s.target_path', $providerKey);
146 2
        $targetUrl  = $this->session->get($targetPath, '/');
147
148
        // Do not redirect the user if it's an AJAX request.
149 2
        return $request->isXmlHttpRequest()
150
            ? null
151 2
            : new RedirectResponse($targetUrl);
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157 1
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
158
    {
159 1
        return new Response('Authentication required.', Response::HTTP_UNAUTHORIZED);
160
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165 1
    public function supportsRememberMe()
166
    {
167 1
        return false;
168
    }
169
170
    /**
171
     * Returns OAuth2 provider for the specified firewall.
172
     *
173
     * @param RouterInterface $router
174
     * @param string          $firewall
175
     *
176
     * @return \League\OAuth2\Client\Provider\AbstractProvider
177
     */
178
    abstract protected function getProvider(RouterInterface $router, string $firewall);
179
180
    /**
181
     * Returns user entity based on specified OAuth2 account.
182
     *
183
     * @param ResourceOwnerInterface $owner
184
     *
185
     * @return UserInterface|null
186
     */
187
    abstract protected function getUserFromResourceOwner(ResourceOwnerInterface $owner);
188
}
189