TwitterConnection::grantNewAccessToken()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 16
c 1
b 0
f 1
nc 3
nop 0
dl 0
loc 26
rs 9.7333
1
<?php
2
/**
3
 * @author Tharanga Kothalawala <[email protected]>
4
 * @date 13-01-2019
5
 */
6
7
namespace TSK\SSO\ThirdParty\Twitter;
8
9
use Abraham\TwitterOAuth\TwitterOAuth;
10
use Abraham\TwitterOAuth\TwitterOAuthException;
11
use TSK\SSO\ThirdParty;
12
use TSK\SSO\ThirdParty\CommonAccessToken;
13
use TSK\SSO\ThirdParty\Exception\NoThirdPartyEmailFoundException;
14
use TSK\SSO\ThirdParty\Exception\ThirdPartyConnectionFailedException;
15
use TSK\SSO\ThirdParty\ThirdPartyUser;
16
use TSK\SSO\ThirdParty\VendorConnection;
17
18
/**
19
 * @codeCoverageIgnore
20
 * @package TSK\SSO\ThirdParty\Twitter
21
 * @see https://developer.twitter.com/en/docs/twitter-for-websites/log-in-with-twitter/guides/implementing-sign-in-with-twitter
22
 */
23
class TwitterConnection implements VendorConnection
24
{
25
    const TOKEN_SEPARATOR = '::';
26
27
    /**
28
     * @var TwitterApiConfiguration
29
     */
30
    private $configuration;
31
32
    /**
33
     * @var TwitterOAuth
34
     */
35
    private $twitter;
36
37
    /**
38
     * TwitterConnection constructor.
39
     * @param TwitterApiConfiguration $configuration
40
     */
41
    public function __construct(TwitterApiConfiguration $configuration)
42
    {
43
        $this->configuration = $configuration;
44
        $this->twitter = $this->getTwitter();
45
    }
46
47
    /**
48
     * Use this to get a link to redirect a user to the third party login
49
     *
50
     * @return string|null
51
     */
52
    public function getGrantUrl()
53
    {
54
        try {
55
            $response = $this->twitter->oauth('oauth/request_token', array(
56
                'oauth_callback' => $this->configuration->redirectUrl()
57
            ));
58
        } catch (TwitterOAuthException $ex) {
59
            return null;
60
        }
61
62
        return sprintf('%s/oauth/authenticate?oauth_token=%s', TwitterOAuth::API_HOST, $response['oauth_token']);
63
    }
64
65
    /**
66
     * Grants a new access token
67
     *
68
     * @return CommonAccessToken
69
     * @throws ThirdPartyConnectionFailedException
70
     */
71
    public function grantNewAccessToken()
72
    {
73
        if (empty($_GET['oauth_token'])) {
74
            throw new ThirdPartyConnectionFailedException('Invalid request!');
75
        }
76
77
        $accessTokenData = $this->twitter->oauth('oauth/access_token', array(
78
            'oauth_callback' => $this->configuration->redirectUrl(),
79
            'oauth_token' => $_GET['oauth_token'],
80
            'oauth_verifier' => $_GET['oauth_verifier'],
81
        ));
82
83
        if (empty($accessTokenData['oauth_token'])) {
84
            throw new ThirdPartyConnectionFailedException(
85
                'Failed to establish a new third party vendor connection'
86
            );
87
        }
88
89
        return new CommonAccessToken(
90
            sprintf(
91
                '%s%s%s',
92
                $accessTokenData['oauth_token'],
93
                self::TOKEN_SEPARATOR,
94
                $accessTokenData['oauth_token_secret']
95
            ),
96
            ThirdParty::TWITTER
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
        $tokenData = explode(self::TOKEN_SEPARATOR, $accessToken->token());
111
112
        $this->twitter = $this->getTwitter($tokenData[0], $tokenData[1]);
113
114
        $userInfo = (array) $this->twitter->get('account/verify_credentials', array(
115
            'oauth_token' => $tokenData[0],
116
            'oauth_token_secret' => $tokenData[1],
117
            'include_email' => true,
118
        ));
119
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['id'],
126
            $userInfo['screen_name'],
127
            $userInfo['email'],
128
            !empty($userInfo['profile_image_url']) ? $userInfo['profile_image_url'] : '',
129
            !empty($userInfo['gender']) ? $userInfo['gender'] : ''
130
        );
131
    }
132
133
    /**
134
     * Use this to revoke the access to the third party data.
135
     * This will completely remove the access from the vendor side.
136
     *
137
     * @param CommonAccessToken $accessToken
138
     * @return bool
139
     */
140
    public function revokeAccess(CommonAccessToken $accessToken)
141
    {
142
        $tokenData = explode(self::TOKEN_SEPARATOR, $accessToken->token());
143
144
        $this->twitter = $this->getTwitter($tokenData[0], $tokenData[1]);
145
146
        try {
147
            $this->twitter->post('oauth/invalidate_token', array(
148
                'access_token' => $tokenData[0],
149
                'access_token_secret' => $tokenData[1],
150
            ));
151
        } catch (TwitterOAuthException $ex) {
152
            return false;
153
        }
154
155
        return true;
156
    }
157
158
    /**
159
     * @return TwitterOAuth
160
     */
161
    private function getTwitter($oauthToken = null, $oauthTokenSecret = null)
162
    {
163
        return new TwitterOAuth(
164
            $this->configuration->consumerApiKey(),
165
            $this->configuration->consumerApiSecret(),
166
            $oauthToken,
167
            $oauthTokenSecret
168
        );
169
    }
170
}
171