Export to GitHub

google-api-python-client - issue #342

oauth2client on GCE throws AttributeError no attribute redirect_uri


Posted on May 12, 2015 by Happy Giraffe

[Use this form for both apiclient and oauth2client issues]

What steps will reproduce the problem? 1. I am porting an Python 2.7 script to a new GCE 2. The script runs on local laptop and connects to BigQuery perfectly 3. The script throws error when run on GCE instance

What is the expected output? What do you see instead? When run on local laptop all is good. But, when run on a new GCE which I build 2 hours ago with the latest client API, the script throws the following error after the client creates the flow:

_HAVE_FLOW: True TEST _HAVE_FLOW: True have storage, next use it to retrieve credential from file: bigquery_credentials.dat ERROR - credentials is None Run oauth2 flow with default arguments - Write_CVS_Records_to_BigQuery() Unexpected error: <type 'exceptions.AttributeError'> Write_CVS_Records_to_BigQuery() AttributeError: 'NoneType' object has no attribute 'redirect_uri' CLOUDSDK_CONFIG: /home/.../.config/gcloud GOOGLE_APPLICATION_CREDENTIALS: client_secret_Xkjduoiyewryq3.apps.googleusercontent.com.json

GCLOUD_DATASET_ID: applied-algebra-93003

Traceback (most recent call last): File "/dump/CI_SA_load_bq.py", line 221, in Write_CVS_Records_to_BigQuery credentials = tools.run_flow(_FLOW, storage, tools.argparser.parse_args([])) File "/usr/lib/python2.7/site-packages/oauth2client/util.py", line 137, in positional_wrapper return wrapped(*args, **kwargs) File "/usr/lib/python2.7/site-packages/oauth2client/tools.py", line 190, in run_flow flow.redirect_uri = oauth_callback

AttributeError: 'NoneType' object has no attribute 'redirect_uri'

Traceback (most recent call last): File "/dump/CI_SA_load_bq.py", line 266, in <module> Write_CVS_Records_to_BigQuery() File "/dump/CI_SA_load_bq.py", line 221, in Write_CVS_Records_to_BigQuery credentials = tools.run_flow(_FLOW, storage, tools.argparser.parse_args([])) File "/usr/lib/python2.7/site-packages/oauth2client/util.py", line 137, in positional_wrapper return wrapped(*args, **kwargs) File "/usr/lib/python2.7/site-packages/oauth2client/tools.py", line 190, in run_flow flow.redirect_uri = oauth_callback AttributeError: 'NoneType' object has no attribute 'redirect_uri' ~]$

What version of the product are you using? On what operating system? The latest verion installed by pip. The most recent Centos version of GCE

Please provide any additional information below.

More than likely this is a configuration problem on the GCE; I've likely missed adding some setting required on a GCE instance. Here's the 2 suspect methods related to the AttributeError:

_SECRET_FILE_NAME='client_secret_devgce2.apps.googleusercontent.com.json' _REDIRECT_URI='urn:ietf:wg:oauth:2.0:oob'

Set up flow object to be used for authenticating the client

def Get_Client_Flow(): try: if os.path.exists(_SECRET_FOLDER_NAME): print "_SECRET_FOLDER_NAME: %s exists"%(str(_SECRET_FOLDER_NAME)) _SECRET_FILE = os.path.join(_SECRET_FOLDER_NAME,_SECRET_FILE_NAME) if os.path.isfile(_SECRET_FILE):
print "_SECRET_FILE: %s exists"%(_SECRET_FILE)
_HAVE_SECRET_FILE=True _FLOW = flow_from_clientsecrets(_SECRET_FILE, scope='https://www.googleapis.com/auth/bigquery', redirect_uri=_REDIRECT_URI) if not _FLOW==None: _HAVE_FLOW.append(True) print ("_HAVE_FLOW: %s")%(_HAVE_FLOW[0]) else: _HAVE_FLOW.append(False) print ("_HAVE_FLOW: %s")%(_HAVE_FLOW[0]) else: print "_SECRET_FILE: %s does not exist"%(str(_SECRET_FILE)) else: print "_SECRET_FOLDER_NAME: %s does not exist"%(str(_SECRET_FOLDER_NAME))

except Exception, inst:
    print &quot;\n - Get_Client_Flow() Unexpected error: %s&quot;%(str(sys.exc_info()[0]))
    if isinstance(inst,ValueError):
        print &quot;Get_Client_Flow() - ValueError: %s\n&quot;%(inst.message)
    if isinstance(inst,AttributeError):
        print &quot;Get_Client_Flow() - AttributeError: %s\n&quot;%(inst.message)
    if isinstance(inst,TypeError):
        print &quot;Get_Client_Flow() - TypeError: %s\n&quot;%(inst.message)      
    #print &quot;\nPYTHONPATH: %s&quot; % (os.environ['PYTHONPATH'])
    print &quot;CLOUDSDK_CONFIG: %s&quot; %  (os.environ['CLOUDSDK_CONFIG'])
    print &quot;GOOGLE_APPLICATION_CREDENTIALS: %s&quot;%(os.environ['GOOGLE_APPLICATION_CREDENTIALS'])
    print &quot;GCLOUD_DATASET_ID: %s&quot;%(os.environ['GCLOUD_DATASET_ID'])    
    print '-'*60
    traceback.print_exc(file=sys.stdout)
    print '-'*60                            
    raise  

