Passed
Pull Request — master (#8)
by Pol
13:59 queued 10s
created

CasAuthenticator::onAuthenticationFailure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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