Notification Setup Error

We have detected an error in your notification set-up (Event-ID dab39dc24f564ec7bd4628d1305fd03c). Currently, we cannot inform you about inspection progress. Please check that the user 557058:bca11929-8c2d-43f2-8a82-c5416880d395 still has access to your repository or update the API account.

Completed
Push — develop ( a55da1...39a772 )
by
unknown
27:43 queued 12:35
created

OAuth2Plugin::getAccessToken()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 9.392
c 0
b 0
f 0
cc 3
nc 3
nop 0
1
<?php
2
/**
3
 * This file is part of the bitbucket-api package.
4
 *
5
 * (c) Alexandru Guzinschi <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Bitbucket\API\Http\Plugin;
12
13
use Bitbucket\API\Exceptions\ForbiddenAccessException;
14
use Bitbucket\API\Exceptions\HttpResponseException;
15
use Bitbucket\API\Http\Client;
16
use Bitbucket\API\Http\ClientInterface;
17
use Http\Client\Common\Plugin;
18
use Psr\Http\Message\RequestInterface;
19
20
/**
21
 * @author Alexandru Guzinschi <[email protected]>
22
 */
23
class OAuth2Plugin implements Plugin
24
{
25
    use Plugin\VersionBridgePlugin;
26
27
    const ENDPOINT_ACCESS_TOKEN     = '/oauth2/access_token';
28
    const ENDPOINT_AUTHORIZE        = '/oauth2/authorize';
29
30
    /** @var array */
31
    private $config = array(
32
        'oauth_client_id'       => 'anon',
33
        'oauth_client_secret'   => 'anon',
34
        'token_type'            => 'bearer',
35
        'scopes'                => array()
36
    );
37
38
    /** @var ClientInterface */
39
    private $httpClient;
40
41
    public function __construct(array $config, ClientInterface $client = null)
42
    {
43
        $this->config       = array_merge($this->config, $config);
44
        $this->httpClient   = (null !== $client) ? $client : new Client(
45
            array(
46
                'base_url'      => 'https://bitbucket.org',
47
                'api_version'   => 'site',
48
                'api_versions'  => array('site')
49
            )
50
        );
51
    }
52
53
    /**
54
     * {@inheritDoc}
55
     *
56
     * @throws ForbiddenAccessException
57
     * @throws \InvalidArgumentException
58
     */
59
    protected function doHandleRequest(RequestInterface $request, callable $next, callable $first)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
Unused Code introduced by
The parameter $first is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
60
    {
61
        $oauth2Header = $request->getHeader('Authorization');
62
        foreach ($oauth2Header as $header) {
63
            if (strpos($header, 'Bearer') !== false) {
64
                return $next($request);
65
            }
66
        }
67
68
        if (false === array_key_exists('access_token', $this->config)) {
69
            try {
70
                $data = $this->getAccessToken();
71
                $this->config['token_type']     = $data['token_type'];
72
                $this->config['access_token']   = $data['access_token'];
73
            } catch (HttpResponseException $e) {
74
                throw new ForbiddenAccessException("Can't fetch access_token.", 0, $e);
75
            }
76
        }
77
78
        $request = $request->withHeader(
79
            'Authorization',
80
            sprintf(
81
                '%s %s',
82
                ucfirst(strtolower($this->config['token_type'])),
83
                $this->config['access_token']
84
            )
85
        );
86
87
        return $next($request);
88
    }
89
90
    /**
91
     * Fetch access token with a grant_type of client_credentials
92
     *
93
     * @access public
94
     * @return array
95
     *
96
     * throws \InvalidArgumentException
97
     * @throws HttpResponseException
98
     */
99
    protected function getAccessToken()
100
    {
101
        $response = $this->httpClient
102
            ->post(
103
                self::ENDPOINT_ACCESS_TOKEN,
104
                array(
105
                    'grant_type'    => 'client_credentials',
106
                    'client_id'     => $this->config['client_id'],
107
                    'client_secret' => $this->config['client_secret'],
108
                    'scope'         => implode(',', $this->config['scopes'])
109
                )
110
            )
111
        ;
112
113
        $contents = $response->getBody()->getContents();
114
        $data = json_decode($contents, true);
115
116
        if (json_last_error() !== JSON_ERROR_NONE) {
117
            $ex = new HttpResponseException('[access_token] Invalid JSON: '. json_last_error_msg());
118
            $ex
119
                ->setResponse($response)
120
                ->setRequest($this->httpClient->getLastRequest())
121
            ;
122
123
            throw $ex;
124
        }
125
126
        if (false === array_key_exists('access_token', $data)) {
127
            throw new HttpResponseException('access_token is missing from response. '. $contents);
128
        }
129
130
        return $data;
131
    }
132
}
133