Passed
Push — master ( 94fa1d...3978c2 )
by Pol
13:07 queued 11:32
created

CasGuardAuthenticator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 1
rs 10
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\ServerRequestInterface;
14
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
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
class CasGuardAuthenticator extends AbstractGuardAuthenticator implements LogoutSuccessHandlerInterface
0 ignored issues
show
Deprecated Code introduced by
The interface Symfony\Component\Securi...SuccessHandlerInterface has been deprecated: since Symfony 5.1 ( Ignorable by Annotation )

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

26
class CasGuardAuthenticator extends AbstractGuardAuthenticator implements /** @scrutinizer ignore-deprecated */ LogoutSuccessHandlerInterface

This interface has been deprecated. The supplier of the interface has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the interface will be removed and what other interface to use instead.

Loading history...
27
{
28
    /**
29
     * The ecphp/cas-lib library.
30
     *
31
     * @var \EcPhp\CasLib\CasInterface
32
     */
33
    private $cas;
34
35
    /**
36
     * @var \Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface
37
     */
38
    private $httpMessageFactory;
39
40 11
    public function __construct(
41
        CasInterface $cas,
42
        HttpMessageFactoryInterface $httpMessageFactory
43
    ) {
44 11
        $this->cas = $cas;
45 11
        $this->httpMessageFactory = $httpMessageFactory;
46 11
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51 1
    public function checkCredentials($credentials, UserInterface $user)
52
    {
53
        try {
54 1
            $introspect = Introspector::detect($credentials);
55 1
        } catch (InvalidArgumentException $exception) {
56 1
            throw new AuthenticationException($exception->getMessage());
57
        }
58
59 1
        if (false === ($introspect instanceof ServiceValidate)) {
60 1
            throw new AuthenticationException(
61 1
                'Failure in the returned response'
62
            );
63
        }
64
65 1
        return true;
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function getCredentials(Request $request)
72
    {
73
        $response = $this
74
            ->cas
75
            ->requestTicketValidation();
76
77
        if (null === $response) {
78
            throw new AuthenticationException('Unable to authenticate the user with such service ticket.');
79
        }
80
81
        return $response;
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87 1
    public function getUser($credentials, UserProviderInterface $userProvider)
88
    {
89 1
        if (false === ($userProvider instanceof CasUserProviderInterface)) {
90 1
            throw new AuthenticationException('Unable to load the user through the given User Provider.');
91
        }
92
93
        try {
94 1
            $user = $userProvider->loadUserByResponse($credentials);
95 1
        } catch (AuthenticationException $exception) {
96 1
            throw $exception;
97
        }
98
99 1
        return $user;
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105 1
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
106
    {
107 1
        $uri = $this->toPsr($request)->getUri();
108
109 1
        if (true === Uri::hasParams($uri, 'ticket')) {
110
            // Remove the ticket parameter.
111 1
            $uri = Uri::removeParams(
112 1
                $uri,
113 1
                'ticket'
114
            );
115
116
            // Add the renew parameter to force login again.
117 1
            $uri = Uri::withParam($uri, 'renew', 'true');
118
119 1
            return new RedirectResponse((string) $uri);
120
        }
121
122 1
        return null;
123
    }
124
125
    /**
126
     * {@inheritdoc}
127
     */
128 1
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
129
    {
130 1
        return new RedirectResponse(
131 1
            (string) Uri::removeParams(
132 1
                $this->toPsr($request)->getUri(),
133 1
                'ticket',
134 1
                'renew'
135
            )
136
        );
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142 1
    public function onLogoutSuccess(Request $request)
143
    {
144
        $response = $this
145 1
            ->cas
146 1
            ->logout();
147
148 1
        if (null === $response) {
149
            throw new AuthenticationException('Unable to trigger the logout procedure');
150
        }
151
152 1
        return new RedirectResponse(
153
            $response
154 1
                ->getHeaderLine('location')
155
        );
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161 2
    public function start(Request $request, ?AuthenticationException $authException = null)
162
    {
163 2
        if (true === $request->isXmlHttpRequest()) {
164 1
            return new JsonResponse(
165 1
                ['message' => 'Authentication required'],
166 1
                Response::HTTP_UNAUTHORIZED
167
            );
168
        }
169
170
        $response = $this
171 1
            ->cas
172 1
            ->login();
173
174 1
        if (null === $response) {
175
            throw new AuthenticationException('Unable to trigger the login procedure');
176
        }
177
178 1
        return new RedirectResponse(
179
            $response
180 1
                ->getHeaderLine('location')
181
        );
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187 2
    public function supports(Request $request)
188
    {
189
        return $this
190 2
            ->cas
191 2
            ->withServerRequest($this->toPsr($request))
192 2
            ->supportAuthentication();
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198 1
    public function supportsRememberMe()
199
    {
200 1
        return false;
201
    }
202
203
    /**
204
     * Convert a Symfony request into a PSR Request.
205
     *
206
     * @param \Symfony\Component\HttpFoundation\Request $request
207
     *   The Symfony request.
208
     *
209
     * @return \Psr\Http\Message\ServerRequestInterface
210
     *   The PSR request.
211
     */
212 4
    private function toPsr(Request $request): ServerRequestInterface
213
    {
214
        // As we cannot decorate the Symfony Request object, we convert it into
215
        // a PSR Request so we can override the PSR HTTP Message factory if
216
        // needed.
217
        // See the reasons at https://github.com/ecphp/cas-lib/issues/5
218 4
        return $this->httpMessageFactory->createRequest($request);
219
    }
220
}
221