Passed
Push — master ( 9a67fa...2cb997 )
by Pol
27:34 queued 12:35
created

CasGuardAuthenticator::toPsr()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

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