I'm working on adding user profile photo management to my application. My 
app was already using the Profiles API and it's successfully able to 
hide/unhide users from the global GAL. However, when attempting to perform 
any sort of user profile photo management I'd get an "Authsub token has 
wrong scope" error. After some trial and error. I've found that the code 
fails if my OAuth token is scope for profiles:

https://www.google.com/m8/feeds/profiles   (according to 
http://code.google.com/googleapps/domain/profiles/developers_guide.html#Auth
)

but it works if I "widen" the scope to the Contacts API scope:

https://www.google.com/m8/feeds   (according to 
http://code.google.com/apis/contacts/docs/3.0/developers_guide.html#Auth)

attached is a simple app that demos the issue by attempting to get the 
profile photo for every user in a GA domain and save it to a file. It 
should fail OOB with the AuthSub error when attempting to grab the 1st 
photo but if line 73 is uncommented and 74 is commented and then oauth.txt 
is recreated (with Contacts API scope this time) it should work.

Jay

-- 
You received this message because you are subscribed to the Google
Groups "Google Contacts, Shared Contacts and User Profiles APIs" group.
To post to this group, send email to
[email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://code.google.com/apis/contacts/community/forum.html
#!/usr/bin/env python
#
# User Photo Manager
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""User Photo Manager (UPM) is a command line tool which allows Administrators to manage user profile photos"""

__author__ = '[email protected] (Jay Lee)'
__version__ = '0.1'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'

import pickle
import os
import gdata.apps.service
import gdata.contacts.service
import gdata.auth
import sys
import re
from optparse import OptionParser
import webbrowser

def SetupOptionParser():
  # Usage message is the module's docstring.
  parser = OptionParser(usage=__doc__)
  parser.add_option('--version',
    action='store_true',
    dest='version',
    help='just print User Profile Manager Version and then quit')
  parser.add_option('--debug',
    action='store_true',
    dest='debug',
    help='Turn on verbose debugging and connection information.')
  parser.add_option('--domain',
    dest='domain',
    help='Google Apps domain to use')
  return parser

def loadOAuth(gdataObject):
  global domain
  oauthfile = open('oauth.txt', 'r')
  domain = oauthfile.readline()[0:-1]
  token = pickle.load(oauthfile)
  oauthfile.close()
  gdataObject.domain = domain
  client_id = '711837411296.apps.googleusercontent.com'
  client_secret = 'A0R_LC-PU0YKJCwCb9N3Njxt'
  gdataObject.SetOAuthInputParameters(gdata.auth.OAuthSignatureMethod.HMAC_SHA1, consumer_key=client_id, consumer_secret=client_secret)
  token.oauth_input_params = gdataObject._oauth_input_params
  gdataObject.SetOAuthToken(token)
  
def doRequestOAuth(domain):
  api_key = 'AIzaSyAqi4Qo0Qrtx4FrEwIC4naWYF1q1I6Osa8'
  fetch_params = {'xoauth_displayname':'User Photo Manager',
                  'key':api_key}
  #scopes = ['https://www.google.com/m8/feeds/']                   # Contacts API
  scopes = ['https://www.google.com/m8/feeds/profiles']           # Profiles API
  apps = gdata.apps.service.AppsService(domain=domain)
  apps.source = 'User Photo Manager %s / %s / %s / ' % (__version__, __author__,
                   'Python %s.%s.%s %s' % (sys.version_info[0], 
                   sys.version_info[1], sys.version_info[2], sys.version_info[3]))
  client_id = 'anonymous'
  client_secret = 'anonymous'
  apps.SetOAuthInputParameters(gdata.auth.OAuthSignatureMethod.HMAC_SHA1, consumer_key=client_id, consumer_secret=client_secret)
  try:
    request_token = apps.FetchOAuthRequestToken(scopes=scopes, extra_parameters=fetch_params)
  except gdata.service.FetchingOAuthRequestTokenFailed, e:
    if str(e).find('Timestamp') != -1:
      print "In order to use OAuth, your system time needs to be correct.\nPlease fix your time and try again."
      sys.exit(5)
  url_params = {'hd': domain}
  url = apps.GenerateOAuthAuthorizationURL(request_token=request_token, extra_params=url_params)
  raw_input("\nNow User Photo Manager will open a web page in order for you to grant %s access. Make sure you are logged in as an Administrator of your Google Apps domain before granting access. Press the Enter key to open your browser." % fetch_params['xoauth_displayname'])
  try:
    webbrowser.open(str(url))
  except Exception, e:
    pass
  raw_input("\n\nYou should now see a web page asking you to grant %s\n"
            'access. If the page didn\'t open, you can manually\n'
            'go to %s to grant access.\n'
            '\n'
            'Once you\'ve granted access, press the Enter key.' % (fetch_params['xoauth_displayname'], url))
  try:
    final_token = apps.UpgradeToOAuthAccessToken(request_token)
  except gdata.service.TokenUpgradeFailed:
    print 'Failed to upgrade the token. Did you grant User Photo Manager access in your browser?'
    sys.exit(4)
  f = open('oauth.txt', 'w')
  f.write('%s\n' % domain)
  pickle.dump(final_token, f)
  f.close()

def main(argv):
  options_parser = SetupOptionParser()
  (options, args) = options_parser.parse_args()
  if options.version:
    print 'User Photo Manager %s' % __version__
    sys.exit(0)
  if not options.domain:
    options_parser.print_help()
    print "ERROR: --domain is required."
    return
  if not os.path.isfile('oauth.txt'):
    doRequestOAuth(options.domain)
  cs = gdata.contacts.service.ContactsService()
  if options.debug:
    cs.debug = True
  cs.ssl = True
  cs.source = 'User Photo Manager %s / %s / %s / ' % (__version__, __author__,
                   'Python %s.%s.%s %s' % (sys.version_info[0], 
                   sys.version_info[1], sys.version_info[2], sys.version_info[3]))
  loadOAuth(cs)
  profiles_feed = cs.GetProfilesFeed('/m8/feeds/profiles/domain/%s/full?v=3' % options.domain)
  for entry in profiles_feed.entry:
    user_address = entry.email[0].address.lower()
    user_domain = user_address[user_address.find('@')+1:]
    cs.domain = user_domain
    if user_address[:2] == '.@' or user_address[:27] == 'secure-data-connector-user@':
      continue
    print "Getting photo for %s:" % user_address
    try:
      photo = cs.GetPhoto(entry.link[0].href)
    except gdata.service.RequestError, e:
      print e
    filename = '%s.jpg' % (entry.email[0].address)
    photo_file = open(filename, 'wb')
    photo_file.write(photo)
    photo_file.close()

if __name__ == '__main__':
  try:
    main(sys.argv)
  except KeyboardInterrupt:
    sys.exit(4)

Reply via email to