TokenRevocationEndpoint   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 50
c 0
b 0
f 0
dl 0
loc 114
rs 10
wmc 18

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getResponse() 0 14 3
A getCallback() 0 8 2
A process() 0 25 5
A getClient() 0 8 2
A getToken() 0 8 2
A getTokenTypeHints() 0 17 3
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2019 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace OAuth2Framework\Component\TokenRevocationEndpoint;
15
16
use OAuth2Framework\Component\Core\Client\Client;
17
use OAuth2Framework\Component\Core\Message\OAuth2Error;
18
use Psr\Http\Message\ResponseFactoryInterface;
19
use Psr\Http\Message\ResponseInterface;
20
use Psr\Http\Message\ServerRequestInterface;
21
use Psr\Http\Server\MiddlewareInterface;
22
use Psr\Http\Server\RequestHandlerInterface;
23
24
abstract class TokenRevocationEndpoint implements MiddlewareInterface
25
{
26
    /**
27
     * @var TokenTypeHintManager
28
     */
29
    private $tokenTypeHintManager;
30
31
    /**
32
     * @var ResponseFactoryInterface
33
     */
34
    private $responseFactory;
35
36
    public function __construct(TokenTypeHintManager $tokenTypeHintManager, ResponseFactoryInterface $responseFactory)
37
    {
38
        $this->tokenTypeHintManager = $tokenTypeHintManager;
39
        $this->responseFactory = $responseFactory;
40
    }
41
42
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
43
    {
44
        $callback = $this->getCallback($request);
45
46
        try {
47
            $client = $this->getClient($request);
48
            $token = $this->getToken($request);
49
            $hints = $this->getTokenTypeHints($request);
50
51
            foreach ($hints as $hint) {
52
                $result = $hint->find($token);
53
                if (null !== $result) {
54
                    if ($client->getPublicId()->getValue() === $result->getClientId()->getValue()) {
55
                        $hint->revoke($result);
56
57
                        return $this->getResponse(200, '', $callback);
58
                    }
59
60
                    throw OAuth2Error::invalidRequest('The parameter "token" is invalid.');
61
                }
62
            }
63
64
            return $this->getResponse(200, '', $callback);
65
        } catch (OAuth2Error $e) {
66
            return $this->getResponse($e->getCode(), \Safe\json_encode($e->getData(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), $callback);
67
        }
68
    }
69
70
    protected function getToken(ServerRequestInterface $request): string
71
    {
72
        $params = $this->getRequestParameters($request);
73
        if (!\array_key_exists('token', $params)) {
74
            throw OAuth2Error::invalidRequest('The parameter "token" is missing.');
75
        }
76
77
        return $params['token'];
78
    }
79
80
    /**
81
     * @return TokenTypeHint[]
82
     */
83
    protected function getTokenTypeHints(ServerRequestInterface $request): array
84
    {
85
        $params = $this->getRequestParameters($request);
86
        $tokenTypeHints = $this->tokenTypeHintManager->getTokenTypeHints();
87
88
        if (\array_key_exists('token_type_hint', $params)) {
89
            $tokenTypeHint = $params['token_type_hint'];
90
            if (!\array_key_exists($params['token_type_hint'], $tokenTypeHints)) {
91
                throw new OAuth2Error(400, 'unsupported_token_type', \Safe\sprintf('The token type hint "%s" is not supported. Please use one of the following values: %s.', $params['token_type_hint'], implode(', ', array_keys($tokenTypeHints))));
92
            }
93
94
            $hint = $tokenTypeHints[$tokenTypeHint];
95
            unset($tokenTypeHints[$tokenTypeHint]);
96
            $tokenTypeHints = [$tokenTypeHint => $hint] + $tokenTypeHints;
97
        }
98
99
        return $tokenTypeHints;
100
    }
101
102
    protected function getCallback(ServerRequestInterface $request): ?string
103
    {
104
        $params = $this->getRequestParameters($request);
105
        if (\array_key_exists('callback', $params)) {
106
            return $params['callback'];
107
        }
108
109
        return null;
110
    }
111
112
    abstract protected function getRequestParameters(ServerRequestInterface $request): array;
113
114
    private function getResponse(int $code, string $data, ?string $callback): ResponseInterface
115
    {
116
        if (null !== $callback) {
117
            $data = \Safe\sprintf('%s(%s)', $callback, $data);
118
        }
119
120
        $response = $this->responseFactory->createResponse($code);
121
        $response->getBody()->write($data);
122
        $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Cache-Control' => 'no-cache, no-store, max-age=0, must-revalidate, private', 'Pragma' => 'no-cache'];
123
        foreach ($headers as $k => $v) {
124
            $response = $response->withHeader($k, $v);
125
        }
126
127
        return $response;
128
    }
129
130
    private function getClient(ServerRequestInterface $request): Client
131
    {
132
        $client = $request->getAttribute('client');
133
        if (null === $client) {
134
            throw new OAuth2Error(400, OAuth2Error::ERROR_INVALID_CLIENT, 'Client authentication failed.');
135
        }
136
137
        return $client;
138
    }
139
}
140