gcloudやgoogle-api-python-clientの使うcredentialsを見る

メモ。

gcloud

sqliteにはいっているみたい

$ file ~/.config/gcloud/credentials.db 2>&1| sed "s@$HOME@HOME@"
HOME/.config/gcloud/credentials.db: SQLite 3.x database, last written using SQLite version 3024000

おもむろに取り出すと、access_token、refresh_tokenなどが見える。

$ sqlite3 ~/.config/gcloud/credentials.db
sqlite> .tables credentials
credentials
sqlite> .schema credentials
CREATE TABLE IF NOT EXISTS "credentials" (account_id TEXT PRIMARY KEY, value BLOB);
$ sqlite3 ~/.config/gcloud/credentials.db "select value from credentials;"
{
  "client_id": "xxxxxxxxxxx.apps.googleusercontent.com",
  "client_secret": "XxxxXXxXxxxxxxXxXXxxxxxx",
  "id_token": {
    "at_hash": "xxxxxXXxxxXXXXxXxXXxXX",
    "aud": "xxxxxxxxxxx.apps.googleusercontent.com",
    "azp": "xxxxxxxxxxx.apps.googleusercontent.com",
    "email": "xxxxxxxxx@gmail.com",
    "email_verified": true,
    "exp": xxxxxxxxxx,
    "iat": xxxxxxxxxx,
    "iss": "https://accounts.google.com",
    "sub": "xxxxxxxxxxxxxxxxxxxxx"
  },
  "refresh_token": "xxXxXXxxxXXXxxxxXXxXxXxXXxxXxxxxXxxXxXXxXxxXX",
  "revoke_uri": "https://accounts.google.com/o/oauth2/revoke",
  "scopes": [
    "https://www.googleapis.com/auth/compute",
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/cloud-platform",
    "https://www.googleapis.com/auth/appengine.admin",
    "https://www.googleapis.com/auth/accounts.reauth"
  ],
  "token_response": {
    "access_token": "xxxxxXxxXXxXxxxxXXxXXxxxXxxxxXXxXxxxXxXxxxXxXxxxxXxxxXxxXXXxXxXXXxXxxxxXxxxxxxXxXXxXxXxxXXxXXXxXXxxXxXXxXxxxxXxxxxxXXXxxXXXxXXxxx",
    "expires_in": 3600,
    "id_token": "xxXxxXxxXxXXXxXxXxXxXxxxXXXxXxXxXxxxXXXxXxXxXxXxXxXxXxXxXxxxXXXxXXXxXXXxXXxxXxXxXXXxxXxxxXxxxXxXxXxXxXxXXxxXXXxXXxxxXXxXxxxxxxxXXXxXXXxxxxxXXxxXxXxxXXxXxXxXXXxXxXxXXXxXXXxXXXxXxXxxXXxXxxxXxxxxXXxxxXxxxXxxxXxXxxxXxxxxxXxXxxxXXXxXXXxXXXxXXxxXXXxXXXxXXxxXxxxXXxxxXxxXxXxXxXxxxXxXxXXXxxxxXxxXxxxXxxxXXxxxXxxxxXxxXXxXXXxXxXxxXXxXxXxXxxxxxxxXxXxXXxxXXXXXXxxXXXXXxXXXXXxXxXXXxxxXXxxXxxxXXXxXXxxXXXxXXXxxxXxXxXxxXXxxxxxXxXxXxxxxxXxXxxxxxxxXXxxxxxxXXXxXXXxXxXxXxXxXXXxXxXxxXxxXXXxxXxxxxxXxxXXxxxXxxXxXxxXXXXxxXXXXxxxXxxXxxxxxxXxxXxXXxXXXxxxxXxXxxXXXXXxxxXxxXxxxXXXxXXXXxxXxxxxXXXxXxxxXxXXxxxxxXxXxXxXxxXxxXxxxxXXxXxxxXXxxXxxXxxXXxxxxXXxxxXxXxXXxXxxxXXXxXxXxxXxXXxXXXXXxxXxxXxxxxxxxxXxxXxXXXxxxXxXxXxxXxXXxXxXxxxxxxXxxxxxXxxxxXxxXxXxXxXXxxxxxXxXxXxxxXxXxxXxXxxxxXXxXxxxxXXXXxxxxxxXxxxxXXxXXxxXxXxXxXxxxxXxxxxxxxXxxxx",
    "refresh_token": "xxXxXXxxxXXXxxxxXXxXxXxXXxxXxxxxXxxXxXXxXxxXX",
    "scope": "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/accounts.reauth https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/appengine.admin",
    "token_type": "Bearer"
  },
  "token_uri": "https://www.googleapis.com/oauth2/v4/token",
  "type": "authorized_user",
  "user_agent": "google-cloud-sdk"
}

