リンクアンドモチベーションでSREをしている井川です。
GoogleのAPIを使おうと思った際に、下記の通り認証方法を作成する方法が3種類あったのでそれぞれ試しつつ、仕組みについて整理しました。

試したこと
Goal:コードを実行して、スプレッドシートの最初のセルを出力させる。
APIキー
設定
実行
- コード実行
import os
from dotenv import load_dotenv
from googleapiclient.discovery import build
# Load environment variables from .env file
load_dotenv()
API_KEY = os.getenv('API_KEY')
SPREADSHEET_ID = os.getenv('SPREADSHEET_ID')
service = build('sheets', 'v4', developerKey=API_KEY)
result = service.spreadsheets().values().get(
spreadsheetId=SPREADSHEET_ID,
range='A1'
).execute()
print(result.get('values', [['']])[0][0])
- 成功
OAuthクライアントID
設定
実行
- コード実行
import os
from dotenv import load_dotenv
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
load_dotenv()
SPREADSHEET_ID = os.getenv('SPREADSHEET_ID')
SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
creds = flow.run_local_server(port=8080)
service = build('sheets', 'v4', credentials=creds)
result = service.spreadsheets().values().get(
spreadsheetId=SPREADSHEET_ID,
range='A1'
).execute()
print(result.get('values', [['']])[0][0])
サービスアカウント
設定
- サービスアカウントを作成する
- キーを追加する
- スプレッドシートの共有対象にサービスアカウントを追加する
- 作成されたJSONファイルを
service-account.jsonに保存する
実行
- コード実行
import os
from dotenv import load_dotenv
from google.oauth2 import service_account
from googleapiclient.discovery import build
load_dotenv()
SPREADSHEET_ID = os.getenv('SPREADSHEET_ID')
SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']
creds = service_account.Credentials.from_service_account_file('service-account.json', scopes=SCOPES)
service = build('sheets', 'v4', credentials=creds)
result = service.spreadsheets().values().get(spreadsheetId=SPREADSHEET_ID, range='A1').execute()
print(result.get('values', [['']])[0][0])
- 成功
認証方法の仕組み
APIキー
シンプルな仕組みですね。
その分、非公開データにアクセスできない特徴があります。

OAuthクライアントID
ユーザーのアクションが必要になるのが特徴ですね。

https://developers.google.com/identity/protocols/oauth2?hl=ja
サービスアカウント
ユーザー不在でも動作するのが特徴ですね。

https://developers.google.com/shopping-content/guides/how-tos/service-accounts?hl=ja
シーケンス図作成の過程で出てきた不明点の解消
- client_secretはどこで発行される?
- OAuthクライアントIDを作成した際に発行され、credentials.jsonとしてダウンロードする
- この情報があることでサーバーが正規のものであることを証明できる
- Bearerの仕組みとは?
- 認証方式の1種であり、トークン所持者に権限を付与する
- 平文で送られるため、必ず暗号化されるHTTPSで送る
- トークン検証の方法とは?
- JWTと不透明トークンの2種類があり、それぞれでトークンが認可情報を処理および検証する方法が異なる
- JWTとは?
- JSON Web Token
- 認証に必要な情報をすべてもつ自己完結型のトークン
- サービス間で認証・認可のデータを伝送する際に使われるJSONオブジェクトと署名を表現するアプローチ
- ex. RSA(秘密鍵で署名して認証サーバーに送り、認証サーバーでは公開鍵で署名の検証をする)
- https://auth-wiki.logto.io/ja/jwt
- 不透明トークンとは?
- クライアントにとって意味のないランダムでユニークな文字列
- サーバーのデータベースで認可データを検索するための参照キーとして使われる
- https://auth-wiki.logto.io/ja/opaque-token
まとめ
それぞれの認証の裏に、様々な技術や仕組みがあることを学びました。
今後使う上では、下記のように適切に使い分けていきたいと思います。
- APIキー
- 公開データにのみアクセスする場合(非公開データにはアクセスできない)
- OAuthクライアントID
- ユーザーごとで異なるデータにアクセスする場合
- サービスアカウント
- ユーザー不在で通信する場合
- バックエンドの自動処理の場合