def Write_CVS_Records_to_BigQuery(): try: print "\n Write_CVS_Records_to_BigQuery()" ''' Connect to BigQuery Service API ''' Get_Client_Flow()

    if _HAVE_FLOW[0]:
        print (&quot;TEST _HAVE_FLOW: %s&quot;)%(_HAVE_FLOW[0])
        #_FLOW.redirect_uri = _REDIRECT_URI

        # GET oauth2client STORAGE
        storage = Storage('bigquery_credentials.dat')
        if storage is None:
            print &quot;storage is None, error creating means for retrieving credential from file: %s&quot;%('bigquery_credentials.dat')
        else:
            print &quot;have storage, next use it to retrieve credential from file: %s&quot;%('bigquery_credentials.dat')
            credentials = storage.get()
            if credentials is None:
                print &quot;ERROR - credentials is None&quot;

        if credentials is None or credentials.invalid:
            print &quot;Run oauth2 flow with default arguments&quot;
            # Run oauth2 flow with default arguments.
            credentials = tools.run_flow(_FLOW, storage, tools.argparser.parse_args([]))

        # create the HTTP object to handle your requests, and authorize with your credentials
        http = httplib2.Http()
        http = credentials.authorize(http)

        # create the service object for interacting with BigQuery
        _BIGQUERY_SERVICE = build('bigquery', 'v2', http=http)

        print (&quot;BEGIN call to loadTable()&quot;)
        try:
            #print &quot;did not call loadTable()&quot;
            loadTable(_BIGQUERY_SERVICE, _PROJECT_NUMBER, _BIGQUERY_DATASET_ID, _TARGET_TABLE_ID, _SOURCE_CSV)

        except HttpError as err:
            print 'Write_CVS_Records_to_BigQuery() HttpError:', pprint.pprint(err.resp)
            print 'Write_CVS_Records_to_BigQuery()- HttpError content: %s: '%(err.content)
            print 'Write_CVS_Records_to_BigQuery() HttpError uri - loadTable(): ', pprint.pprint(err.uri)

        except AccessTokenRefreshError:
            print (&quot;Write_CVS_Records_to_BigQuery() - Credentials have been revoked or expired, please re-run&quot;
                   &quot;the application to re-authorize&quot;)
    else:
        print (&quot;TEST _HAVE_FLOW: %s&quot;)%(_HAVE_FLOW[0])

except Exception, inst:
    print &quot;\n - Write_CVS_Records_to_BigQuery() Unexpected error: %s&quot;%(str(sys.exc_info()[0]))
    if isinstance(inst,ValueError):
        print &quot;Write_CVS_Records_to_BigQuery() ValueError: %s\n&quot;%(inst.message)
    if isinstance(inst,AttributeError):
        print &quot;Write_CVS_Records_to_BigQuery() AttributeError: %s\n&quot;%(inst.message)
    if isinstance(inst,TypeError):
        print &quot;Write_CVS_Records_to_BigQuery()TypeError: %s\n&quot;%(inst.message)      
    #print &quot;\nPYTHONPATH: %s&quot; % (os.environ['PYTHONPATH'])
    print &quot;CLOUDSDK_CONFIG: %s&quot; %  (os.environ['CLOUDSDK_CONFIG'])
    print &quot;GOOGLE_APPLICATION_CREDENTIALS: %s&quot;%(os.environ['GOOGLE_APPLICATION_CREDENTIALS'])
    print &quot;GCLOUD_DATASET_ID: %s&quot;%(os.environ['GCLOUD_DATASET_ID'])    
    print '-'*60
    traceback.print_exc(file=sys.stdout)
    print '-'*60                            
    raise

This is not likely, in my view, a bug with the API, but a matter of an omitted setting in the code or in the .bashrc file. The only difference in the code that runs on the laptop and the code that fails to run on the GCE is the new addition of _REDIRECT_URI (when creating the flow object)

Any suggestions to fix this mis-configuration are appreciated.

Comment #1

Posted on May 12, 2015 by Happy Giraffe

I edited the client secret file to contain "redirect_uris":["http://localhost", "urn:ietf:wg:oauth:2.0:oob"], and I assigned these to the _REDIRECT_URI array as well, but the same error is thrown.

Status: New

Labels:
Type-Defect Priority-Medium