Passed
Pull Request — master (#8)
by Pol
01:59
created

CasAuthenticator::supports()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 9
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 13
ccs 0
cts 13
cp 0
crap 2
rs 9.9666
1
<?php
2
3
declare(strict_types=1);
4
5
namespace EcPhp\CasBundle\Security;
6
7
use EcPhp\CasBundle\Security\Core\User\CasUser;
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\Http\Authenticator\AbstractAuthenticator;
22
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
23
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
24
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
25
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
26
27
/**
28
 * Class CasAuthenticator.
29
 */
30
class CasAuthenticator extends AbstractAuthenticator implements AuthenticationEntryPointInterface
31
{
32
    /**
33
     * The PSR CAS library.
34
     *
35
     * @var \EcPhp\CasLib\CasInterface
36
     */
37
    private $cas;
38
39
    /**
40
     * @var \Psr\Http\Message\ServerRequestFactoryInterface
41
     */
42
    private $serverRequestFactory;
43
44
    /**
45
     * @var \Psr\Http\Message\UriFactoryInterface
46
     */
47
    private $uriFactory;
48
49
    /**
50
     * CasGuardAuthenticator constructor.
51
     *
52
     * @param \EcPhp\CasLib\CasInterface $cas
53
     * @param \Psr\Http\Message\UriFactoryInterface $uriFactory
54
     * @param \Psr\Http\Message\ServerRequestFactoryInterface $serverRequestFactory
55
     */
56
    public function __construct(
57
        CasInterface $cas,
58
        UriFactoryInterface $uriFactory,
59
        ServerRequestFactoryInterface $serverRequestFactory
60
    ) {
61
        $this->cas = $cas;
62
        $this->uriFactory = $uriFactory;
63
        $this->serverRequestFactory = $serverRequestFactory;
64
    }
65
66
    public function authenticate(Request $request): PassportInterface
67
    {
68
        $response = $this
69
            ->cas
70
            ->requestTicketValidation();
71
72
        if (null === $response) {
73
            throw new AuthenticationException('Unable to authenticate the user with such service ticket.');
74
        }
75
76
        try {
77
            $introspect = Introspector::detect($response);
78
        } catch (InvalidArgumentException $exception) {
79
            throw new AuthenticationException($exception->getMessage());
80
        }
81
82
        if (false === ($introspect instanceof ServiceValidate)) {
83
            throw new AuthenticationException(
84
                'Failure in the returned response'
85
            );
86
        }
87
88
        return new Passport(new CasUser($introspect->getCredentials()), new PasswordCredentials(''));
89
    }
90
91
    public function onAuthenticationFailure(
92
        Request $request,
93
        AuthenticationException $exception
94
    ): ?Response {
95
        return null;
96
    }
97
98
    public function onAuthenticationSuccess(
99
        Request $request,
100
        TokenInterface $token,
101
        string $firewallName
102
    ): ?Response {
103
        return new RedirectResponse(
104
            (string) Uri::removeParams(
105
                $this->uriFactory->createUri(
106
                    $request->getUri()
107
                ),
108
                'ticket',
109
                'renew'
110
            )
111
        );
112
    }
113
114
    public function start(
115
        Request $request,
116
        ?AuthenticationException $authException = null
117
    ) {
118
        if (true === $request->isXmlHttpRequest()) {
119
            return new JsonResponse(
120
                ['message' => 'Authentication required'],
121
                Response::HTTP_UNAUTHORIZED
122
            );
123
        }
124
125
        $response = $this
126
            ->cas
127
            ->login();
128
129
        if (null === $response) {
130
            throw new AuthenticationException('Unable to start the authentication process.', 0, $authException);
131
        }
132
133
        return new RedirectResponse(
134
            $response
135
                ->getHeaderLine('location')
136
        );
137
    }
138
139
    public function supports(Request $request): ?bool
140
    {
141
        return $this
142
            ->cas
143
            ->withServerRequest(
144
                $this
145
                    ->serverRequestFactory
146
                    ->createServerRequest(
147
                        $request->getMethod(),
148
                        $request->getUri()
149
                    )
150
            )
151
            ->supportAuthentication();
152
    }
153
}
154