Search code examples
pythongoogle-appsgoogle-apps-marketplace

Permission problems with Google Apps Marketplace


We created an application for Google Apps Marketplace, and we want to add a new feature - get all the domain's user defined schemas. But I didn't find out how to grant our application permission to do it. Do we have to get permission again from all our customers? Or maybe create a new Google Apps Marketplace application and ask permission for it only from the customers who need it? (not all our customers need this feature).

Here is my code, it fails in two ways:

class EmailSettingsClient:
    headers = None
    domain = None

    def __init__(self, admin_email):
        self.initCredentials(admin_email)
        logging.debug("headers={}".format(self.headers))

    def initCredentials(self, admin_email):
        http = httplib2.Http()
        credentials = SignedJwtAssertionCredentials(
            SERVICE_EMAIL, 
            PRIVATE_KEY, 
            scope='https://apps-apis.google.com/a/feeds/emailsettings/2.0/ https://www.googleapis.com/auth/admin.directory.user.readonly https://www.googleapis.com/auth/admin.directory.userschema.readonly',
            sub=str(admin_email) # it doesn't work with this line.
        )
        http = credentials.authorize(http)
        service = build(serviceName='admin', version='directory_v1', http=http)
        creds = credentials.to_json()
        access_token  = credentials.token_response['access_token']
        self.headers = {
            'Content-type': 'application/atom+xml',
            'Authorization': 'Bearer '+access_token
        }

    def get_all_domain_custom_schemas(self, feed_uri):
        customer_id = "..." # domain customerId
        logging.debug("EmailSettingsClient::get_all_domain_custom_schemas, feed_uri = {}, customerId = {} .".format(feed_uri, customer_id))
        request_url = 'https://www.googleapis.com/admin/directory/v1/customer/{}/schemas'.format(customer_id)
        reply = requests.get(request_url, headers=self.headers)
        # data = json.loads(reply.content)
        logging.info(reply.content)
        customer_id = "my_customer"
        logging.debug("EmailSettingsClient::get_all_domain_custom_schemas, feed_uri = {}, customerId = {} .".format(feed_uri, customer_id))
        request_url = 'https://www.googleapis.com/admin/directory/v1/customer/{}/schemas'.format(customer_id)
        reply = requests.get(request_url, headers=self.headers)
        # data = json.loads(reply.content)
        logging.info(reply.content)

class GetAllDomainCustomSchemasHandler(RequestHandler):
    def post(self):
        return self.get()

    def get(self):
        domain_str = self.request.get('domain')
        domain = Domain.get_by_key_name(domain_str)
        feed_uri = self.request.get('feed_uri', "")

        email_settings_client = EmailSettingsClient(domain.admin)
        email_settings_client.get_all_domain_custom_schemas(feed_uri)
        return

One, it throws an exception if we use the "sub" parameter from another user with the domain admin's email address. And Two, if I don't include the "sub" parameter and run the application from the domain admin's account, it returns an error message: When I tried with the domain customerId, I got this error message:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "forbidden",
    "message": "Not Authorized to access this resource/api"
   }
  ],
  "code": 403,
  "message": "Not Authorized to access this resource/api"
 }
}

And when I tried with "my_customer", I got this error message:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "backendError",
    "message": "Service unavailable. Please try again"
   }
  ],
  "code": 503,
  "message": "Service unavailable. Please try again"
 }
}

I'm sure I missed something, but I didn't find out how to make it work. Any suggestions?


Solution

  • Eventually I found out that we can add this permission in the Google Developers Console, under APIs / Google Apps Marketplace SDK / Configuration. I added https://www.googleapis.com/auth/admin.directory.userschema.readonly, and each domain admin has to approve the new permissions. If you have more information you can edit this answer or post a new answer.