Google APIの各種リソースに対する大抵の操作はREST風かつOAuth2なAPIになっていて、Access TokenとAPIのURLさえわかっていれば、例えば次のようにcurl
コマンドを使って簡単にAPIを実行できます。
curl -H "Authorization: Bearer $ACCESS_TOKEN" $ENDPOINT
OAuth2はラクチンで助かりますね。ただここで必要となるAccess Tokenは OAuth2 Flow と呼ばれる手順を用いて取得する必要があり、そこを理解していない人が多そうに思いました。実はこちらもすごい簡単で、curlとブラウザだけで認可フローを実行できるのです。
TL;DR
環境変数の設定
CLIENT_ID=...
CLIENT_SECRET=...
REDIRECT_URI=urn:ietf:wg:oauth:2.0:oob
SCOPE=SCOPE1%20SCOPE2%20
認可画面のURLを組み立て、ブラウザで開く
echo "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=$SCOPE&access_type=offline"
ブラウザに表示されたAuthorization Codeを使ってAccess Tokenを取得する
AUTHORIZATION_CODE=...
curl --data "code=$AUTHORIZATION_CODE" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "redirect_uri=$REDIRECT_URI" --data "grant_type=authorization_code" --data "access_type=offline" https://www.googleapis.com/oauth2/v4/token
Refresh Tokenを使って新しいAccess Tokenを取得する
REFRESH_TOKEN=...
curl --data "refresh_token=$REFRESH_TOKEN" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token
OAuth2 の認可フローの簡単な説明
登場人物は3者です。
- Application
- User(Browser)
認可フローは Google Identity Platformのリファレンスにも記述がありますが、Applicationの役割に注目すると、以下の二点を実装するだけです。
- Applicationが、ユーザの認可を得るためのページのURLをGoogleから取得し、Browserにリダイレクトとして送信する(Redirecting to Google's OAuth 2.0 server)
- ユーザが認可することで生成された
Authorization Code
をGoogleに渡してAccess Token
に交換してもらう(Handling the OAuth 2.0 server response)
CLIでの手順
Client IDの生成
Developer ConsoleのAPI Managerで、ClientIDを作成する必要があります。
Application Type
は「認可フロー(Access Tokenを取得するフロー)」の方法であって、APIを叩くときには関係ありません。よくあるのはWeb Application
ですが、Other
を選ぶとout of band
という種類で、いわゆるDesktop Client用のフローを選択した事になります。Web Application
でいうredirect_ui
の値は固定値urn:ietf:wg:oauth:2.0:oob
を使用することになります。
Scopeの調査
使用するAPIのリファレンスを探し当て、リファレンスの"Auth" というキーワードと"Scope"というキーワードを調べるとすぐにわかります。例えばGoogle Drive APIであればhttps://www.googleapis.com/auth/drive
という値です。
認可画面のURLを取得する
まずは以下のように環境変数を設定します。SCOPE
に複数の値を設定する場合は 空白文字で連結する必要があるので、空白文字をURLエンコードした値 %20
で連結しましょう。
CLIENT_ID=...
CLIENT_SECRET=...
REDIRECT_URI=urn:ietf:wg:oauth:2.0:oob
SCOPE=SCOPE1%20SCOPE2%20
認可画面のURLを取得する…のはブラウザにまかせて、「認可画面のURLを返すENDPOINThttps://accounts.google.com/o/oauth2/v2/auth
」へのパラメータを組み立てて、そのままブラウザで開きます。
ここで組み立てたURLにアクセスすると、302が返されそのLocationヘッダの中身が「認可画面のURL」なんですが、302はそのままブラウザ任せで処理してもらうということです。
echo "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=$SCOPE&access_type=offline"
ここでは、Refresh Tokenも取得するためにaccess_type=offline
も指定しています。このURLをブラウザで開くと認可画面が表示されるので、AcceptしてやるとAuthorization Codeが表示されます。
Authorization CodeをAccess Tokenに交換する
先の手順で取得したAuthorization Codeを環境変数に設定し、https://www.googleapis.com/oauth2/v4/token を叩いてやります。
AUTHORIZATION_CODE=...
curl --data "code=$AUTHORIZATION_CODE" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "redirect_uri=$REDIRECT_URI" --data "grant_type=authorization_code" --data "access_type=offline" https://www.googleapis.com/oauth2/v4/token
これでAccess Token, Refresh Token等を取得できます。SCOPEにopenid email profile
を追加してやれば、OpenID Connectで使う id_token も取得できます。
おまけ:
Refresh TokenをAccess Tokenに交換する
Access Tokenは有効期限がありますが、Refresh Tokenを保存しておけばいつでも(明示的にrevokeするまでは)新しいAccess Tokenを取得できます。
REFRESH_TOKEN=...
curl --data "refresh_token=$REFRESH_TOKEN" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token
Refresh TokenやAccess Tokenを使ってRevokeする
curl https://accounts.google.com/o/oauth2/revoke?token=...
token
に指定する値は、Refresh Token, Access TokenどちらでもOKです。
Access Tokenの状態を確認する
curl "https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=$ACCESS_TOKEN"
このAPIでAccess Tokenの有効期限や、認可されたSCOPEが取得できます。
なお、SCOPEが足りない(認可されていないリソース)へアクセスしようとした場合は 403 Insufficient Permission
というエラーが返されて403の原因が少しわかりにくいので、原因不明の403を受けた場合はこのAPIを試すと良いです。
一方、同じく403ではありますが、Projectで有効にしていないAPIを叩いた場合はAccess Not Configured. The API (Notes API) is not enabled for your project...
というわかりやすいエラーが返されます。