Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Re: google api and oauth2

Reply
Thread Tools

Re: google api and oauth2

 
 
Kushal Kumaran
Guest
Posts: n/a
 
      09-26-2012
(making no attempt to fix messed up quoting, please take a look at
your mail client configuration)

On Wed, Sep 26, 2012 at 1:52 AM, Littlefield, Tyler <(E-Mail Removed)> wrote:
> On 9/25/2012 2:05 PM, Demian Brecht wrote:
>
> This is a shameless plug, but if you want a much easier to understand method
> of accessing protected resources via OAuth2, I have a 55 LOC client
> implementation with docs and examples here:
> https://github.com/demianbrecht/sanction (Google is one of the tested
> providers with an access example).
>
>
> No complaints from me if it works. Honestly I was a bit discouraged at
> Google's decent lack of documentation and the quality of the code.
>


If you are writing a desktop application, read this:
https://developers.google.com/accoun...th2#clientside

>
> Are you trying to access resources client side (through Javascript) or
> server side? Either way, the redirect URI *is* important. The first step is
> to have your user authorize your application using Google's authorization
> page. As one of the query parameters, you must specify the redirect URI
> (which must match those registered through Google's app console).
>
> I'm trying to access it through a desktop Python application, which made me
> really confused. There was something else that talked about returning the
> tokens in a different way, but it talked about returning them in the title
> of the webpage, and since I'd be spawning a browser to request
> authorization, I'd have to write something that would pull the window
> information and then parse out the token from the title, which doesn't sound
> to stable.
>


After authenticating with google from a web browser, and authorizing
your application, the user will be presented with a web page from
which they can copy the access token (from the url or a text field
presented in the web page) and input into your application using
whatever mechanism you choose. If you are a simple text-based app,
you can just use input() to ask for the token.

If you are a GUI app, you can do other things, such as embedding a web
browser into your application and reading the redirected URL.

>
> Once the user has authorized your application, they're redirected back to
> your site (via the specified redirect URI), with a "code" attached as a
> query param. Once you get that code, you must exchange that with Google's
> token endpoint to retrieve the access and refresh tokens.
>
> Awesome. I could theoretically just create a webpage on my server to
> redirect people to with the query, but I'm still not quite sure how I'd
> retrieve that from the desktop application.
>
>
> No, it doesn't matter which library you use. Google's (imho) is overly
> verbose and difficult to grok (especially for someone new to either OAuth
> 2.0 or Python, or both). The client ID doesn't need to be kept private, but
> the secret does. You should *never* put this anywhere that can be read
> publicly.
>
> I plan on storing them both in variables. It's not going to be the best
> solution, but I plan to use python -O to create pyo files, which from what I
> understand are harder to decompile, and it'll be in a py2exe executable.
> Still not to hard to get at, but it's not right there either.
>


Don't worry about it. There is no way to keep it secret for desktop
applications. It is exactly the same as the DRM problem. The google
documentation itself admits: "... These applications, in general,
cannot keep secrets.". You should store the given tokens
persistently, though.

> <snipped>


In the past, I made a half-hearted attempt to writing something to
upload stuff to google calendar from .ics files. Here's the
google-authentication part of the code, if you can use it. I cannot,
at the moment, recall why I did not use the oauth2client library from
google.

#!/usr/bin/env python3
import datetime
import json
import os.path
import configparser
import requests
import webbrowser
import urllib.parse

def _store_tokens(auth_data, filename):
expiry_time = (datetime.datetime.now() +
datetime.timedelta(seconds=int(auth_data['expires_in'])))
auth_data['expiry_time'] = expiry_time.isoformat()
with open(filename, 'w') as file_stream:
json.dump(auth_data, file_stream)

def _get_new_token(config, token_file):
payload = {
'response_type' : 'code',
'client_id' : config['api']['client_id'],
'redirect_uri' : config['api']['redirect_uri'],
'scope' : 'https://www.googleapis.com/auth/calendar',
'state' : 'init'
}
url = 'https://accounts.google.com/o/oauth2/auth'
params = ['{}={}'.format(key, urllib.parse.quote(value))
for (key, value) in payload.items()]
webbrowser.open('{}?{}'.format(url, '&'.join(params)), new=2)
auth_code = input('Enter authorization code obtained: ')
payload = {
'code' : auth_code,
'client_id' : config['api']['client_id'],
'client_secret' : config['api']['client_secret'],
'redirect_uri' : config['api']['redirect_uri'],
'grant_type' : 'authorization_code'
}
r = requests.post('https://accounts.google.com/o/oauth2/token',
data=payload)
auth_data = json.loads(r.text)
_store_tokens(auth_data, token_file)
return auth_data['access_token']

def _refreshed_token(config, auth_data, token_file):
payload = {
'refresh_token' : auth_data['refresh_token'],
'client_id' : config['api']['client_id'],
'client_secret' : config['api']['client_secret'],
'grant_type' : 'refresh_token'
}
r = requests.post('https://accounts.google.com/o/oauth2/token',
data=payload)
auth_data = json.loads(r.text)
_store_tokens(auth_data, token_file)
return auth_data['access_token']

def _get_existing_token(config, token_file):
with open(token_file) as token_stream:
auth_data = json.load(token_stream)
now = datetime.datetime.now().isoformat()
if auth_data['expiry_time'] < now:
return _refreshed_token(config, auth_data, token_file)
return auth_data['access_token']

def auth(config):
token_file = os.path.expanduser(config['api']['token_file'])
if os.path.exists(token_file):
return _get_existing_token(config, token_file)
else:
return _get_new_token(config, token_file)

The "config" object required by the auth function is from a config
file that looks like this:

[api]
client_id = <get your client id from google>
client_secret = <get your client secret from google>
redirect_uri = urn:ietf:wgauth:2.0ob
token_file = ~/.google-tokens

The "scope" value in the _get_new_token function will need to be
changed to whatever scope your application needs. This code uses the
python requests module for http(s) requests. It will start up a web
browser to let the user authenticate and then asks for the token.

The google api will issue two tokens: an "access" token and a
"refresh" token. The access token will have a short expiry time,
after which you need to get another access token issued. You use the
refresh token for that reissue request.

--
regards,
kushal
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: google api and oauth2 Kushal Kumaran Python 0 09-26-2012 08:24 AM
google api and oauth2 Littlefield, Tyler Python 0 09-25-2012 07:04 PM
oauth2 server implementation Aljosa Mohorovic Python 3 09-28-2011 12:53 PM
Looking for Google API expert to consult on our Google hosted apps(calendar, maps, email, docs) styles@xlsuite.com Ruby 0 11-20-2007 04:21 AM
Ruby/Google (Ruby abstraction of Google API) is dead? Ethan Herdrick Ruby 1 05-11-2006 06:38 AM



Advertisments