1 # https://developers.google.com/accounts/docs/OAuth2ForDevices
2 # https://developers.google.com/drive/web/auth/web-server
3 # https://developers.google.com/google-apps/calendar/v3/reference/calendars
4 # https://developers.google.com/picasa-web/
9 import httplib # python2
11 import http.client # python3
15 from oauth2client.client import OAuth2Credentials
16 import gdata.calendar.service
17 import gdata.docs.service
18 import gdata.photos.service, gdata.photos
19 from apiclient.discovery import build
21 from apiclient.discovery import build
26 def __init__(self, client_id, client_secret):
27 print "Initializing oauth token..."
28 self.client_id = client_id
29 self.client_secret = client_secret
30 #print 'Client id: %s' % (client_id)
31 #print 'Client secret: %s' % (client_secret)
33 self.device_code = None
34 self.verfication_url = None
35 self.token_file = 'client_secrets.json'
37 #'https://www.googleapis.com/auth/calendar',
38 #'https://www.googleapis.com/auth/drive',
39 'https://docs.google.com/feeds',
40 'https://www.googleapis.com/auth/calendar.readonly',
41 'https://picasaweb.google.com/data/',
42 'https://photos.googleapis.com/data/',
43 #'http://picasaweb.google.com/data/',
44 #'https://www.google.com/calendar/feeds/',
46 self.host = 'accounts.google.com'
47 self.reset_connection()
52 # this setup is isolated because it eventually generates a BadStatusLine
53 # exception, after which we always get httplib.CannotSendRequest errors.
54 # When this happens, we try re-creating the exception.
55 def reset_connection(self):
56 self.ssl_ctx = ssl.create_default_context(cafile='/usr/local/etc/ssl/cert.pem')
57 httplib.HTTPConnection.debuglevel = 2
58 self.conn = httplib.HTTPSConnection(self.host, context=self.ssl_ctx)
62 if os.path.isfile(self.token_file):
63 f = open(self.token_file)
65 self.token = json.loads(json_token)
69 f = open(self.token_file, 'w')
70 f.write(json.dumps(self.token))
74 if self.token != None:
75 print "We have a token!"
77 print "We have no token."
78 return self.token != None
80 def get_user_code(self):
83 "/o/oauth2/device/code",
85 'client_id': self.client_id,
86 'scope' : ' '.join(self.scope)
88 {"Content-type": "application/x-www-form-urlencoded"})
89 response = self.conn.getresponse()
90 if response.status == 200:
91 data = json.loads(response.read())
92 self.device_code = data['device_code']
93 self.user_code = data['user_code']
94 self.verification_url = data['verification_url']
95 self.retry_interval = data['interval']
100 return self.user_code
102 def get_new_token(self):
103 # call get_device_code if not already set
104 if not self.user_code:
105 print "getting user code"
108 while self.token == None:
113 'client_id' : self.client_id,
114 'client_secret' : self.client_secret,
115 'code' : self.device_code,
116 'grant_type' : 'http://oauth.net/grant_type/device/1.0'
118 {"Content-type": "application/x-www-form-urlencoded"})
119 response = self.conn.getresponse()
120 if response.status == 200:
121 data = json.loads(response.read())
122 if 'access_token' in data:
126 time.sleep(self.retry_interval + 2)
128 print "failed to get token"
129 print response.status
130 print response.read()
132 def refresh_token(self):
133 if self.checking_too_often():
134 print "Not refreshing yet, too soon..."
137 print 'Trying to refresh oauth token...'
138 self.reset_connection()
139 refresh_token = self.token['refresh_token']
144 'client_id' : self.client_id,
145 'client_secret' : self.client_secret,
146 'refresh_token' : refresh_token,
147 'grant_type' : 'refresh_token'
149 {"Content-type": "application/x-www-form-urlencoded"})
151 response = self.conn.getresponse()
152 self.last_action = time.time()
153 if response.status == 200:
154 data = json.loads(response.read())
155 if 'access_token' in data:
157 # in fact we NEVER get a new refresh token at this point
158 if not 'refresh_token' in self.token:
159 self.token['refresh_token'] = refresh_token
162 print "Unexpected response %d to renewal request" % response.status
163 print response.read()
166 def checking_too_often(self):
168 return (now - self.last_action) <= 30
170 # https://developers.google.com/picasa-web/
171 def photos_service(self):
173 "Authorization": "%s %s" % (self.token['token_type'], self.token['access_token'])
175 client = gdata.photos.service.PhotosService(additional_headers=headers)
178 # https://developers.google.com/drive/
179 def docs_service(self):
180 cred = OAuth2Credentials(self.token['access_token'],
183 self.token['refresh_token'],
184 datetime.datetime.now(),
185 'http://accounts.google.com/o/oauth2/token',
187 http = httplib2.Http(disable_ssl_certificate_validation=True)
188 http = cred.authorize(http)
189 service = build('drive', 'v2', http)
192 # https://developers.google.com/google-apps/calendar/
193 def calendar_service(self):
194 cred = OAuth2Credentials(self.token['access_token'],
197 self.token['refresh_token'],
198 datetime.datetime.now(),
199 'http://accounts.google.com/o/oauth2/token',
201 http = httplib2.Http(disable_ssl_certificate_validation=True)
202 http = cred.authorize(http)
203 service = build('calendar', 'v3', http)