ClientCredentialsFlow   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Importance

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

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A handleAccessTokenRequest() 0 27 3
A getDefaultResponseMode() 0 3 1
A getGrantTypes() 0 3 1
A isRegistrationOfRedirectUriRequired() 0 3 1
A getResponseTypes() 0 3 1
A getUnsupportedResponseModes() 0 3 1
A handleAuthorizationRequest() 0 3 1
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: GCC-MED
5
 * Date: 12/03/2018
6
 * Time: 15:41
7
 */
8
9
namespace OAuth2\AuthorizationGrantTypes\Flows;
10
11
12
use OAuth2\Endpoints\Authorization\AuthorizationRequest;
13
use OAuth2\Endpoints\Authorization\AuthorizationRequestInterface;
14
use OAuth2\Endpoints\TokenEndpoint;
15
use OAuth2\Exceptions\OAuthException;
16
use OAuth2\AuthorizationGrantTypes\AbstractGrantType;
17
use OAuth2\Helper;
18
use OAuth2\Roles\ClientTypes\ConfidentialClientInterface;
19
use OAuth2\ScopePolicy\ScopePolicyManager;
20
use OAuth2\Storages\AccessTokenStorageInterface;
21
use OAuth2\Storages\RefreshTokenStorageInterface;
22
23
/**
24
 * Class ClientCredentialsFlow
25
 * @package OAuth2\AuthorizationGrantTypes\Flows
26
 *
27
 * @see https://tools.ietf.org/html/rfc6749#section-1.3.4
28
 * The client credentials (or other forms of client authentication) can
29
 * be used as an authorization grant when the authorization scope is
30
 * limited to the protected resources under the control of the client,
31
 * or to protected resources previously arranged with the authorization
32
 * server.  Client credentials are used as an authorization grant
33
 * typically when the client is acting on its own behalf (the client is
34
 * also the resource owner) or is requesting access to protected
35
 * resources based on an authorization previously arranged with the
36
 * authorization server.
37
 *
38
 * @see https://tools.ietf.org/html/rfc6749#section-4.4
39
 * The client can request an access token using only its client
40
 * credentials (or other supported means of authentication) when the
41
 * client is requesting access to the protected resources under its
42
 * control, or those of another resource owner that have been previously
43
 * arranged with the authorization server (the method of which is beyond
44
 * the scope of this specification).
45
 *
46
 * The client credentials grant type MUST only be used by confidential
47
 * clients.
48
 */
49
class ClientCredentialsFlow extends AbstractGrantType implements FlowInterface
50
{
51
    /**
52
     * @var ScopePolicyManager
53
     */
54
    private $scopePolicyManager;
55
56
    public function __construct(ScopePolicyManager $scopePolicyManager,
57
                                AccessTokenStorageInterface $accessTokenStorage,
58
                                RefreshTokenStorageInterface $refreshTokenStorage)
59
    {
60
        parent::__construct($accessTokenStorage, $refreshTokenStorage);
61
        $this->scopePolicyManager = $scopePolicyManager;
62
    }
63
64
    /**
65
     * @return array
66
     *
67
     * @see https://tools.ietf.org/html/rfc6749#section-4.4.1
68
     * Since the client authentication is used as the authorization grant,
69
     * no additional authorization request is needed.
70
     */
71
    public function getResponseTypes(): array
72
    {
73
        return [];
74
    }
75
76
    public function getGrantTypes(): array
77
    {
78
        return ['client_credentials'];
79
    }
80
81
    /**
82
     * @param TokenEndpoint $tokenEndpoint
83
     * @param array $requestData
84
     * @return array
85
     * @throws OAuthException
86
     *
87
     * @see https://tools.ietf.org/html/rfc6749#section-4.4.2
88
     * The client makes a request to the token endpoint by adding the
89
     * following parameters using the "application/x-www-form-urlencoded"
90
     * format per Appendix B with a character encoding of UTF-8 in the HTTP
91
     * request entity-body:
92
     *
93
     * grant_type
94
     * REQUIRED.  Value MUST be set to "client_credentials".
95
     *
96
     * scope
97
     * OPTIONAL.  The scope of the access request as described by
98
     * Section 3.3.
99
     *
100
     * The client MUST authenticate with the authorization server as
101
     * described in Section 3.2.1.
102
     *
103
     * For example, the client makes the following HTTP request using
104
     * transport-layer security (with extra line breaks for display purposes
105
     * only):
106
     *
107
     * POST /token HTTP/1.1
108
     * Host: server.example.com
109
     * Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
110
     * Content-Type: application/x-www-form-urlencoded
111
     *
112
     * grant_type=client_credentials
113
     *
114
     * The authorization server MUST authenticate the client.
115
     *
116
     * @see https://tools.ietf.org/html/rfc6749#section-4.4.3
117
     * If the access token request is valid and authorized, the
118
     * authorization server issues an access token as described in
119
     * Section 5.1.  A refresh token SHOULD NOT be included.  If the request
120
     * failed client authentication or is invalid, the authorization server
121
     * returns an error response as described in Section 5.2.
122
     */
123
    public function handleAccessTokenRequest(TokenEndpoint $tokenEndpoint, array $requestData): array
124
    {
125
        if (!$tokenEndpoint->getClient() instanceof ConfidentialClientInterface) {
126
            throw new OAuthException('unauthorized_client',
127
                'The authenticated client is not authorized to use this authorization grant type. 
128
                The client credentials grant type MUST only be used by confidential clients.',
129
                'https://tools.ietf.org/html/rfc6749#section-4.4');
130
        }
131
132
133
        $requestedScopes = $this->scopePolicyManager->scopeStringToArray($requestData['scope'] ?? null);
134
        $scopes = $this->scopePolicyManager->getScopes($tokenEndpoint->getClient(), $requestedScopes);
135
136
        $responseData = $this->issueAccessToken($scopes, $tokenEndpoint->getClient()->getIdentifier(), null);
137
138
        /**
139
         * @see https://tools.ietf.org/html/rfc6749#section-3.3
140
         * The authorization and token endpoints allow the client to specify the
141
         * scope of the access request using the "scope" request parameter.  In
142
         * turn, the authorization server uses the "scope" response parameter to
143
         * inform the client of the scope of the access token issued.
144
         */
145
        if (Helper::array_equals($requestedScopes, $scopes)) {
146
            $responseData['scope'] = implode(' ', $scopes);
147
        }
148
149
        return $responseData;
150
    }
151
152
    public function handleAuthorizationRequest(AuthorizationRequestInterface $authorizationRequest): array
153
    {
154
        throw new \BadMethodCallException();
155
    }
156
157
//    public function verifyAuthorizationRequest(AuthorizationEndpoint $authorizationEndpoint, array $requestData)
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
158
//    {
159
//        throw new \BadMethodCallException();
160
//    }
161
162
    public function getDefaultResponseMode(): string
163
    {
164
        throw new \BadMethodCallException();
165
    }
166
167
    public function getUnsupportedResponseModes(): array
168
    {
169
        throw new \BadMethodCallException();
170
    }
171
172
    public function isRegistrationOfRedirectUriRequired(): bool
173
    {
174
        throw new \BadMethodCallException();
175
    }
176
}