Completed
Push — master ( 3377ec...b18ded )
by Tharanga
02:10
created

AmazonConnection::getGrantUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Tharanga Kothalawala <[email protected]>
4
 * @date 17-02-2019
5
 */
6
7
namespace TSK\SSO\ThirdParty\Amazon;
8
9
use TSK\SSO\Http\CurlRequest;
10
use TSK\SSO\ThirdParty;
11
use TSK\SSO\ThirdParty\CommonAccessToken;
12
use TSK\SSO\ThirdParty\Exception\NoThirdPartyEmailFoundException;
13
use TSK\SSO\ThirdParty\Exception\ThirdPartyConnectionFailedException;
14
use TSK\SSO\ThirdParty\ThirdPartyUser;
15
use TSK\SSO\ThirdParty\VendorConnection;
16
17
/**
18
 * @codeCoverageIgnore
19
 * @package TSK\SSO\ThirdParty\Amazon
20
 * @see https://login.amazon.com/website
21
 * @see https://images-na.ssl-images-amazon.com/images/G/01/lwa/dev/docs/website-developer-guide._TTH_.pdf
22
 */
23
class AmazonConnection implements VendorConnection
24
{
25
    const API_BASE = 'https://api.amazon.com';
26
27
    /**
28
     * @var AmazonApiConfiguration
29
     */
30
    private $apiConfiguration;
31
32
    /**
33
     * @var CurlRequest
34
     */
35
    private $curlClient;
36
37
    /**
38
     * AmazonConnection constructor.
39
     * @param AmazonApiConfiguration $apiConfiguration
40
     * @param CurlRequest $curlClient
41
     */
42
    public function __construct(AmazonApiConfiguration $apiConfiguration, CurlRequest $curlClient)
43
    {
44
        $this->apiConfiguration = $apiConfiguration;
45
        $this->curlClient = $curlClient;
46
    }
47
48
    /**
49
     * Use this to get a link to redirect a user to the third party login
50
     *
51
     * @return string|null
52
     */
53
    public function getGrantUrl()
54
    {
55
        return sprintf(
56
            'https://www.amazon.com/ap/oa?client_id=%s&scope=profile&response_type=code&redirect_uri=%s&state=%s',
57
            $this->apiConfiguration->clientId(),
58
            urlencode($this->apiConfiguration->redirectUrl()),
59
            $this->apiConfiguration->ourSecretState()
60
        );
61
    }
62
63
    /**
64
     * Grants a new access token
65
     *
66
     * @return CommonAccessToken
67
     * @throws ThirdPartyConnectionFailedException
68
     */
69
    public function grantNewAccessToken()
70
    {
71
        if (empty($_GET['code'])
72
            || empty($_GET['state'])
73
            || $_GET['state'] !== $this->apiConfiguration->ourSecretState()
74
        ) {
75
            throw new ThirdPartyConnectionFailedException('Invalid request!');
76
        }
77
78
        $accessTokenJsonResponse = $this->curlClient->postUrlEncoded(
79
            sprintf("%s/auth/o2/token", self::API_BASE),
80
            sprintf(
81
                'grant_type=authorization_code&code=%s&client_id=%s&client_secret=%s&redirect_uri=%s',
82
                $_GET['code'],
83
                $this->apiConfiguration->clientId(),
84
                $this->apiConfiguration->clientSecret(),
85
                urlencode($this->apiConfiguration->redirectUrl())
86
            )
87
        );
88
89
        $accessTokenData = json_decode($accessTokenJsonResponse, true);
90
        if (empty($accessTokenData['access_token'])) {
91
            throw new ThirdPartyConnectionFailedException('Failed to establish a new third party vendor connection.');
92
        }
93
94
        return new CommonAccessToken(
95
            $accessTokenData['access_token'],
96
            ThirdParty::AMAZON
97
        );
98
    }
99
100
    /**
101
     * Use this to retrieve the current user's third party user data using there existing granted access token
102
     *
103
     * @param CommonAccessToken $accessToken
104
     * @return ThirdPartyUser
105
     * @throws NoThirdPartyEmailFoundException
106
     * @throws ThirdPartyConnectionFailedException
107
     */
108
    public function getSelf(CommonAccessToken $accessToken)
109
    {
110
        $userJsonInfo = $this->curlClient->get(
111
            sprintf("%s/user/profile", self::API_BASE),
112
            array(
113
                sprintf('Authorization: Bearer %s', $accessToken->token()),
114
                'Accept: application/json',
115
                'Accept-Language: en-us',
116
            )
117
        );
118
119
        $userInfo = json_decode($userJsonInfo, true);
120
        if (empty($userInfo['email'])) {
121
            throw new NoThirdPartyEmailFoundException('An email address cannot be found from vendor');
122
        }
123
124
        return new ThirdPartyUser(
125
            $userInfo['user_id'],
126
            $userInfo['name'],
127
            $userInfo['email']
128
        );
129
    }
130
131
    /**
132
     * Use this to revoke the access to the third party data.
133
     * This will completely remove the access from the vendor side.
134
     *
135
     * @param CommonAccessToken $accessToken
136
     * @return bool
137
     */
138
    public function revokeAccess(CommonAccessToken $accessToken)
139
    {
140
        // noop : cannot find documentation on how to revoke the app's access.
141
        return true;
142
    }
143
}
144