Passed
Pull Request — master (#2)
by Pol
16:04
created

CasGuardAuthenticator   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Test Coverage

Coverage 90.91%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 65
c 1
b 0
f 0
dl 0
loc 184
ccs 60
cts 66
cp 0.9091
rs 10
wmc 17

10 Methods

Rating   Name   Duplication   Size   Complexity  
A start() 0 14 2
A onAuthenticationFailure() 0 15 2
A getCredentials() 0 11 2
A __construct() 0 8 1
A checkCredentials() 0 15 3
A onAuthenticationSuccess() 0 9 1
A onLogoutSuccess() 0 7 1
A supports() 0 13 1
A getUser() 0 13 3
A supportsRememberMe() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace EcPhp\CasBundle\Security;
6
7
use EcPhp\CasBundle\Security\Core\User\CasUserProviderInterface;
8
use EcPhp\CasLib\CasInterface;
9
use EcPhp\CasLib\Introspection\Contract\ServiceValidate;
10
use EcPhp\CasLib\Introspection\Introspector;
11
use EcPhp\CasLib\Utils\Uri;
12
use InvalidArgumentException;
13
use Psr\Http\Message\ServerRequestFactoryInterface;
14
use Psr\Http\Message\UriFactoryInterface;
15
use Symfony\Component\HttpFoundation\JsonResponse;
16
use Symfony\Component\HttpFoundation\RedirectResponse;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
20
use Symfony\Component\Security\Core\Exception\AuthenticationException;
21
use Symfony\Component\Security\Core\User\UserInterface;
22
use Symfony\Component\Security\Core\User\UserProviderInterface;
23
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
24
use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
25
26
/**
27
 * Class CasGuardAuthenticator.
28
 */
29
class CasGuardAuthenticator extends AbstractGuardAuthenticator implements LogoutSuccessHandlerInterface
30
{
31
    /**
32
     * The PSR CAS library.
33
     *
34
     * @var \EcPhp\CasLib\CasInterface
35
     */
36
    private $cas;
37
38
    /**
39
     * @var \Psr\Http\Message\ServerRequestFactoryInterface
40
     */
41
    private $serverRequestFactory;
42
43
    /**
44
     * @var \Psr\Http\Message\UriFactoryInterface
45
     */
46
    private $uriFactory;
47
48
    /**
49
     * CasGuardAuthenticator constructor.
50
     *
51
     * @param \EcPhp\CasLib\CasInterface $cas
52
     * @param \Psr\Http\Message\UriFactoryInterface $uriFactory
53
     * @param \Psr\Http\Message\ServerRequestFactoryInterface $serverRequestFactory
54
     */
55 11
    public function __construct(
56
        CasInterface $cas,
57
        UriFactoryInterface $uriFactory,
58
        ServerRequestFactoryInterface $serverRequestFactory
59
    ) {
60 11
        $this->cas = $cas;
61 11
        $this->uriFactory = $uriFactory;
62 11
        $this->serverRequestFactory = $serverRequestFactory;
63 11
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68 1
    public function checkCredentials($credentials, UserInterface $user)
69
    {
70
        try {
71 1
            $introspect = Introspector::detect($credentials);
72 1
        } catch (InvalidArgumentException $exception) {
73 1
            throw new AuthenticationException($exception->getMessage());
74
        }
75
76 1
        if (false === ($introspect instanceof ServiceValidate)) {
77 1
            throw new AuthenticationException(
78 1
                'Failure in the returned response'
79
            );
80
        }
81
82 1
        return true;
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function getCredentials(Request $request)
89
    {
90
        $response = $this
91
            ->cas
92
            ->requestTicketValidation();
93
94
        if (null === $response) {
95
            throw new AuthenticationException('Unable to authenticate the user with such service ticket.');
96
        }
97
98
        return $response;
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104 1
    public function getUser($credentials, UserProviderInterface $userProvider)
105
    {
106 1
        if (false === ($userProvider instanceof CasUserProviderInterface)) {
107 1
            throw new AuthenticationException('Unable to load the user through the given User Provider.');
108
        }
109
110
        try {
111 1
            $user = $userProvider->loadUserByResponse($credentials);
112 1
        } catch (AuthenticationException $exception) {
113 1
            throw $exception;
114
        }
115
116 1
        return $user;
117
    }
118
119
    /**
120
     * {@inheritdoc}
121
     */
122 1
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
123
    {
124 1
        if (true === $request->query->has('ticket')) {
125
            // Remove the ticket parameter.
126 1
            $uri = Uri::removeParams(
127 1
                $this->uriFactory->createUri(
128 1
                    $request->getUri()
129
                ),
130 1
                'ticket'
131
            );
132
133
            // Add the renew parameter to force login again.
134 1
            $uri = Uri::withParam($uri, 'renew', 'true');
135
136 1
            return new RedirectResponse((string) $uri);
137
        }
138 1
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143 1
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
144
    {
145 1
        return new RedirectResponse(
146 1
            (string) Uri::removeParams(
147 1
                $this->uriFactory->createUri(
148 1
                    $request->getUri()
149
                ),
150 1
                'ticket',
151 1
                'renew'
152
            )
153
        );
154
    }
155
156
    /**
157
     * {@inheritdoc}
158
     */
159 1
    public function onLogoutSuccess(Request $request)
160
    {
161 1
        return new RedirectResponse(
162
            $this
163 1
                ->cas
164 1
                ->logout()
165 1
                ->getHeaderLine('location')
166
        );
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     */
172 2
    public function start(Request $request, ?AuthenticationException $authException = null)
173
    {
174 2
        if (true === $request->isXmlHttpRequest()) {
175 1
            return new JsonResponse(
176 1
                ['message' => 'Authentication required'],
177 1
                Response::HTTP_UNAUTHORIZED
178
            );
179
        }
180
181 1
        return new RedirectResponse(
182
            $this
183 1
                ->cas
184 1
                ->login()
185 1
                ->getHeaderLine('location')
186
        );
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     */
192 2
    public function supports(Request $request)
193
    {
194
        return $this
195 2
            ->cas
196 2
            ->withServerRequest(
197
                $this
198 2
                    ->serverRequestFactory
199 2
                    ->createServerRequest(
200 2
                        $request->getMethod(),
201 2
                        $request->getUri()
202
                    )
203
            )
204 2
            ->supportAuthentication();
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210 1
    public function supportsRememberMe()
211
    {
212 1
        return false;
213
    }
214
}
215