Failed Conditions
Pull Request — master (#29)
by Helene
03:02
created

OAuthMiddleware   B

Complexity

Total Complexity 38

Size/Duplication

Total Lines 206
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 96.47%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 38
c 2
b 0
f 0
lcom 1
cbo 7
dl 0
loc 206
ccs 82
cts 85
cp 0.9647
rs 8.3999

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
B onBefore() 0 20 6
C onFailure() 0 34 8
B acquireAccessToken() 0 17 8
A getAccessToken() 0 8 3
A getRefreshToken() 0 8 2
B setAccessToken() 0 19 5
B setRefreshToken() 0 20 5
1
<?php
2
3
namespace CommerceGuys\Guzzle\Oauth2\Middleware;
4
5
use CommerceGuys\Guzzle\Oauth2\AccessToken;
6
use CommerceGuys\Guzzle\Oauth2\GrantType\GrantTypeBase;
7
use CommerceGuys\Guzzle\Oauth2\GrantType\GrantTypeInterface;
8
use CommerceGuys\Guzzle\Oauth2\GrantType\RefreshTokenGrantTypeInterface;
9
use GuzzleHttp\Client;
10
use GuzzleHttp\ClientInterface;
11
use GuzzleHttp\Promise\PromiseInterface;
12
use Psr\Http\Message\RequestInterface;
13
use Psr\Http\Message\ResponseInterface;
14
15
class OAuthMiddleware
16
{
17
    /**
18
     * @var AccessToken|null
19
     */
20
    protected $accessToken;
21
22
    /**
23
     * @var GrantTypeInterface
24
     */
25
    protected $grantType;
26
27
    /**
28
     * @var RefreshTokenGrantTypeInterface
29
     */
30
    protected $refreshTokenGrantType;
31
32
    /**
33
     * @var ClientInterface
34
     */
35
    protected $client;
36
37
    /**
38
     * Create a new Oauth2 subscriber.
39
     *
40
     * @param ClientInterface                $client
41
     * @param GrantTypeInterface             $grantType
42
     * @param RefreshTokenGrantTypeInterface $refreshTokenGrantType
43
     */
44 10
    public function __construct(
45
        ClientInterface $client,
46
        GrantTypeInterface $grantType = null,
47
        RefreshTokenGrantTypeInterface $refreshTokenGrantType = null
48
    ) {
49 10
        $this->client = $client;
50 10
        $this->grantType = $grantType;
51 10
        $this->refreshTokenGrantType = $refreshTokenGrantType;
52 10
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57 6
    public function onBefore()
58
    {
59
        return function (callable $handler) {
60
            return function (RequestInterface $request, array $options) use ($handler) {
61
                if (
62 6
                    isset($options['auth']) &&
63 6
                    'oauth2' == $options['auth'] &&
64 6
                    $this->grantType instanceof GrantTypeInterface &&
65 6
                    $this->grantType->getConfigByName(GrantTypeBase::CONFIG_TOKEN_URL) != $request->getUri()->getPath()
66 6
                ) {
67 6
                    $token = $this->getAccessToken();
68 6
                    if ($token !== null) {
69 6
                        return $handler($request->withAddedHeader('Authorization', 'Bearer '.$token->getToken()), $options);
70
                    }
71
                }
72
73 4
                return $handler($request, $options);
74 6
            };
75 6
        };
76
    }
77
78 6
    public function onFailure($limit)
79
    {
80 6
        $calls = 0;
81
82
        return function (callable $handler) use (&$calls, $limit) {
83
            return function (RequestInterface $request, array $options) use ($handler, &$calls, $limit) {
84
                /* @var PromiseInterface */
85 6
                $promise = $handler($request, $options);
86
87 6
                return $promise->then(
88 6
                    function (ResponseInterface $response) use ($request, $options, &$calls, $limit) {
89
                        if (
90 6
                            $response->getStatusCode() == 401 &&
91 6
                            isset($options['auth']) &&
92 6
                            'oauth2' == $options['auth'] &&
93 6
                            $this->grantType instanceof GrantTypeInterface &&
94 3
                            $this->grantType->getConfigByName(GrantTypeBase::CONFIG_TOKEN_URL) != $request->getUri()->getPath()
95 6
                        ) {
96 3
                            ++$calls;
97 3
                            if ($calls > $limit) {
98 1
                                return $response;
99
                            }
100
101 3
                            if ($token = $this->getAccessToken()) {
102 3
                                $response = $this->client->send($request->withHeader('Authorization', 'Bearer '.$token->getToken()), $options);
103 3
                            }
104 3
                        }
105
106 6
                        return $response;
107
                    }
108 6
                );
109 6
            };
110 6
        };
111
    }
112
113
    /**
114
     * Get a new access token.
115
     *
116
     * @return AccessToken|null
117
     */
118 4
    protected function acquireAccessToken()
119
    {
120 4
        if ($this->refreshTokenGrantType) {
121
            // Get an access token using the stored refresh token.
122 2
            if ($this->accessToken instanceof AccessToken && $this->accessToken->getRefreshToken() instanceof AccessToken && $this->accessToken->isExpired()) {
123 2
                $this->refreshTokenGrantType->setRefreshToken($this->accessToken->getRefreshToken()->getToken());
124 2
                $this->accessToken = $this->refreshTokenGrantType->getToken();
125 2
            }
126 2
        }
127
128 4
        if ((!$this->accessToken || $this->accessToken->isExpired()) && $this->grantType) {
129
            // Get a new access token.
130 2
            $this->accessToken = $this->grantType->getToken();
131 2
        }
132
133 4
        return $this->accessToken;
134
    }
135
136
    /**
137
     * Get the access token.
138
     *
139
     * @return AccessToken|null Oauth2 access token
140
     */
141 6
    public function getAccessToken()
142
    {
143 6
        if (!($this->accessToken instanceof AccessToken) || $this->accessToken->isExpired()) {
144 4
            $this->acquireAccessToken();
145 4
        }
146
147 6
        return $this->accessToken;
148
    }
149
150
    /**
151
     * Get the refresh token.
152
     *
153
     * @return AccessToken|null
154
     */
155 4
    public function getRefreshToken()
156
    {
157 4
        if ($this->accessToken instanceof AccessToken) {
158 4
            return $this->accessToken->getRefreshToken();
159
        }
160
161
        return null;
162
    }
163
164
    /**
165
     * Set the access token.
166
     *
167
     * @param AccessToken|string $accessToken
168
     * @param string             $type
169
     * @param int                $expires
170
     *
171
     * @return self
172
     */
173 7
    public function setAccessToken($accessToken, $type = null, $expires = null)
174
    {
175 7
        if (is_string($accessToken)) {
176 2
            $this->accessToken = new AccessToken($accessToken, $type, ['expires' => $expires]);
177 7
        } elseif ($accessToken instanceof AccessToken) {
178 4
            $this->accessToken = $accessToken;
179 4
        } else {
180 1
            throw new \InvalidArgumentException('Invalid access token');
181
        }
182
183
        if (
184 6
            $this->accessToken->getRefreshToken() instanceof AccessToken &&
185 4
            $this->refreshTokenGrantType instanceof RefreshTokenGrantTypeInterface
186 6
        ) {
187 3
            $this->refreshTokenGrantType->setRefreshToken($this->accessToken->getRefreshToken()->getToken());
188 3
        }
189
190 6
        return $this;
191
    }
192
193
    /**
194
     * Set the refresh token.
195
     *
196
     * @param AccessToken|string $refreshToken The refresh token
197
     *
198
     * @return self
199
     */
200 3
    public function setRefreshToken($refreshToken)
201
    {
202 3
        if (!($this->accessToken instanceof AccessToken)) {
203 1
            throw new \InvalidArgumentException('Unable to update the refresh token. You have never set first the access token.');
204
        }
205
206 2
        if (is_string($refreshToken)) {
207 2
            $refreshToken = new AccessToken($refreshToken, 'refresh_token');
208 2
        } elseif (!$refreshToken instanceof AccessToken) {
209
            throw new \InvalidArgumentException('Invalid refresh token');
210
        }
211
212 2
        $this->accessToken->setRefreshToken($refreshToken);
213
214 2
        if ($this->refreshTokenGrantType instanceof RefreshTokenGrantTypeInterface) {
215 1
            $this->refreshTokenGrantType->setRefreshToken($refreshToken->getToken());
216 1
        }
217
218 2
        return $this;
219
    }
220
}
221