OAuth2とは
あるリソースに対する認可を
ユーザーの認可操作を通して
第三者のアプリにケーションに付与する方法
補足:
- Basic認証よりもセキュア
- パスワードを直接渡さない
- トークンを無効化することでアクセスを取り消せる
- 認可の権限を細かく制御できる
認証フローの実例
前提条件
- GCPでgmailのapiの設定とOAuthクライアントの設定は済んでいる
- クライアントの認証情報を示すcredentials.jsonはすでに配置されている
初回接続時
1. credentials.json を読み込み
2. ブラウザでGoogleログインページを開く
3. ユーザーが権限を承認
4. Access Token + Refresh Token を取得
5. token.json に保存
2回目以降
1. token.json から認証情報を読み込み
2. Access Token が有効検証
3. 有効でない場合、Refresh Token で Access Token を更新
4. token.json を更新(これをしないとAccess Tokenが更新されず、apiを呼び出すたびにrefreshの処理が入ることになる)
token.jsonの形式
{
"token": "xxxxx",
"refresh_token": "yyyyy",
"token_uri": "https://oauth2.googleapis.com/token",
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"scopes": ["https://www.googleapis.com/auth/gmail.readonly"],
"universe_domain": "googleapis.com",
"account": "",
"expiry": "2025-10-20T09:18:16Z"
}
認証操作コード例
# import
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
# helper functions
def save_token(creds):
"""Save the credentials to token.json."""
with open("token.json", "w") as token:
token.write(creds.to_json())
def initialize_token():
"""Initialize token.json by running the OAuth2 flow.
Save the obtained credentials to token.json in local.
Returns the obtained Credentials object.
"""
flow = InstalledAppFlow.from_client_secrets_file(
"credentials.json",
SCOPES
)
creds = flow.run_local_server(port=0)
save_token(creds)
return creds
# main functions
def build_creds():
""" Build credentials for GCP API access."""
if os.path.exists("token.json"):
creds = Credentials.from_authorized_user_file("token.json", SCOPES)
else:
creds = initialize_token()
if not creds.valid:
if creds.expired and creds.refresh_token:
creds.refresh(Request())
save_token(creds)
else:
creds = initialize_token()
return creds
def build_gmail_service():
""" Build service for GCP API access."""
creds = build_creds()
service = build("gmail", "v1", credentials=creds)
return service
認証コード使用例
直近5件のthreadを取得するコード
service = build_gmail_service()
results = service.users().threads().list(
userId='me',
maxResults=5
).execute()
results
---
{
'threads': [
{
'id': 'aaaa',
'snippet': 'bbb',
'historyId': 'ccc'
}, ...
],
'nextPageToken': '16135562161548514955',
'resultSizeEstimate': 201
}
トラブルシューティング
※AIによる提案
-
Access Token が期限切れになった
→ 自動的に Refresh Token で更新される。 -
Refresh Token も無効になった
→ 再度 OAuth フローを実行する必要があります。token.jsonを削除して再実行。 -
権限エラーが出る
→SCOPESの設定を確認。変更した場合はtoken.jsonを削除して再認証。