Re: google api and oauth2

Discussion in 'Python' started by Kushal Kumaran, Sep 26, 2012.

  1. (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 <> 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:
    > (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:

    > 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

    #!/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 = ( +
    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' : '',
    'state' : 'init'
    url = ''
    params = ['{}={}'.format(key, urllib.parse.quote(value))
    for (key, value) in payload.items()]'{}?{}'.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 ='',
    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 ='',
    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 =
    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)
    return _get_new_token(config, token_file)

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

    client_id = <get your client id from google>
    client_secret = <get your client secret from google>
    redirect_uri = urn:ietf:wg:eek:auth:2.0:eek:ob
    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.

    Kushal Kumaran, Sep 26, 2012
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Aljosa Mohorovic

    oauth2 server implementation

    Aljosa Mohorovic, Sep 27, 2011, in forum: Python
    Roy Smith
    Sep 28, 2011
  2. Ethan Herdrick
    Ethan Herdrick
    May 11, 2006
  3. Replies:
  4. Littlefield, Tyler

    google api and oauth2

    Littlefield, Tyler, Sep 25, 2012, in forum: Python
    Littlefield, Tyler
    Sep 25, 2012
  5. Kushal Kumaran

    Re: google api and oauth2

    Kushal Kumaran, Sep 26, 2012, in forum: Python
    Kushal Kumaran
    Sep 26, 2012

Share This Page