madtyn
madtyn

Reputation: 1549

Several error working with blogger/google API using python and service account auth

I'm trying to access blogger API using the official Google python library and a service account with a JSON key file made at the Google Developer console.

I'm using Linux Debian.

google-api-python-client=2.65.0

The thing is that I'm getting this traceback:

Traceback (most recent call last):
  File "/path/to/myproject/lib/python3.9/site-packages/googleapiclient/discovery.py", line 287, in build
    content = _retrieve_discovery_doc(
  File "/path/to/myproject/lib/python3.9/site-packages/googleapiclient/discovery.py", line 422, in _retrieve_discovery_doc
    resp, content = req.execute(num_retries=num_retries)
  File "/path/to/myproject/lib/python3.9/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/path/to/myproject/lib/python3.9/site-packages/googleapiclient/http.py", line 923, in execute
    resp, content = _retry_request(
  File "/path/to/myproject/lib/python3.9/site-packages/googleapiclient/http.py", line 191, in _retry_request
    resp, content = http.request(uri, method, *args, **kwargs)
  File "/path/to/myproject/lib/python3.9/site-packages/httplib2/__init__.py", line 1322, in request
    (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
  File "/path/to/myproject/lib/python3.9/site-packages/httplib2/__init__.py", line 1072, in _request
    (response, content) = self._conn_request(conn, request_uri, method, body, headers)
  File "/path/to/myproject/lib/python3.9/site-packages/httplib2/__init__.py", line 996, in _conn_request
    conn.request(method, request_uri, body, headers)
  File "/usr/lib/python3.9/http/client.py", line 1279, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1325, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1274, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1034, in _send_output
    self.send(msg)
  File "/usr/lib/python3.9/http/client.py", line 995, in send
    self.sock.sendall(data)
OSError: [Errno 9] Bad file descriptor

Which point to some sort of error at the OS when opening some file, but I can't imagine which is the file that is causing trouble. The credentials seem like are doing all right when recovered from the json file and at the moment of the exception is just sending this:

b'GET /discovery/v1/apis/blogger/v3/rest HTTP/1.1\r\nHost: www.googleapis.com\r\ncontent-length: 0\r\nuser-agent: Python-httplib2/0.10.3 (gzip)\r\naccept-encoding: gzip, deflate\r\n\r\n'

through the internet. This also seems to do fine from my browser.

The code is here below:

import json

import google.auth
from google.oauth2 import service_account
import googleapiclient.discovery
from oauth2client import client
from oauth2client.service_account import ServiceAccountCredentials

SCOPES = ['https://www.googleapis.com/auth/blogger']


def get_key_dict():
    SERVICE_ACCOUNT_FILE = '/path/to/myproject/apis/blogger/private_secrets.json'
    with open(SERVICE_ACCOUNT_FILE, 'r') as keyfile:
        return json.load(keyfile)

key_dict = get_key_dict()
credentials = ServiceAccountCredentials.from_json_keyfile_dict(key_dict, scopes=SCOPES)

# Here it breaks!
service = googleapiclient.discovery.build('blogger', 'v3', credentials=credentials, static_discovery=False,)

try:
    users = service.users()

    # Retrieve this user's profile information
    thisuser = users.get(userId="self").execute()
    print("This user's display name is: %s" % thisuser["displayName"])

    blogs = service.blogs()

    # Retrieve the list of Blogs this user has write privileges on
    thisusersblogs = blogs.listByUser(userId="self").execute()
    for blog in thisusersblogs["items"]:
        print("The blog named '%s' is at: %s" % (blog["name"], blog["url"]))

    posts = service.posts()

    # List the posts for each blog this user has
    for blog in thisusersblogs["items"]:
        print("The posts for %s:" % blog["name"])
        request = posts.list(blogId=blog["id"])
        while request != None:
            posts_doc = request.execute()
            if "items" in posts_doc and not (posts_doc["items"] is None):
                for post in posts_doc["items"]:
                    print("  %s (%s)" % (post["title"], post["url"]))
            request = posts.list_next(request, posts_doc)

except client.AccessTokenRefreshError:
    print(
        "The credentials have been revoked or expired, please re-run"
        "the application to re-authorize"
    )

Upvotes: 0

Views: 214

Answers (1)

Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 116996

if you check the documentation Authorizing requests and identifying your application you will find that it states that you can use Oauth2 for authorizing a user to the blogger api and api keys. There is no mention of using service account authorization with this api.

To my knowledge as i tried about five years ago this api does not support service account authentication. You will need to use Oauth2.

Upvotes: 1

Related Questions