Authentication::parseTokenResponse()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
namespace DominionEnterprises\Api;
3
use DominionEnterprises\Util;
4
use DominionEnterprises\Util\Arrays;
5
use DominionEnterprises\Util\Http;
6
7
/**
8
 * Layer for OAuth2 Authentication
9
 */
10
final class Authentication
11
{
12
    /**
13
     * Function to create a Request object for obtaining a new token from the API
14
     *
15
     * @var callable
16
     */
17
    private $_getTokenRequestFunc;
18
19
    /**
20
     * Private constructor to safeguard undeclared functions
21
     *
22
     * @param callable $getTokenRequestFunc Function to create a Request object for obtaining a new token from the API
23
     */
24
    private function __construct(callable $getTokenRequestFunc)
25
    {
26
        $this->_getTokenRequestFunc = $getTokenRequestFunc;
27
    }
28
29
    /**
30
     * Creates a new instance of Authentication for Client Credentials grant type
31
     *
32
     * @param string $clientId The oauth client id
33
     * @param string $clientSecret The oauth client secret
34
     * @param string $refreshResource The refresh token resource of the API
35
     *     Only needed since apigee doesnt use the token resource that is in the oauth2 spec
36
     *
37
     * @return \DominionEnterprises\Api\Authentication
38
     */
39
    public static function createClientCredentials($clientId, $clientSecret, $refreshResource = 'token', $tokenResource = 'token')
40
    {
41
        Util::throwIfNotType(['string' => [$clientId, $clientSecret]], true);
42
43
        $getTokenRequestFunc = function($baseUrl, $refreshToken) use ($clientId, $clientSecret, $refreshResource, $tokenResource) {
44
            if ($refreshToken !== null) {
45
                return self::_getRefreshTokenRequest($baseUrl, $clientId, $clientSecret, $refreshResource, $refreshToken);
46
            }
47
48
            $data = ['client_id' => $clientId, 'client_secret' => $clientSecret, 'grant_type' => 'client_credentials'];
49
            return new Request(
50
                "{$baseUrl}/{$tokenResource}",
51
                'POST',
52
                Http::buildQueryString($data),
53
                ['Content-Type' => 'application/x-www-form-urlencoded']
54
            );
55
        };
56
57
        return new self($getTokenRequestFunc);
58
    }
59
60
    /**
61
     * Creates a new instance of Authentication for Owner Credentials grant type
62
     *
63
     * @param string $clientId The oauth client id
64
     * @param string $clientSecret The oauth client secret
65
     * @param string $username The oauth username
66
     * @param string $password The oauth password
67
     * @param string $refreshResource The refresh token resource of the API
68
     *     Only needed since apigee doesnt use the token resource that is in the oauth2 spec
69
     *
70
     * @return \DominionEnterprises\Api\Authentication
71
     */
72
    public static function createOwnerCredentials(
73
        $clientId,
74
        $clientSecret,
75
        $username,
76
        $password,
77
        $refreshResource = 'token',
78
        $tokenResource = 'token'
79
    )
80
    {
81
        Util::throwIfNotType(['string' => [$clientId, $clientSecret, $username, $password]], true);
82
83
        $getTokenRequestFunc = function($baseUrl, $refreshToken)
84
        use ($clientId, $clientSecret, $username, $password, $refreshResource, $tokenResource) {
85
            if ($refreshToken !== null) {
86
                return self::_getRefreshTokenRequest($baseUrl, $clientId, $clientSecret, $refreshResource, $refreshToken);
87
            }
88
89
            $data = [
90
                'client_id' => $clientId,
91
                'client_secret' => $clientSecret,
92
                'username' => $username,
93
                'password' => $password,
94
                'grant_type' => 'password',
95
            ];
96
            return new Request(
97
                "{$baseUrl}/{$tokenResource}",
98
                'POST',
99
                Http::buildQueryString($data),
100
                ['Content-Type' => 'application/x-www-form-urlencoded']
101
            );
102
        };
103
104
        return new self($getTokenRequestFunc);
105
    }
106
107
    /**
108
     * Extracts an access token from the given API response
109
     *
110
     * @param \DominionEnterprises\Api\Response $response The API response containing the access token
111
     *
112
     * @return array Array containing the access token, refresh token and expires timestamp
113
     */
114
    public static function parseTokenResponse(Response $response)
115
    {
116
        $parsedJson = $response->getResponse();
117
        Util::ensureNot('invalid_client', Arrays::get($parsedJson, 'error'), 'Invalid Credentials');
118
        Util::ensure(200, $response->getHttpCode(), Arrays::get($parsedJson, 'error_description', 'Unknown API error'));
119
        return [$parsedJson['access_token'], Arrays::get($parsedJson, 'refresh_token'), time() + (int)$parsedJson['expires_in']];
120
    }
121
122
    /**
123
     * Creates a Request object for obtaining a new token from the API
124
     *
125
     * @param string $baseUrl The base url of the API
126
     * @param string $refreshToken The refresh token of the API
127
     *
128
     * @return \DominionEnterprises\Api\Request
129
     */
130
    public function getTokenRequest($baseUrl, $refreshToken)
131
    {
132
        Util::throwIfNotType(['string' => [$baseUrl]], true);
133
        Util::throwIfNotType(['string' => [$refreshToken]], true, true);
134
135
        return call_user_func($this->_getTokenRequestFunc, $baseUrl, $refreshToken);
136
    }
137
138
    /**
139
     * Build a refresh token request
140
     *
141
     * @param string $baseUrl API base url
142
     * @param string $clientId The client id
143
     * @param string $clientSecret The client secret
144
     * @param string $refreshResource The refresh token resource of the API
145
     *     Only needed since apigee doesnt use the token resource that is in the oauth2 spec
146
     * @param string $refreshToken The refresh token of the API
147
     *
148
     * @return \DominionEnterprises\Api\Request The built token refresh request
149
     */
150
    private static function _getRefreshTokenRequest($baseUrl, $clientId, $clientSecret, $refreshResource, $refreshToken)
151
    {
152
        //NOTE client_id and client_secret are needed for Apigee but are not in the oauth2 spec
153
        $data = ['client_id' => $clientId, 'client_secret' => $clientSecret, 'refresh_token' => $refreshToken, 'grant_type' => 'refresh_token'];
154
155
        //NOTE the oauth2 spec says the refresh resource should be the same as the token resource, which is impossible in Apigee and why the
156
        //$refreshResource variable exists
157
        return new Request(
158
            "{$baseUrl}/{$refreshResource}",
159
            'POST',
160
            Http::buildQueryString($data),
161
            ['Content-Type' => 'application/x-www-form-urlencoded']
162
        );
163
    }
164
}
165