LinkedInConnection   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 46
c 1
b 0
f 0
dl 0
loc 123
rs 10
wmc 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A revokeAccess() 0 8 1
A getSelf() 0 17 2
A grantNewAccessToken() 0 29 5
A __construct() 0 6 1
A getGrantUrl() 0 9 1
1
<?php
2
/**
3
 * @author Tharanga Kothalawala <[email protected]>
4
 * @date 31-12-2018
5
 */
6
7
namespace TSK\SSO\ThirdParty\LinkedIn;
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\LinkedIn
20
 * @see https://developer.linkedin.com/docs/oauth2
21
 */
22
class LinkedInConnection implements VendorConnection
23
{
24
    const AUTH_API_BASE = 'https://www.linkedin.com/oauth/v2';
25
    const API_BASE = 'https://api.linkedin.com/v1';
26
27
    /**
28
     * @var LinkedInApiConfiguration
29
     */
30
    private $linkedInApiConfiguration;
31
32
    /**
33
     * @var CurlRequest
34
     */
35
    private $curlClient;
36
37
    /**
38
     * @param LinkedInApiConfiguration $linkedInApiConfiguration
39
     * @param CurlRequest $curlClient
40
     */
41
    public function __construct(
42
        LinkedInApiConfiguration $linkedInApiConfiguration,
43
        CurlRequest $curlClient
44
    ) {
45
        $this->linkedInApiConfiguration = $linkedInApiConfiguration;
46
        $this->curlClient = $curlClient;
47
    }
48
49
    /**
50
     * Use this to get a link to redirect a user to the facebook login page.
51
     *
52
     * @return string
53
     */
54
    public function getGrantUrl()
55
    {
56
        return sprintf(
57
            '%s/authorization?response_type=code&client_id=%s&redirect_uri=%s&state=%s&scope=%s',
58
            self::AUTH_API_BASE,
59
            $this->linkedInApiConfiguration->appId(),
60
            $this->linkedInApiConfiguration->redirectUrl(),
61
            $this->linkedInApiConfiguration->ourSecretState(),
62
            $this->linkedInApiConfiguration->appPermissions()
63
        );
64
    }
65
66
    /**
67
     * Grants a new access token
68
     *
69
     * @return CommonAccessToken
70
     * @throws ThirdPartyConnectionFailedException
71
     */
72
    public function grantNewAccessToken()
73
    {
74
        // state and code validation
75
        if (empty($_GET['code'])
76
            || empty($_GET['state'])
77
            || $_GET['state'] !== $this->linkedInApiConfiguration->ourSecretState()
78
        ) {
79
            throw new ThirdPartyConnectionFailedException('Invalid request!');
80
        }
81
82
        $accessTokenJsonInfo = $this->curlClient->post(
83
            sprintf(
84
                "%s/accessToken?grant_type=authorization_code&code=%s&redirect_uri=%s&client_id=%s&client_secret=%s",
85
                self::AUTH_API_BASE,
86
                $_GET['code'],
87
                $this->linkedInApiConfiguration->redirectUrl(),
88
                $this->linkedInApiConfiguration->appId(),
89
                $this->linkedInApiConfiguration->appSecret()
90
            )
91
        );
92
93
        $accessTokenInfo = json_decode($accessTokenJsonInfo, true);
94
        if (!empty($accessTokenInfo['error'])) {
95
            throw new ThirdPartyConnectionFailedException(
96
                'Failed to establish a new third party vendor connection due to' . $accessTokenInfo['error_description']
97
            );
98
        }
99
100
        return new CommonAccessToken($accessTokenInfo['access_token'], ThirdParty::LINKEDIN);
101
    }
102
103
    /**
104
     * Get the current authenticated user data using there existing granted token
105
     *
106
     * @param CommonAccessToken $accessToken
107
     * @return ThirdPartyUser
108
     * @throws NoThirdPartyEmailFoundException
109
     */
110
    public function getSelf(CommonAccessToken $accessToken)
111
    {
112
        $userJson = $this->curlClient->get(sprintf(
113
            '%s/people/~:(id,firstName,lastName,emailAddress)?format=json&oauth2_access_token=%s',
114
            self::API_BASE,
115
            $accessToken->token()
116
        ));
117
118
        $user = json_decode($userJson, true);
119
        if (empty($user['emailAddress'])) {
120
            throw new NoThirdPartyEmailFoundException('An email address cannot be found from vendor');
121
        }
122
123
        return new ThirdPartyUser(
124
            $user['id'],
125
            sprintf('%s %s', $user['firstName'], $user['lastName']),
126
            $user['emailAddress']
127
        );
128
    }
129
130
    /**
131
     * Use this to revoke the access to the third party data.
132
     * This will completely remove the access from the vendor side.
133
     *
134
     * @param CommonAccessToken $accessToken
135
     * @return bool
136
     */
137
    public function revokeAccess(CommonAccessToken $accessToken)
138
    {
139
        $this->curlClient->get(sprintf(
140
            'https://api.linkedin.com/uas/oauth/invalidateToken?oauth2_access_token=%s',
141
            $accessToken->token()
142
        ));
143
144
        return true;
145
    }
146
}
147