Google::Apis::DriveV3 (Ruby) で Google Drive を操作する
REST client の使い方を見ていく
googleapis/google-api-ruby-client: REST client for Google APIs
実際の Gem はサービス毎に分かれているっぽい
The client gems are named according to the pattern google-apis-<servicename>_<serviceversion>. For example, the client for the Google Drive V3 API is google-apis-drive_v3.
Google Drive の場合は google-apis-drive_v3
という Gem を利用する。
ユーザガイドを読む
google-api-ruby-client/usage-guide.md at main · googleapis/google-api-ruby-client
Google API を使うための準備
- Google アカウント (すでにある)
- Google APIs Console で project を作る
プロジェクトを作成する
適当にプロジェクトを作る
Google Drive API を有効にする
認証について理解する
プリンシパル
- ユーザーアカウント
- 人間のユーザに代わってリソースにアクセスする場合
- サービスアカウント
- 人間のユーザ以外(アプリケーション自体)がリソースにアクセスする場合
認証ストラテジ
種類
- API キー
- 一般公開データへの匿名アクセスする
- OAuth 2.0 クライアント
- エンドユーザに代わって限定公開データにアクセスする
- 環境提供のサービスアカウント
- Google Cloud 環境内で、サービスアカウントに代わって限定公開データにアクセスする
- サービスカウントキー
- Google Cloud 環境外で、サービスアカウントに代わって非公開データにアクセスする
今回想定しているケースでは、エンドユーザになり変わってエンドユーザが権限を持つデータにアクセスすることを想定している。
そのため、「OAuth 2.0 クライアント」を利用するので良さそう。
エンドユーザーとして認証する (OAuth 2.0 クライアント)
クライアント認証情報の作成
OAuth 同意画面
不特定多数の Google アカウントを持つユーザを対象とする場合は「外部」を選択する
アプリ情報を入力する
スコープで Google Drive API 関連を選択してみる
各スコープの違い
-
/auth/drive
- インストールされたアカウントの Google Drive のすべてのファイルにアクセス可能となる
-
/auth/drive.appdata
- アプリケーション固有の設定情報などが格納されていて、ドライブにアプリケーションがインストールされたときに作成され、アンインストールされたときに削除される
- ファイルは他の Drive アプリケーションやユーザに対して見えないようになっている
- https://developers.google.com/drive/api/guides/appdata
-
/auth/drive.file
- アプリケーションが作成したファイルや、ユーザーが明示的にアクセスを許可したファイルのみがアクセス可能となる
-
/auth/docs
- ??
-
/auth/drive.metadata
- ??
認証情報を用意する
OAuth クライアント ID を用意してみる
作成が完了すると
- クライアントID
- クライアントシークレット
が表示される。
また、それらが含まれた JSON がダウンロードできる。
JSONは以下のような構造になっていた
{
"web": {
"client_id": "xxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
"project_id": "xxxxxxxxxxxxxxx",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
"redirect_uris": [
"http://localhost:3000/callback"
],
"javascript_origins": [
"http://localhost:3000"
]
}
}
OAuth2.0 Play Ground を試す
Step1 scope (アクセスを許可するAPI) を選択する
とりあえず Drive API v3 の /auth/drive
を許可する
認可フロー
アプリケーションにアクセスを許可する Google アカウントを選択する
アクセス方法について許可を求められるので許可する
リダイレクトで Authrization code が取得できるので、それを Access Token (及び Refresh Token) に交換する
結果として、Access Token と Refrfesh Token が返却されるのでアプリケーション側のストレージ領域(DBやファイルシステム、オブジェクトストレージなど)に保存しておく。
試しに、ファイル一覧を取得してみる
疑問: トークンの有効期限はアプリケーション側で設定できる?
(TBW)
疑問: トークンのリフレッシュにはユーザーの操作が必要?
(TBW)
サンプルコード
API Console で認証情報を作成する
完全な例 より
require 'google/apis/drive_v2'
require 'google/api_client/client_secrets'
require 'json'
require 'sinatra'
enable :sessions
set :session_secret, 'setme'
get '/' do
unless session.has_key?(:credentials)
redirect to('/oauth2callback')
end
client_opts = JSON.parse(session[:credentials])
auth_client = Signet::OAuth2::Client.new(client_opts)
drive = Google::Apis::DriveV2::DriveService.new
files = drive.list_files(options: { authorization: auth_client })
"<pre>#{JSON.pretty_generate(files.to_h)}</pre>"
end
get '/oauth2callback' do
client_secrets = Google::APIClient::ClientSecrets.load
auth_client = client_secrets.to_authorization
auth_client.update!(
:scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
:redirect_uri => url('/oauth2callback'))
if request['code'] == nil
auth_uri = auth_client.authorization_uri.to_s
redirect to(auth_uri)
else
auth_client.code = request['code']
auth_client.fetch_access_token!
auth_client.client_secret = nil
session[:credentials] = auth_client.to_json
redirect to('/')
end
end
(TBW)
作成した結果、 JSON がダウンロードできるので、それを client_secret.json
という名前で保存しておく。
実行
$ ruby client.rb
== Sinatra (v2.2.1) has taken the stage on 4567 for development with backup from Puma
Puma starting in single mode...
* Puma version: 5.6.4 (ruby 3.1.2-p20) ("Birdie's Version")
* Min threads: 0
* Max threads: 5
* Environment: development
* PID: 9182
* Listening on http://127.0.0.1:4567
* Listening on http://[::1]:4567
Use Ctrl-C to stop
疑問: オフラインアクセス?
https://developers.google.com/identity/protocols/oauth2/web-server#offline
オフライン アクセスのリクエストは、ユーザーが存在しない場合に Google API にアクセスする必要があるすべてのアプリケーションで必須です。たとえば、バックアップ サービスを実行するアプリや、既定の時間にアクションを実行するアプリは、ユーザーが存在しないときにアクセス トークンを更新できる必要があります。デフォルトのアクセススタイルはonline
です。
つまり、バッチ処理や非同期処理などでユーザーが介在しない場所での API を実行する場合にアクセストークンを適切に利用するためには offline
アクセスが必要ということらしい。
Google Auth ライブラリ
Google::Auth::ClientId とは?
認証情報を用意する で GCP console で作成したクライアント認証情報をコード上で表現したものっぽい。
Google::Auth::Stores::RedisTokenStore とは?
Storage
Authorizers require a storage instance to manage long term persistence of access and refresh tokens. Two storage implementations are included:
- Google::Auth::Stores::FileTokenStore
- Google::Auth::Stores::RedisTokenStore
Authorizer には取得したトークンを一定期間保持しておくための保存領域が必要で、その保存方法に応じた TokenStore がSDKとしてあらかじめ用意されているっぽい。
そのうちの一つとして、 Redis に Token を保存するためのクラスが RedisTokenStore
Google::Auth::UserAuthorizer とは?
OAuth2 によるユーザ認証に利用するURLの生成や、認可コードを使ってトークンエンドポイント経由でアクセストークンを取得したりする。
また、取得したアクセストークンは TokenStore を使って一定期間永続化し、必要なタイミングでリトークンのリフレッシュも行ったりする。
Googl::Auth::WebUserAuthorizer とは?
(TBW)
Application Default Credentials って?
AIP-4110: Application Default Credentials
Google auth libraries use a strategy called Application Default Credentials (ADC) to detect and select credentials based on environment or context. With ADC, developers should be able to run the code in different environments and the supporting systems fetch the appropriate credentials based on each environment in an effortless manner.
アプリケーションは ADC を利用することで、環境毎に認証情報を切り替えるということを意識せずに済む、みたいなことを言っている。
AWS における EC2 や ECS で実行するアプリケーションにAWSリソースにアクセスするための認証情報直接アクセスキーを渡さずに IAM Role をEC2インスタンスやタスクに紐づける仕組みと似ている。
そして ADC を利用できるのは、GCP 上の Compute リソース上でアプリケーションを実行する場合に限られている、というように読める。