いつも苦労するので備忘録として
pythonからGoogle OAuthする方法ですが、検索すると情報が古かったり、サービスアカウント使うやりかただったりして、個人のユーザーに対してサービス提供する為のやり方がいまいち分からなかったりしたのでまとめ。
必須事項
- GCP使ってAPIキーを取得する
- Google_Client_IDとGoogle_Client_Secretは必須です
- redirect_uriは、帰ってくるURLを入れてください。これはGCPに設定したものと同じである必要があります
OAuthするためのURIを生成する
GOOGLE_DISCOVERY_URL = (
"https://accounts.google.com/.well-known/openid-configuration"
)
def get_google_provider_cfg():
return requests.get(GOOGLE_DISCOVERY_URL).json()
def get_google_request_url():
google_provider_cfg = get_google_provider_cfg()
authorization_endpoint = google_provider_cfg["authorization_endpoint"]
google_client = WebApplicationClient(os.environ.get("Google_Client_ID"))
request_uri = google_client.prepare_request_uri(
authorization_endpoint,
redirect_uri=os.environ.get("redirect_uri"),
scope=['https://www.googleapis.com/auth/calendar.readonly','email','https://www.googleapis.com/auth/spreadsheets.readonly','https://www.googleapis.com/auth/documents.readonly','https://www.googleapis.com/auth/presentations.readonly'],
approval_prompt='force',
access_type="offline"
)
return request_uri
こんな感じでget_google_request_urlを使ってURLを作ってアクセスします
リダイレクト後の処理を書く
受け取った情報からトークンを取得する必要があります
ルートの設定(/google/callback)は、自分の環境に合わせて書き換えてください
ちなみに、この設定の場合はリダイレクトURLはこちらになります
http://localhost:5000/google/callback
@bolt.route("/google/callback", methods=["GET"])
def google_auth_callback(app_id):
# Googleから返却された認証コードを取得する
code = request.args.get("code")
#トークンを取得するためのURLを取得する
google_provider_cfg = get_google_provider_cfg()
token_endpoint = google_provider_cfg["token_endpoint"]
# トークンを取得するための情報を生成し、送信する
google_client = WebApplicationClient(os.environ.get("Google_Client_ID"))
token_url, headers, body = google_client.prepare_token_request(
token_endpoint,
authorization_response=request.url,
redirect_url=request.base_url,
code=code,
approval_prompt='force',
access_type='offline'
)
token_response = requests.post(
token_url,
headers=headers,
data=body,
auth=(os.environ.get("Google_Client_ID"), os.environ.get("Google_Client_Secret"),
)
google_access_token = token_response.json().get('access_token')
google_refresh_token = token_response.json().get('refresh_token')
以上の処理でgoogle_access_tokenとgoogle_refresh_tokenがとれます
google_refresh_tokenは一度しか取れないので注意してください(開発時に何度も取得すると思うのですが、revokeしないとrefresh_tokenは付与されないのです)
ローカル実行時の注意
ローカルで実行する場合は環境変数に
export OAUTHLIB_INSECURE_TRANSPORT=1
これを設定してください。
これをやらないと
google_client.prepare_token_request
のところで、httpsじゃないと駄目ですよと怒られます。
逆に本番環境でこれを入れると、それはそれで怒られます。