google-api-python-client

google-api-python-clientを使ったコードについて(たとえばこれとか)。

以下の部分が重要。

from oauth2client import file, client, tools

SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly'

def main():
    store = file.Storage('token.json')
    creds = store.get()
    if not creds or creds.invalid:
        flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
        creds = tools.run_flow(flow, store)
    service = build('sheets', 'v4', http=creds.authorize(Http()))
  1. oauth2client.file.Storageに入っている情報があればそれを使う(defaultでは"./token.json")
  2. なければ、oauth2client.tools.run_flowを使ってoauth2の認証に飛ぶ(このときcredentials.jsonを見る)

つまり、token.jsonaccess tokenなどが存在する。

token.json

{
  "_class": "OAuth2Credentials",
  "_module": "oauth2client.client",
  "access_token": "xxxxxXxxXXxXXxxxxXxxxXxxxxXXXxxxxXxxxXxxXXXXXxXxxxXXxXXXXxxxxxXXXxXXxxxXxxXxXxXXXXXxXxxxxXxxxXxxxxxxxxxxxxXXxxxXxxXxxxxxXxxXxxxxx",
  "client_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
  "client_secret": "xXxXxXxxxXxxXXxXxxXXxxXx",
  "id_token": null,
  "id_token_jwt": null,
  "invalid": false,
  "refresh_token": "xxxxxxXXXxxxXXXxXxXXxXxxxxxxxXXXXXxxxxXXxXXxXxxxxXxxXxXxxxxXXXxxxx",
  "revoke_uri": "https://accounts.google.com/o/oauth2/revoke",
  "scopes": [
    "https://www.googleapis.com/auth/spreadsheets.readonly"
  ],
  "token_expiry": "2018-09-03T14:58:14Z",
  "token_info_uri": "https://www.googleapis.com/oauth2/v3/tokeninfo",
  "token_response": {
    "access_token": "xxxxxXxxXXxXXxxxxXxxxXxxxxXXXxxxxXxxxXxxXXXXXxXxxxXXxXXXXxxxxxXXXxXXxxxXxxXxXxXXXXXxXxxxxXxxxXxxxxxxxxxxxxXXxxxXxxXxxxxxXxxXxxxxx",
    "expires_in": 3600,
    "refresh_token": "xxxxxxXXXxxxXXXxXxXXxXxxxxxxxXXXXXxxxxXXxXXxXxxxxXxxXxXxxxxXXXxxxx",
    "scope": "https://www.googleapis.com/auth/spreadsheets.readonly",
    "token_type": "Bearer"
  },
  "token_uri": "https://www.googleapis.com/oauth2/v3/token",
  "user_agent": null
}

ちなみにcredentials.jsonはこういうやつ。

{
  "installed": {
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "client_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
    "client_secret": "xXxXxXxxxXxxXXxXxxXXxxXx",
    "project_id": "xxxxxx-xxxxxxx-xxxxxx",
    "redirect_uris": [
      "urn:ietf:wg:oauth:2.0:oob",
      "http://localhost"
    ],
    "token_uri": "https://www.googleapis.com/oauth2/v3/token"
  }
}