Test Failed
Push — develop ( 4fb714...2a02a1 )
by nguereza
05:02
created

OAuthResourceMiddleware::process()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 26
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 4
nop 2
dl 0
loc 26
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Platine PHP
5
 *
6
 * Platine PHP is a lightweight, high-performance, simple and elegant
7
 * PHP Web framework
8
 *
9
 * This content is released under the MIT License (MIT)
10
 *
11
 * Copyright (c) 2020 Platine PHP
12
 *
13
 * Permission is hereby granted, free of charge, to any person obtaining a copy
14
 * of this software and associated documentation files (the "Software"), to deal
15
 * in the Software without restriction, including without limitation the rights
16
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
 * copies of the Software, and to permit persons to whom the Software is
18
 * furnished to do so, subject to the following conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all
21
 * copies or substantial portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
 * SOFTWARE.
30
 */
31
32
declare(strict_types=1);
33
34
namespace Platine\Framework\OAuth2\Middleware;
35
36
use Platine\Config\Config;
37
use Platine\Http\Handler\MiddlewareInterface;
38
use Platine\Http\Handler\RequestHandlerInterface;
39
use Platine\Http\ResponseInterface;
40
use Platine\Http\ServerRequestInterface;
41
use Platine\OAuth2\Entity\AccessToken;
42
use Platine\OAuth2\Exception\InvalidAccessTokenException;
43
use Platine\OAuth2\ResourceServerInterface;
44
use Platine\OAuth2\Response\OAuthJsonResponse;
45
use Platine\Route\Route;
46
47
/**
48
 * @class OAuthResourceMiddleware
49
 * @package Platine\Framework\OAuth2\Middleware
50
 * @template T
51
 */
52
class OAuthResourceMiddleware implements MiddlewareInterface
53
{
54
    /**
55
     * The Resource Server
56
     * @var ResourceServerInterface
57
     */
58
    protected ResourceServerInterface $resourceServer;
59
60
    /**
61
     * The configuration instance
62
     * @var Config<T>
63
     */
64
    protected Config $config;
65
66
    /**
67
     * The scope list
68
     * @var array<string>
69
     */
70
    protected array $scopes = [];
71
72
    /**
73
     * Create new instance
74
     * @param ResourceServerInterface $resourceServer
75
     * @param Config<T> $config
76
     */
77
    public function __construct(
78
        ResourceServerInterface $resourceServer,
79
        Config $config
80
    ) {
81
        $this->resourceServer = $resourceServer;
82
        $this->config = $config;
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function process(
89
        ServerRequestInterface $request,
90
        RequestHandlerInterface $handler
91
    ): ResponseInterface {
92
        if ($this->shouldBeProcessed($request) === false) {
93
            return $handler->handle($request);
94
        }
95
96
        try {
97
            $token = $this->resourceServer->getAccessToken($request, $this->scopes);
98
            if ($token === null) {
99
                throw InvalidAccessTokenException::invalidToken('No access token found in the request');
100
            }
101
        } catch (InvalidAccessTokenException $ex) {
102
            // If we're here, this means that there was an access token, but it's either expired
103
            // or invalid. If that's the case we must immediately return
104
            return new OAuthJsonResponse(
105
                [
106
                    'error' => $ex->getCode(),
107
                    'error_description' => $ex->getMessage(),
108
                ],
109
                401
110
            );
111
        }
112
113
        return $handler->handle($request->withAttribute(AccessToken::class, $token));
114
    }
115
116
    /**
117
     * Whether we can process this request
118
     * @param ServerRequestInterface $request
119
     * @return bool
120
     */
121
    protected function shouldBeProcessed(ServerRequestInterface $request): bool
122
    {
123
       //If no route has been match no need check
124
        /** @var Route|null $route */
125
        $route = $request->getAttribute(Route::class);
126
        if ($route === null) {
127
            return false;
128
        }
129
130
        $scopes = $route->getAttribute('scopes');
131
        $this->scopes = $scopes ?? [];
132
133
        //check if is url whitelist
134
        $urls = $this->config->get('oauth2.url_whitelist', []);
135
        if (in_array($route->getName(), $urls)) {
136
            return false;
137
        }
138
139
        return true;
140
    }
141
}
142