OAuth2認証が必要なGoogle Cloud APIをプログラムから実行する
はじめに
Google Cloud APIは、様々なGoogleの機能をHTTPで操作する為のAPI群です。
認証方式には、APIキー方式やサービスアカウントキー方式などがありますが、ユーザーのデータにアクセスするAPIや、ユーザーの代わりに操作を行うAPIなどでは、OAuth2.0認証が必要です。
具体的には、Google Drive APIや、Google Calendar API、Google Analytics API等の利用時には、Googleサインイン画面を表示して、ユーザーの認証と使用する機能に対する同意が必要になります。
セキュリティの面からは必要な認証機能なのですが、プロジェクト単位で作成したGoogle Driveなどに、プログラムからアクセスするような場合には、この認証フローの為に、自動実行することができなくなってしまいます。
このような場合の対応方法について説明します。
Google Forms API
先日、Google Formsを使用してアンケートを作成することがありました。
その際、Backend側で、アンケート情報を収集する機能が必要だったので、Google Forms APIを使用して、収集されたアンケート内容を取得するプログラムを作成しました。
Google Formsで作成したアンケートの回答は、Google Drive上に保存されます。
通常は、プロジェクトで作成されたGoogleアカウントのGoogle Drive上に保存されると思います。
そのアンケートの回答を取得するには、forms.responses.list APIを叩く必要があるのですが、このAPIにアクセスする為には、Google DriveのOAuthスコープが必要なので、Googleサインイン画面を表示して、ユーザ認証と権限付与の同意が必要です。
必要になる権限スコープは以下の3つです。
- https://www.googleapis.com/auth/drive
- https://www.googleapis.com/auth/drive.file
- https://www.googleapis.com/auth/forms.responses.readonly
このAPIを、Backendのプログラムで実行させるための準備を行っていきます。
Google Cloud Platformコンソールでの準備
Google Cloud APIを使用するには、Google Cloud Platformでプロジェクトの作成が必要です。
上記コンソールにGoogleアカウントでログインし、プロジェクトを作成してください。
Google Forms APIの有効化
まずは、Google Forms APIを有効にします。
Google Cloud Platformコンソールにログインしたら、クイックアクセスにある「APIとサービス」をクリックし、「APIとサービスを有効にする」ボタンを押します。
検索窓に「forms」と入力し、表示されるGoogle Forms APIを選択して、「有効にする」ボタンを押すと、APIが有効になります。
認証情報の作成
次に、左メニューから「認証情報」を選択し、「認証情報を作成」ボタンを押します。
表示される「OAuthクライアントIDの作成」画面で、以下のように入力します。
- アプリケーションの種類:ウェブアプリケーション
- 名前:(適当な名称)
- 承認済みのリダイレクトURL:http://localhost:8080(アクセスできなくてOK)
クライアントIDを作成したら、一覧から選択して詳細を表示させ、「クライアントID」と「クライアントシークレット」をメモしておきます。
最後に、認証を行うユーザのGoogleアカウントのメールアドレスをテストユーザに追加します。
リフレッシュトークンの取得
Backendプログラムで、Google Forms APIを利用するには、以下の3つが必要です。
- クライアントID(作成済み)
- クライアントシークレット(作成済み)
- リフレッシュトークン
上記3つの情報があれば、プログラムから、APIにアクセスする為のアクセストークンを取得して、APIにアクセスすることができます。
クライアントIDとクライアントシークレットは、すでに作成済みなので、リフレッシュトークンを取得します。
codeの取得
リフレッシュトークンを取得する為に、まず、codeパラメータを取得します。
ブラウザで「https://accounts.google.com/o/oauth2/auth」 に以下の値をパラメータに追加して実行してください。
name | value |
---|---|
client_id | クライアントID |
redirect_uri | 認証情報作成で入力したリダイレクトURL (http://localhost:8080) |
scope | 取得する権限スコープ 複数の場合はスペースを入れて記述 今回はGoogle Forms APIのlistで必要な下記の3つのスコープを指定 https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/forms.responses.readonly |
response_type | code |
access_type | offline |
以下のようなURLを作成してブラウザでアクセスします。
- https://accounts.google.com/o/oauth2/auth?client_id=[クライアントID]&redirect_uri=http://localhost:8080&scope=https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/forms.responses.readonly https://www.googleapis.com/auth/forms.body.readonly&response_type=code&access_type=offline
権限スコープの一覧はこちらに載っています。
また、使用するAPIのヘルプページにも必要なスコープの記載があります。
生成したURLに、ブラウザでアクセスすると、Googleアカウントのサインイン画面が表示されますので、サインインします。
テスト環境だと、以下のようなページが表示されますが、気にせず「続行」を選択します。
権限許可のページが表示されますので、すべての権限にチェックを入れます。
ページ遷移すると、設定したRedirectUrl(hrrp://localhost:8080)に遷移しますが、アクセスできないのでエラーになります。
この時、アドレスバーに表示されているURLに、「code」パラメータが表示されていますので、これをコピーします。
- http://localhost:8080/?code=XXXXXXX&scope=https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/forms.body.readonly https://www.googleapis.com/auth/forms.responses.readonly
リフレッシュトークンの取得
取得したcodeパラメータを指定して、リフレッシュトークンを取得します。
「https://www.googleapis.com/oauth2/v4/token」 にPOSTでQueryParameterとして、以下のデータを送信します。
name | value |
---|---|
code | 取得したcodeの値 |
client_id | クライアントID |
client_secret | クライアントシークレット |
redirect_uri | 認証情報作成で入力したリダイレクトURL (http://localhost:8080) |
scope | 取得する権限スコープ 複数の場合はスペースを入れて記述 今回はGoogle Forms APIのlistで必要な下記の3つのスコープを指定 https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/forms.responses.readonly |
grant_type | authorization_code |
curlで実行する場合は、以下のようになります。
curl -XPOST https://www.googleapis.com/oauth2/v4/token \
--data "code=[codeの値]&client_id=[クライアントID]&client_secret=[クライアントシークレット]&redirect_uri=http://localhost:8080&scope=https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/forms.body.readonly https://www.googleapis.com/auth/forms.responses.readonly&grant_type=authorization_code"
成功すると、以下のようなJSON形式のレスポンスが取得できます。
{
"access_token": "XXXXX",
"expires_in": 3599,
"refresh_token": "XXXXXX",
"scope": "https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/forms.responses.readonly https://www.googleapis.com/auth/forms.body.readonly",
"token_type": "Bearer"
}
これでリフレッシュトークンが取得できました。
このリフレッシュトークンは、再度上記の手順でGoogleサインインを行うと無効になってしまいますので、その場合はcodeの取得からやり直してください。
Google Forms APIの実行
それでは、取得したクライアントID/クライアントシークレット/リフレッシュトークンを使用して、Google Forms APIを実行してみます。
実際にプログラムで実行する場合は、クライアントID/クライアントシークレット/リフレッシュトークンを引数にして、プログラム内部で以下の2つの処理を実行することになります。
- アクセストークンの取得
- APIの実行
アクセストークンの取得
APIを実行する為に、まずアクセストークンを取得します。
「https://www.googleapis.com/oauth2/v4/token」 にPOSTでQueryParameterとして、以下のデータを送信します。
name | value |
---|---|
client_id | クライアントID |
client_secret | クライアントシークレット |
refresh_token | リフレッシュトークン |
grant_type | refresh_token |
curlで実行する場合は、以下のようになります。
curl -XPOST https://www.googleapis.com/oauth2/v4/token \
--data "client_id=[クライアントID]&client_secret=[クライアントシークレット]&refresh_token=[リフレッシュトークン]&grant_type=refresh_token"
成功すると、以下のようなJSON形式のレスポンスが取得できます。
{
"access_token": "XXXXX",
"expires_in": 3599,
"refresh_token": "XXXXXX",
"scope": "https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/forms.responses.readonly https://www.googleapis.com/auth/forms.body.readonly",
"token_type": "Bearer"
}
取得したaccess_tokenを、API実行時のHTTP Headerに、Authorization: Bearer XXXXXX の形で設定してリスエストを送信します。
ちなみに、取得したアクセストークンには有効期限があります。
レスポンスのexpires_inが有効期限(秒)の情報になりますので、この時間が過ぎたら再度アクセストークンを取得する必要があります。
APIの実行
Google Formsで作成したアンケート回答を取得するには、forms.responses.listを使用します。
このAPIでは、以下のURLにHTTP GETでアクセスすると、回答内容がJSON形式で取得できます。
このリクエストのHTTPヘッダーに、先程取得したアクセストークンを設定します。
curlで実行する場合は、以下のようになります。
curl https://forms.googleapis.com/v1/forms/[フォームID]/responses \
-H "Authorization: Bearer [アクセストークン]"
成功すると、以下のような回答データが返却されます。
{
"responses": [
{
"responseId": "XXXXX",
"createTime": "2024-11-07T04:17:48.544Z",
"lastSubmittedTime": "2024-11-07T04:17:48.544044Z",
"answers": {
"0ed7f87c": {
"questionId": "0ed7f87c",
"textAnswers": {
"answers": [
{
"value": "2F"
}
]
}
},
"715c81b0": {
"questionId": "715c81b0",
"textAnswers": {
"answers": [
{
"value": "選択肢 1"
}
]
}
}
}
},
{
"responseId": "XXXXX",
"createTime": "2024-11-07T04:18:07.078Z",
"lastSubmittedTime": "2024-11-07T04:18:07.078451Z",
"answers": {
:
:
:
Discussion