Completed
Pull Request — master (#498)
by Dragonqos
02:27
created

Google::getAccessTokenEndpoint()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace OAuth\OAuth2\Service;
4
5
use OAuth\OAuth2\Token\StdOAuth2Token;
6
use OAuth\Common\Http\Exception\TokenResponseException;
7
use OAuth\OAuth2\Service\Exception\InvalidAccessTypeException;
8
use OAuth\Common\Http\Uri\Uri;
9
10
class Google extends AbstractService
11
{
12
    /**
13
     * Defined scopes - More scopes are listed here:
14
     * https://developers.google.com/oauthplayground/
15
     *
16
     * Make a pull request if you need more scopes.
17
     */
18
19
    // Basic
20
    const SCOPE_EMAIL                       = 'email';
21
    const SCOPE_PROFILE                     = 'profile';
22
23
    const SCOPE_USERINFO_EMAIL              = 'https://www.googleapis.com/auth/userinfo.email';
24
    const SCOPE_USERINFO_PROFILE            = 'https://www.googleapis.com/auth/userinfo.profile';
25
26
    // Google+
27
    const SCOPE_GPLUS_ME                    = 'https://www.googleapis.com/auth/plus.me';
28
    const SCOPE_GPLUS_LOGIN                 = 'https://www.googleapis.com/auth/plus.login';
29
    const SCOPE_GPLUS_CIRCLES_READ          = 'https://www.googleapis.com/auth/plus.circles.read';
30
    const SCOPE_GPLUS_CIRCLES_WRITE         = 'https://www.googleapis.com/auth/plus.circles.write';
31
    const SCOPE_GPLUS_STREAM_READ           = 'https://www.googleapis.com/auth/plus.stream.read';
32
    const SCOPE_GPLUS_STREAM_WRITE          = 'https://www.googleapis.com/auth/plus.stream.write';
33
    const SCOPE_GPLUS_MEDIA                 = 'https://www.googleapis.com/auth/plus.media.upload';
34
    const SCOPE_EMAIL_PLUS                  = 'https://www.googleapis.com/auth/plus.profile.emails.read';
35
36
    // Google Drive
37
    const SCOPE_DOCUMENTSLIST               = 'https://docs.google.com/feeds/';
38
    const SCOPE_SPREADSHEETS                = 'https://spreadsheets.google.com/feeds/';
39
    const SCOPE_GOOGLEDRIVE                 = 'https://www.googleapis.com/auth/drive';
40
    const SCOPE_DRIVE_APPS                  = 'https://www.googleapis.com/auth/drive.appdata';
41
    const SCOPE_DRIVE_APPS_READ_ONLY        = 'https://www.googleapis.com/auth/drive.apps.readonly';
42
    const SCOPE_GOOGLEDRIVE_FILES           = 'https://www.googleapis.com/auth/drive.file';
43
    const SCOPE_DRIVE_METADATA_READ_ONLY    = 'https://www.googleapis.com/auth/drive.metadata.readonly';
44
    const SCOPE_DRIVE_READ_ONLY             = 'https://www.googleapis.com/auth/drive.readonly';
45
    const SCOPE_DRIVE_SCRIPTS               = 'https://www.googleapis.com/auth/drive.scripts';
46
47
    // Adwords
48
    const SCOPE_ADSENSE                     = 'https://www.googleapis.com/auth/adsense';
49
    const SCOPE_ADWORDS                     = 'https://www.googleapis.com/auth/adwords';
50
    const SCOPE_ADWORDS_DEPRECATED          = 'https://www.googleapis.com/auth/adwords/'; //deprecated in v201406 API version
51
    const SCOPE_GAN                         = 'https://www.googleapis.com/auth/gan'; // google affiliate network...?
52
53
    //Doubleclick for Publishers
54
    const SCOPE_DFP                         = 'https://www.googleapis.com/auth/dfp';
55
    const SCOPE_DFP_TRAFFICKING             = 'https://www.googleapis.com/auth/dfatrafficking';
56
    const SCOPE_DFP_REPORTING               = 'https://www.googleapis.com/auth/dfareporting';
57
58
    // Google Analytics
59
    const SCOPE_ANALYTICS                   = 'https://www.googleapis.com/auth/analytics';
60
    const SCOPE_ANALYTICS_EDIT              = 'https://www.googleapis.com/auth/analytics.edit';
61
    const SCOPE_ANALYTICS_MANAGE_USERS      = 'https://www.googleapis.com/auth/analytics.manage.users';
62
    const SCOPE_ANALYTICS_READ_ONLY         = 'https://www.googleapis.com/auth/analytics.readonly';
63
64
    //Gmail
65
    const SCOPE_GMAIL_MODIFY                = 'https://www.googleapis.com/auth/gmail.modify';
66
    const SCOPE_GMAIL_READONLY              = 'https://www.googleapis.com/auth/gmail.readonly';
67
    const SCOPE_GMAIL_COMPOSE               = 'https://www.googleapis.com/auth/gmail.compose';
68
    const SCOPE_GMAIL_SEND                  = 'https://www.googleapis.com/auth/gmail.send';
69
    const SCOPE_GMAIL_INSERT                = 'https://www.googleapis.com/auth/gmail.insert';
70
    const SCOPE_GMAIL_LABELS                = 'https://www.googleapis.com/auth/gmail.labels';
71
    const SCOPE_GMAIL_FULL                  = 'https://mail.google.com/';
72
73
    // Other services
74
    const SCOPE_BOOKS                       = 'https://www.googleapis.com/auth/books';
75
    const SCOPE_BLOGGER                     = 'https://www.googleapis.com/auth/blogger';
76
    const SCOPE_CALENDAR                    = 'https://www.googleapis.com/auth/calendar';
77
    const SCOPE_CALENDAR_READ_ONLY          = 'https://www.googleapis.com/auth/calendar.readonly';
78
    const SCOPE_CONTACT                     = 'https://www.google.com/m8/feeds/';
79
    const SCOPE_CONTACTS_RO                 = 'https://www.googleapis.com/auth/contacts.readonly';
80
    const SCOPE_CHROMEWEBSTORE              = 'https://www.googleapis.com/auth/chromewebstore.readonly';
81
    const SCOPE_GMAIL                       = 'https://mail.google.com/mail/feed/atom';
82
    const SCOPE_GMAIL_IMAP_SMTP             = 'https://mail.google.com';
83
    const SCOPE_PICASAWEB                   = 'https://picasaweb.google.com/data/';
84
    const SCOPE_SITES                       = 'https://sites.google.com/feeds/';
85
    const SCOPE_URLSHORTENER                = 'https://www.googleapis.com/auth/urlshortener';
86
    const SCOPE_WEBMASTERTOOLS              = 'https://www.google.com/webmasters/tools/feeds/';
87
    const SCOPE_TASKS                       = 'https://www.googleapis.com/auth/tasks';
88
89
    // Cloud services
90
    const SCOPE_CLOUDSTORAGE                = 'https://www.googleapis.com/auth/devstorage.read_write';
91
    const SCOPE_CONTENTFORSHOPPING          = 'https://www.googleapis.com/auth/structuredcontent'; // what even is this
92
    const SCOPE_USER_PROVISIONING           = 'https://apps-apis.google.com/a/feeds/user/';
93
    const SCOPE_GROUPS_PROVISIONING         = 'https://apps-apis.google.com/a/feeds/groups/';
94
    const SCOPE_NICKNAME_PROVISIONING       = 'https://apps-apis.google.com/a/feeds/alias/';
95
96
    // Old
97
    const SCOPE_ORKUT                       = 'https://www.googleapis.com/auth/orkut';
98
    const SCOPE_GOOGLELATITUDE =
99
        'https://www.googleapis.com/auth/latitude.all.best https://www.googleapis.com/auth/latitude.all.city';
100
    const SCOPE_OPENID                      = 'openid';
101
102
    // YouTube
103
    const SCOPE_YOUTUBE_GDATA               = 'https://gdata.youtube.com';
104
    const SCOPE_YOUTUBE_ANALYTICS_MONETARY  = 'https://www.googleapis.com/auth/yt-analytics-monetary.readonly';
105
    const SCOPE_YOUTUBE_ANALYTICS           = 'https://www.googleapis.com/auth/yt-analytics.readonly';
106
    const SCOPE_YOUTUBE                     = 'https://www.googleapis.com/auth/youtube';
107
    const SCOPE_YOUTUBE_READ_ONLY           = 'https://www.googleapis.com/auth/youtube.readonly';
108
    const SCOPE_YOUTUBE_UPLOAD              = 'https://www.googleapis.com/auth/youtube.upload';
109
    const SCOPE_YOUTUBE_PARTNER             = 'https://www.googleapis.com/auth/youtubepartner';
110
    const SCOPE_YOUTUBE_PARTNER_AUDIT       = 'https://www.googleapis.com/auth/youtubepartner-channel-audit';
111
112
    // Google Glass
113
    const SCOPE_GLASS_TIMELINE              = 'https://www.googleapis.com/auth/glass.timeline';
114
    const SCOPE_GLASS_LOCATION              = 'https://www.googleapis.com/auth/glass.location';
115
116
    // Android Publisher
117
    const SCOPE_ANDROID_PUBLISHER           = 'https://www.googleapis.com/auth/androidpublisher';
118
119
    // Google Classroom
120
    const SCOPE_CLASSROOM_COURSES           = 'https://www.googleapis.com/auth/classroom.courses';
121
    const SCOPE_CLASSROOM_COURSES_READONLY  = 'https://www.googleapis.com/auth/classroom.courses.readonly';
122
    const SCOPE_CLASSROOM_PROFILE_EMAILS    = 'https://www.googleapis.com/auth/classroom.profile.emails';
123
    const SCOPE_CLASSROOM_PROFILE_PHOTOS    = 'https://www.googleapis.com/auth/classroom.profile.photos';
124
    const SCOPE_CLASSROOM_ROSTERS           = 'https://www.googleapis.com/auth/classroom.rosters';
125
    const SCOPE_CLASSROOM_ROSTERS_READONLY  = 'https://www.googleapis.com/auth/classroom.rosters.readonly';
126
127
    protected $accessType = 'online';
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    protected function init()
133
    {
134
        $this->stateParameterInAuthUrl = true;
135
136
        if( $this->baseApiUri === null ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
Coding Style introduced by
Expected 0 spaces before closing bracket; 1 found
Loading history...
137
            $this->baseApiUri = new Uri('https://www.googleapis.com/oauth2/v1/');
138
        }
139
    }
140
141
    public function setAccessType($accessType)
142
    {
143
        if (!in_array($accessType, array('online', 'offline'), true)) {
144
            throw new InvalidAccessTypeException('Invalid accessType, expected either online or offline');
145
        }
146
        $this->accessType = $accessType;
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     */
152
    public function getAuthorizationEndpoint()
153
    {
154
        return new Uri('https://accounts.google.com/o/oauth2/auth?access_type=' . $this->accessType);
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160
    public function getAccessTokenEndpoint()
161
    {
162
        return new Uri('https://accounts.google.com/o/oauth2/token');
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168
    protected function parseAccessTokenResponse($responseBody)
169
    {
170
        $data = json_decode($responseBody, true);
171
172
        if (null === $data || !is_array($data)) {
173
            throw new TokenResponseException('Unable to parse response.');
174
        } elseif (isset($data['error'])) {
175
            throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"');
176
        }
177
178
        $token = new StdOAuth2Token();
179
        $token->setAccessToken($data['access_token']);
180
        $token->setLifetime($data['expires_in']);
181
182
        if (isset($data['refresh_token'])) {
183
            $token->setRefreshToken($data['refresh_token']);
184
            unset($data['refresh_token']);
185
        } else {
186
            # Keep old refresh token when we use offline access type
187
            if($oldToken = $this->storage->retrieveAccessToken($this->service(), $this->account())) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
188
                $token->setRefreshToken($oldToken->getRefreshToken());
189
            }
190
        }
191
192
        unset($data['access_token']);
193
        unset($data['expires_in']);
194
195
        $token->setExtraParams($data);
196
197
        return $token;
198
    }
199
}
200