ScopePolicyManager   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 82
rs 10
c 0
b 0
f 0
wmc 12

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getScopes() 0 20 4
A verifyScopes() 0 14 5
A scopeStringToArray() 0 2 2
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: GCC-MED
5
 * Date: 15/01/2018
6
 * Time: 09:54
7
 */
8
9
namespace OAuth2\ScopePolicy;
10
11
12
use OAuth2\Exceptions\OAuthException;
13
use OAuth2\Roles\ClientInterface;
14
use OAuth2\Roles\ClientTypes\RegisteredClient;
15
use OAuth2\ScopePolicy\Policies\ScopePolicyInterface;
16
17
18
/**
19
 * Class ScopePolicyManager
20
 * @package OAuth2\ScopePolicy
21
 *
22
 * @see https://tools.ietf.org/html/rfc6749#section-3.3
23
 * The authorization and token endpoints allow the client to specify the
24
 * scope of the access request using the "scope" request parameter.  In
25
 * turn, the authorization server uses the "scope" response parameter to
26
 * inform the client of the scope of the access token issued.
27
 *
28
 * The value of the scope parameter is expressed as a list of space-
29
 * delimited, case-sensitive strings.  The strings are defined by the
30
 * authorization server.  If the value contains multiple space-delimited
31
 * strings, their order does not matter, and each string adds an
32
 * additional access range to the requested scope.
33
 *
34
 * scope       = scope-token *( SP scope-token )
35
 * scope-token = 1*( %x21 / %x23-5B / %x5D-7E )
36
 *
37
 * The authorization server MAY fully or partially ignore the scope
38
 * requested by the client, based on the authorization server policy or
39
 * the resource owner's instructions.  If the issued access token scope
40
 * is different from the one requested by the client, the authorization
41
 * server MUST include the "scope" response parameter to inform the
42
 * client of the actual scope granted.
43
 *
44
 * If the client omits the scope parameter when requesting
45
 * authorization, the authorization server MUST either process the
46
 * request using a pre-defined default value or fail the request
47
 * indicating an invalid scope.  The authorization server SHOULD
48
 * document its scope requirements and default value (if defined).
49
 */
50
class ScopePolicyManager
51
{
52
    /**
53
     * @var ScopePolicyInterface
54
     */
55
    private $scopePolicy;
56
57
    /**
58
     * ScopePolicyManager constructor.
59
     * @param ScopePolicyInterface $scopePolicy
60
     */
61
    public function __construct(ScopePolicyInterface $scopePolicy)
62
    {
63
        $this->scopePolicy = $scopePolicy;
64
    }
65
66
    /**
67
     * @see https://tools.ietf.org/html/rfc6749#section-3.3
68
     * The value of the scope parameter is expressed as a list of space-
69
     * delimited, case-sensitive strings.  The strings are defined by the
70
     * authorization server.  If the value contains multiple space-delimited
71
     * strings, their order does not matter, and each string adds an
72
     * additional access range to the requested scope.
73
     *
74
     * scope       = scope-token *( SP scope-token )
75
     * scope-token = 1*( %x21 / %x23-5B / %x5D-7E )
76
     *
77
     * @param null|string $scopes
78
     * @return array|null
79
     */
80
    public function scopeStringToArray(?string $scopes): ?array {
81
        return empty(trim($scopes)) ? null : array_filter(explode(' ', $scopes));
82
    }
83
84
    /**
85
     * @param ClientInterface $client
86
     * @param array|null $requestedScopes
87
     * @return array|null
88
     * @throws OAuthException
89
     */
90
    public function getScopes(ClientInterface $client, ?array $requestedScopes): array
91
    {
92
        $scopes = $this->scopePolicy->getScopes($client, $requestedScopes);
93
94
        if (empty($scopes)) {
95
            throw new OAuthException('invalid_scope',
96
                'The request scope is unknown.',
97
                'https://tools.ietf.org/html/rfc6749#section-4.1');
98
        }
99
100
        $supportedScopes = $client->getMetadata()->getScopes();
101
        if (!empty($supportedScopes)) {
102
            if (!empty(array_diff($scopes, $supportedScopes))) {
103
                throw new OAuthException('invalid_scope',
104
                    'The request scope is invalid. Supported scopes : ' . implode(', ', $supportedScopes),
105
                    'https://tools.ietf.org/html/rfc6749#section-4.1');
106
            }
107
        }
108
109
        return $scopes;
110
    }
111
112
    /**
113
     * @param ClientInterface $client
114
     * @param array $scopes
115
     * @throws OAuthException
116
     * @deprecated
117
     */
118
    public function verifyScopes(ClientInterface $client, array $scopes): void
119
    {
120
        if (empty($scopes)) {
121
            throw new OAuthException('invalid_scope',
122
                'The request scope is unknown.',
123
                'https://tools.ietf.org/html/rfc6749#section-4.1');
124
        }
125
126
        $supportedScopes = $client->getMetadata()->getScopes();
127
        if ($client instanceof RegisteredClient && !empty($supportedScopes)) {
128
            if (!empty(array_diff($scopes, $supportedScopes))) {
129
                throw new OAuthException('invalid_scope',
130
                    'The request scope is invalid. Supported scopes : ' . implode(', ', $supportedScopes),
131
                    'https://tools.ietf.org/html/rfc6749#section-4.1');
132
            }
133
        }
134
    }
135
}