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:
    > 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/accounts/docs/OAuth2#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: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.

    --
    regards,
    kushal
     
    Kushal Kumaran, Sep 26, 2012
    #1
    1. Advertising

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
    Replies:
    3
    Views:
    181
    Roy Smith
    Sep 28, 2011
  2. Ethan Herdrick
    Replies:
    1
    Views:
    110
    Ethan Herdrick
    May 11, 2006
  3. Replies:
    0
    Views:
    493
  4. Littlefield, Tyler

    google api and oauth2

    Littlefield, Tyler, Sep 25, 2012, in forum: Python
    Replies:
    0
    Views:
    199
    Littlefield, Tyler
    Sep 25, 2012
  5. Kushal Kumaran

    Re: google api and oauth2

    Kushal Kumaran, Sep 26, 2012, in forum: Python
    Replies:
    0
    Views:
    233
    Kushal Kumaran
    Sep 26, 2012
Loading...

Share This Page