JavaScriptを有効にしてください

Google APIのトークンをgoogle authで取得する

 ·  ☕ 5 分で読めます

概要

スプレッドシートAPIを例に、gem googleauthを使用してリフレッシュトークンの取得を行う。
自分でURLを組み立てて認証する方法がよく見つかるが、業務等で何度も行う場合には面倒なので手元にコードを置いておけば楽かと思い試してみた。
大体以下のような流れとなる。

  • APIの有効化
  • 認証情報の作成
  • トークンの取得

前提

  • googleアカウント作成済み
  • WEBアプリでのAPI使用を想定
  • 個人で簡単に試す想定で、外部公開はしない
  • rubyの実行環境がある

APIの有効化

GCPにアクセスする
https://console.cloud.google.com

左上にプロジェクト選択欄があるので、使用するものを選ぶ。
なければ新しいプロジェクトを作成する。

サイドバーのAPIとサービスを選択し画面上部のAPIとサービスの有効化を選択。
APIライブラリに移動してGoogle Sheets APIを検索して有効化する。

認証情報の作成

API / サービスの詳細でシートAPIを表示して、認証情報タブを選択。
認証情報を作成からOAuthクライアントIDを選択して新規作成する。

アプリケーションの種類を選択。
名前はデフォルトでも良いが何のためのものかわかる名前の方がわかりやすい。
承認済みのリダイレクトURIを設定。
承認後にリダイレクトされる先で、基本的には何でも良いがhttps://しか設定できない。
作成するとクライアントID等が取得できる。
後で使用するのでjsonファイルをダウンロードしておく。

同意画面の作成

認証の際に表示される画面について設定する必要がある。

同意画面

User Type外部を選択して作成する。(内部はgoogle workspace利用者のみ使用可能)
アプリ名ユーザーサポートメールメールアドレスを設定する。
必須項目以外は省略しても問題ない。
一般公開して、不特定多数の人が利用するアプリの場合には全ての項目を設定して、googleの確認を受ける必要がある。
(その場合はomniauth-google等を使用してエンドユーザーがトークン取得するので自分の手元ではトークン取得しない。)

スコープ

必要な権限を設定する
スコープを追加で一覧からスプレッドシートの編集に必要な権限を設定する。

テストユーザー

テストモードで使用するためにはユーザーを登録しておく必要がある。
未登録のユーザーは認証できない。

全ての項目を設定すると同意画面の設定は完了。

トークンの取得

すでにgemが入っている環境だとこのあたりは不要だが、わかりやすいようにまとめておく。
作業用ディレクトリを作成してGemfileを配置する。

> mkdir google_auth

> cd google_auth

> bundle init

Gemfileを編集

1
2
3
4
5
# frozen_string_literal: true                                                                         
                                                                                                      
source "https://rubygems.org"                                                                         
                                                                                                      
gem 'googleauth' 

ダウンロードしておいたjsonファイルを作業ディレクトリに移動。
この時にファイル名をコード中のものに合わせる。

> mv path/to/secrets ./client_secrets.json

実行用のファイルを作成する(ファイル名は何でも良い)

> touch fetch_token.rb

gemの使用例をコピーして編集する
https://github.com/googleapis/google-auth-library-ruby

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
require 'googleauth'
require 'googleauth/stores/file_token_store'                                                          

OOB_URI = 'https://keee.blog/' # ここが認証情報作成時に設定したリダイレクト先 

scope = 'https://www.googleapis.com/auth/spreadsheets' # 必要なスコープを指定する 
client_id = Google::Auth::ClientId.from_file('./client_secrets.json') # 取得したjsonファイルを指定
token_store = Google::Auth::Stores::FileTokenStore.new(
  :file => './tokens.yaml')
authorizer = Google::Auth::UserAuthorizer.new(client_id, scope, token_store, OOB_URI) # OOB_URIを追加

user_id = ENV['USER'] # ターミナルで echo $USER を実行した時の値。元々設定されているはず。
credentials = authorizer.get_credentials(user_id)
if credentials.nil?
  url = authorizer.get_authorization_url(base_url: OOB_URI )
  puts "Open #{url} in your browser and enter the resulting code:"
  code = gets
  credentials = authorizer.get_and_store_credentials_from_code(
    user_id: user_id, code: code, base_url: OOB_URI)
end

使用例を実行してみていくつか修正が必要なことがわかった。
gemの挙動についてはこの辺りを確認した。
https://github.com/googleapis/google-auth-library-ruby/blob/main/lib/googleauth/user_authorizer.rb

  • OOB_URIはリダイレクトURIとして使用されるので、認証情報作成時に設定したものと一致しないと承認画面へのアクセス時にエラーになる。
  • Google::Auth::UserAuthorizerの引数にOOB_URIを追加しないと、ブラウザでアクセスするURLのredirect_uriOOB_URI/oauth2callbackとなってしまい、上記のURL不一致エラーとなる。
  • scope例はdriveのスコープになっているので、必要に応じて変える必要がある

コードを実行してトークンを取得する

コードを実行するとURLが表示されるのでブラウザを使用して認証する。
設定したURLにリダイレクトされるのでアドレスバーのcodeの値をコピーしてターミナルに入力する。

> ruby fetch_token.rb
Open https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&client_id=クライアントID&include_granted_scopes=true&redirect_uri
=https://keee.blog/&response_type=code&scope=https://www.googleapis.com/auth/spreadsheets in your browser and enter the resulting code:

認証完了したらトークン等を記載したファイルが作成される。

> cat tokens.yaml
---
ユーザー名: '{"client_id":"クライアントID","access_token":"アクセストークン","refresh_token":"リフレッシュトークン","scope":["https://www.googleapis.com/auth/spreadsheets"],"expiration_time_millis":1679603999000}'

エラーが出る場合にはデバッグ用のgemを入れて対応すると良い。

必要な情報をコピーしたらtoken.yamlは削除するか中身を空にする。
(ファイル内を確認してユーザー名にヒットすると認証部分がスキップされる為。)

その他

自分でURLを作成する場合はコピペが面倒なのとミスする可能性があるが、このやり方だとその辺りの不便が解消できそう。
プロジェクト毎にリダイレクト先やスコープが変わるので、そこは編集が必要になる。

公式記載のウェブアプリ向けの方法だと手順が長くて大変そうだが一連の流れについて網羅されている。
https://developers.google.com/identity/protocols/oauth2/web-server?hl=ja#ruby_1


書いた人
keee
Webエンジニア

目次