client_idとcient_secretだけからgoogle authのtoken情報を取得する方法
こんな感じでやれば良い。書きかけ。飽きたので途中でおしまい。
prepare
pip install google-auth-oauthlib python-dotenv
run
以下が必要。
- アプリがRPに権限を要求するときのclient id, client secret
- 権限を要求するscopes
client id, client secret
print(credentials.to_json())
の結果などはキャッシュしておくと良い。
CLIENT_IDとCLIENT_SECRETを環境変数から受け取っている。client idやclient secretの情報はこの辺りにあるはず。なければ作る。
scopes
scopeはAPIによって調整する必要がある。scopeを調べるときはこのあたりを見ると良い。
run
テキトーに自分のドライブのspreadsheetを持ってくる。google-api-python-clientは使っていない。
import os import dotenv import google_auth_oauthlib import requests from google.oauth2.credentials import Credentials from google.auth.transport.requests import Request, AuthorizedSession def get_credentials() -> Credentials: dotenv.load_dotenv() client_id = os.environ["CLIENT_ID"] client_secret = os.environ["CLIENT_SECRET"] scopes = [ "https://www.googleapis.com/auth/drive", ] credentials = google_auth_oauthlib.get_user_credentials( scopes, client_id, client_secret ) return credentials def get_session(credentials: Credentials) -> AuthorizedSession: return AuthorizedSession(credentials=credentials) def iterate_spreadsheets(session: AuthorizedSession): page_token = "" url = "https://www.googleapis.com/drive/v3/files" params = { "q": "mimeType='application/vnd.google-apps.spreadsheet'", "pageSize": 1000, "supportsTeamDrives": True, "includeTeamDriveItems": True, "fields": "nextPageToken,files(name,id)", } while page_token is not None: if page_token: params["pageToken"] = page_token res = session.request("get", url, params=params) assert res.status_code == 200, res.status_code data = res.json() for file in data.get("files", []): yield file page_token = data.get("nextPageToken", None) if page_token is None: break credentials = get_credentials() print(credentials.to_json()) print(credentials.token) print(credentials.valid) print(credentials.refresh(Request())) session = get_session(credentials) assert isinstance(session, requests.Session), session.__class__.mro() for file in iterate_spreadsheets(session): print(f'Found file: {file.get("name")} ({file.get("id")})')
こんな感じで動く。
$ python 00sheets.py Found file: Where is the money Lebowski? (1HfOblsBJfbG0mNyXS1hbUpkG_OpOpMJTgUwDuzSA1W4) Found file: 企業別福利厚生・就業規定・ITポリシーリスト (11DAp3g9zwcRznIf8EFIKmMR10vtRPNNDqHIwx5Zsj3I) Found file: populations (102x3SPWP8vN4L922_GjyXJa7VenPq1AWtbRpC4PRhGk) ...
CONF ?= ~/.config/cliauth/google-client-secrets.json export CLIENT_ID ?= $(shell jqfpy "get('installed/client_id')" $(CONF) -r) export CLIENT_SECRET ?= $(shell jqfpy "get('installed/client_secret')" $(CONF) -r) 00: python $(shell echo $@*.py)
.env ここに書くのではなくこういう感じで設定するよという例 (Makefileがあるので不要かも)。
CLIENT_ID = "xxxx" CLIENT_SECRET = "xxxx"
gist
https://gist.github.com/podhmo/2d0baf179689db5868b32a43654a1bc0
詳細
:warning: ここから下は書きかけのメモ。
TODO: あとで書く
- oauth2lib is depreacated, using oauthlib
- token情報をキャッシュしておく方法
- AuthorizedSessionは毎回refresh tokenからaccess tokenを生成し直している
- revoke tokenの方法
- InstalledAppFlowは
run_console()
ではなくrun_local_server()
の方が便利 - 実は google-auth-oauthlibにコマンドが用意されている。
- ↑の例はoauth2 client idの話
- サービスアカウントの場合は
google.auth
の機能を使うともっと手軽 - ものによっては環境変数にファイルのパスを書くだけで良い
oauth2client is deprecated
https://pypi.org/project/oauth2client/
Note: oauth2client is now deprecated. No more features will be added to the libraries and the core team is turning down support. We recommend you use google-auth and oauthlib.
理由はこのあたり
https://google-auth.readthedocs.io/en/latest/oauth2client-deprecation.html
認証のタイプ
認証のタイプは?
- OAuth2.0 クライアント ID
- サービスアカウント キー
- https://cloud.google.com/docs/authentication/?hl=ja&_ga=2.126156429.-1432081073.1509175144
tokenのキャッシュなども気にした場合
素直にドキュメントを読めば読むと良い。こちらはpython-google-api-clientを使っている例。入力が特定のf−マットに従ったファイルなのがちょっと読み替えが必要でだるいかもしれない。
import pickle import os.path from googleapiclient.discovery import build from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request # If modifying these scopes, delete the file token.pickle. SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly'] # The ID and range of a sample spreadsheet. SAMPLE_SPREADSHEET_ID = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms' SAMPLE_RANGE_NAME = 'Class Data!A2:E' def main(): """Shows basic usage of the Sheets API. Prints values from a sample spreadsheet. """ creds = None # The file token.pickle stores the user's access and refresh tokens, and is # created automatically when the authorization flow completes for the first # time. if os.path.exists('token.pickle'): with open('token.pickle', 'rb') as token: creds = pickle.load(token) # If there are no (valid) credentials available, let the user log in. if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( 'credentials.json', SCOPES) creds = flow.run_local_server(port=0) # Save the credentials for the next run with open('token.pickle', 'wb') as token: pickle.dump(creds, token) service = build('sheets', 'v4', credentials=creds) # Call the Sheets API sheet = service.spreadsheets() result = sheet.values().get(spreadsheetId=SAMPLE_SPREADSHEET_ID, range=SAMPLE_RANGE_NAME).execute() values = result.get('values', []) if not values: print('No data found.') else: print('Name, Major:') for row in values: # Print columns A and E, which correspond to indices 0 and 4. print('%s, %s' % (row[0], row[4])) if __name__ == '__main__': main()
実は google-auth-oauthlibにコマンドが用意されている
$ python -m google_auth_oauthlib.tool --help Usage: __main__.py [OPTIONS] Command-line tool for obtaining authorization and credentials from a user. This tool uses the OAuth 2.0 Authorization Code grant as described in section 1.3.1 of RFC6749: https://tools.ietf.org/html/rfc6749#section-1.3.1 This tool is intended for assist developers in obtaining credentials for testing applications where it may not be possible or easy to run a complete OAuth 2.0 authorization flow, especially in the case of code samples or embedded devices without input / display capabilities. This is not intended for production use where a combination of companion and on-device applications should complete the OAuth 2.0 authorization flow to get authorization from the users. Options: --client-secrets <client_secret_json_file> Path to OAuth2 client secret JSON file. [required] --scope <oauth2 scope> API scopes to authorize access for. [required] --save Save the credentials to file. [default: False] --credentials <oauth2_credentials> Path to store OAuth2 credentials. [default: /Users/nao/Library/Application Support/google-oauthlib- tool/credentials.json] --headless Run a console based flow. [default: False] --help Show this message and exit.