ナビゲーションにスキップ

Frame.io Python SDK — 認証ガイド

このガイドでは、Frame.io Python SDK(frameio)を使用してFrame.io APIで認証する方法について説明します。Frame.io V4 APIはAdobe Identity Management Service(IMS)、アドビのOAuth 2.0アイデンティティプラットフォームを使用します。

これはPython開発者向けの独立したリファレンスです。以下のすべてのコード例とフローはframeioパッケージのみを対象としています。


Python SDKにおける認証タイプ

Python SDKは4つの認証オプションをサポートしています:

方式ユースケースユーザー操作?クライアントシークレットが必要?
静的トークンクイックスクリプト、テスト、または既にトークンを持っている場合いいえいいえ
Server-to-Serverバックエンドサービス、cronジョブ、自動化いいえはい
Web Appサーバーサイドアプリ(Flask、Django、FastAPI)はいはい
SPA (PKCE)ブラウザーアプリ、CLI、またはシークレットを保存できないアプリはいいいえ

Server-to-Serverはアプリをユーザー操作なしでサービスアカウントとして動作させます。これはAdobe Admin Consoleを介して管理されているFrame.io V4アカウントでのみ利用可能です。

Web AppとSPAはアプリを特定のユーザーとして動作させます。どちらも内部的にAdobe IMSを使用します。ユーザーがアプリを認可し、SDKがその結果のコードをトークンと交換します。Python SDKはIMSの/authorize/v2および/token/v3フローを処理します。Web Appではクライアントシークレットが必要で、SPAでは代わりにPKCEを使用します。

Adobeのネイティブアプリ資格情報はOSレベルでリダイレクトをインターセプトするカスタムURIスキームハンドラー(例:adobe+<hash>://…)を必要とします。Pythonにはそのようなハンドラーを登録する標準的な方法がないため、Python SDKはNativeAppAuthクラスを提供しません。ユーザー対話型のPythonアプリには、ローカルコールバックサーバー(例:FlaskやFastAPI)と共にWebAppAuthを使用してください。非対話型のワークロードにはServerToServerAuthを使用してください。


サービスアカウントユーザー

Server-to-Server認証を使用する場合、アプリケーションはサービスアカウントユーザーとして動作します。これは、サービスに代わってアクションを実行できる独特なアカウントタイプです。これらはFrame.ioの他のユーザーに表示されます。サービスアカウントがアクションを実行すると、その名前がUIに表示されます。

Adobe Admin ConsoleとDeveloper Consoleを通じてサービスアカウントアクセスを許可および取り消すことができます。サービスアカウント名はFrame.io UIから管理されます。デフォルトでは、最初のS2S接続はService Account User、2番目はService Account User 2などと名付けられます。

詳細については、Frame.io サーバー間サポートを使用した設定の自動化を参照してください。


クイックスタート

前提条件

  1. Adobe Developer Consoleからの資格情報:

    • Client ID — すべてのOAuthフローに必要
    • Client Secret — Server-to-ServerおよびWeb Appフローに必要
    • Redirect URI — Web AppおよびSPAフローに必要。Adobeプロジェクトに登録する必要があります
  2. SDKをインストール:

pip install frameio

方法の選択

  • ユーザーが関与しない場合: Server-to-Server(ServerToServerAuth)を使用します。
  • ユーザーが関与し、シークレットを保存できる場合: Web App(WebAppAuth)を使用します。
  • ユーザーが関与するが、シークレットを保存できない場合: SPA(SPAAuth)を使用します。

アクセストークン

既にアクセストークンがある場合(他のOAuthシステムまたは以前の交換から、例えばAPI Explorer経由)、直接渡すことができます:

from frameio import Frameio
client = Frameio(token="YOUR_ACCESS_TOKEN")

これは最もシンプルなアプローチですが、トークンは最終的に期限切れになり、SDKは自動的に更新しません。

レガシーデベロッパートークン

Adobe Admin Consoleでまだ管理されていないV4移行アカウントの場合、Frame.ioデベロッパーサイトからのレガシーデベロッパートークンを引き続き使用できます。x-frameio-legacy-token-authヘッダーを含めてtrueに設定する必要があります:

from frameio import Frameio
client = Frameio(
token="YOUR_LEGACY_DEVELOPER_TOKEN",
headers={"x-frameio-legacy-token-auth": "true"},
)

レガシーデベロッパートークンは期限切れになりませんが、移行メカニズムです。新しい統合と本番ワークロードには、以下のOAuth 2.0フローのいずれかを使用することをお勧めします。詳細については、移行ガイドを参照してください。


サーバー間(クライアント資格情報)

ユーザーの操作なしにFrame.ioアクセスが必要なバックエンドサービスやスクリプトに使用します。このフローはAdobe Admin Consoleを介して管理されているFrame.io V4アカウントでのみ利用可能です。アプリケーションは、人間のループなしでサービスアカウントユーザーとして認証されます。

from frameio import Frameio
from frameio.auth import ServerToServerAuth
auth = ServerToServerAuth(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
)
client = Frameio(token=auth.get_token)

これだけです。auth.get_tokenは、SDKがすべてのリクエストで呼び出すコール可能オブジェクトです。現在のトークンがまだ有効な場合、すぐに戻ります。期限切れが近い場合、完全に透過的に新しいトークンを最初に取得します。

仕組み

クライアント資格情報(クライアントID + シークレット)は期限切れになりません。セキュリティ衛生のために手動でのみローテーションします。S2Sは、手動介入なしで効果的に永続的で中断のないAPIアクセスを提供します。

内部的には:

  1. 最初のAPI呼び出しで、get_tokenはclient_credentials付与を使用してAdobe IMSから新しいアクセストークンをリクエストします。
  2. トークンはメモリにキャッシュされます。個々のアクセストークンは期限切れになりますが(通常24時間)、これは自動的に処理されます。
  3. キャッシュされたトークンが更新バッファー内にある場合(デフォルト:期限切れの60秒前)、SDKは同じクライアント資格情報を使用して自動的に新しいトークンを取得します。
  4. リフレッシュトークンは関与しません。クライアント資格情報自体が長期間有効なシークレットであり、常に新しいアクセストークンの作成に使用できます。

明示的認証

トークンを積極的に取得したい場合(例えば、起動時に不正な資格情報で高速に失敗させるため):

auth = ServerToServerAuth(client_id="...", client_secret="...")
auth.authenticate() # raises AuthenticationError if credentials are invalid
client = Frameio(token=auth.get_token)

Web App(認証コード)

ユーザーがAdobe IDでサインインするサーバーサイドアプリケーションに使用します。このフローではクライアントシークレットが必要で、サーバー上に安全に保存する必要があります。

1

ユーザーをAdobe IMSにリダイレクトする

from frameio.auth import WebAppAuth
auth = WebAppAuth(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
redirect_uri="https://yourapp.com/callback",
)
# CSRF攻撃を防ぐために暗号学的にランダムなstate値を生成
import secrets
state = secrets.token_urlsafe(32)
authorization_url = auth.get_authorization_url(state=state)
# `state`をユーザーのセッションに保存し、`authorization_url`にリダイレクトします
2

コールバックを処理する

Adobe IMSがユーザーをredirect_uriにリダイレクトして戻すとき、codeとstateパラメータを抽出します。stateが保存したものと一致することを確認してから、コードをトークンと交換します:

# コールバックハンドラ内で(例:Flask/FastAPIルート):
auth.exchange_code(code=request.args["code"])

これにより、認証コードがアクセストークンとリフレッシュトークンに交換され、両方が内部に保存されます。

3

クライアントを使用する

from frameio import Frameio
client = Frameio(token=auth.get_token)

これだけです。これ以降、get_tokenがトークンのライフサイクルを自動的に管理します。アクセストークンの有効期限が近づくと、SDKはリフレッシュトークンを使用して新しいトークンを取得します。ユーザーの操作は必要ありません。

完全なFlaskの例

import secrets
from flask import Flask, redirect, request, session
from frameio import Frameio
from frameio.auth import WebAppAuth
app = Flask(__name__)
app.secret_key = secrets.token_bytes(32)
auth = WebAppAuth(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
redirect_uri="http://localhost:5000/callback",
)
@app.route("/login")
def login():
state = secrets.token_urlsafe(32)
session["oauth_state"] = state
return redirect(auth.get_authorization_url(state=state))
@app.route("/callback")
def callback():
if request.args.get("state") != session.pop("oauth_state", None):
return "Invalid state parameter", 403
auth.exchange_code(code=request.args["code"])
client = Frameio(token=auth.get_token)
accounts = client.accounts.index()
return f"Authenticated — {len(accounts.data)} account(s) accessible."

単一ページアプリ / PKCE(認証コード + PKCE)

ブラウザーベースのアプリケーション、デスクトップアプリ、またはクライアントシークレットを安全に保存できないCLIツールに使用します。このフローはPKCE (RFC 7636)を使用して認証コード交換を保護します。

1

認証URLを生成する

from frameio.auth import SPAAuth
auth = SPAAuth(
client_id="YOUR_CLIENT_ID",
redirect_uri="https://yourapp.com/callback",
)
import secrets
state = secrets.token_urlsafe(32)
result = auth.get_authorization_url(state=state)
# result.url -> ユーザーをここにリダイレクト
# result.code_verifier -> コールバックまで安全に保存

get_authorization_urlは、完全なURL(PKCEのcode_challengeが埋め込まれた)と次のステップで必要なcode_verifierを含むAuthorizationUrlResultを返します。

2

ベリファイアと共にコードを交換する

ユーザーがリダイレクトされて戻ってきたとき:

auth.exchange_code(
code="CODE_FROM_CALLBACK",
code_verifier=result.code_verifier,
)
3

クライアントを使用する

from frameio import Frameio
client = Frameio(token=auth.get_token)

これだけです。更新はWebアプリと同じように動作します。SDKは自動的にリフレッシュトークンを使用します。違いは、SPAフローがパブリッククライアント用に設計されているため、更新時にクライアントシークレットが送信されないことです。


非同期使用法

すべての認証クラスには、Asyncが接頭辞として付いた非同期対応版があります。上記のコード例には、該当する場合にSyncとAsyncのタブが含まれています。

同期非同期
ServerToServerAuthAsyncServerToServerAuth
WebAppAuthAsyncWebAppAuth
SPAAuthAsyncSPAAuth

APIは同一です。get_authorization_urlは同期のまま(I/Oなし)ですが、exchange_code、refresh、revoke、get_tokenはすべてasyncです。非同期クラスはAsyncFrameioと一緒に使用してください。

手動トークン更新

WebアプリとSPAフローの場合、SDKはget_tokenを介してトークンを自動的に更新します。明示的なコントロールが必要な場合は、refresh()を直接呼び出すことができます:

auth.refresh() # リフレッシュトークンを使用して新しいアクセストークンを取得

これは、自動リフレッシュバッファーに依存するのではなく、重要な操作の前に強制的にリフレッシュを実行したい場合に便利です。


トークンの永続化

すべての認証クラスは、再起動間でのトークン状態の永続化のためにexport_tokens()とimport_tokens()をサポートしています。WebアプリとSPAフローでは、アクセストークンとリフレッシュトークンがデフォルトでメモリに保存されるため、これは特に重要です。アプリケーションが再起動した場合、永続化しない限りユーザーは再認証が必要になります。サーバー間通信では、永続化はオプションです(クライアント資格情報は常に新しいトークンを生成できます)が、キャッシュされたトークンをインポートすることで起動時の余分なラウンドトリップを回避できます。

エクスポートとインポート

# exchange_code()の後、トークン状態を保存
token_data = auth.export_tokens()
# token_dataは辞書です:{"access_token": "...", "refresh_token": "...", "expires_at": 1234567890.0}
# データベース、ファイル、またはシークレットストアに保存
# 次回の起動時に復元
auth.import_tokens(token_data)
client = Frameio(token=auth.get_token)
# SDKはトークンの有効期限が近い場合、自動的にリフレッシュします

on_token_refreshedによる自動永続化

トークンが更新されるたびに自動的に永続化するには、on_token_refreshedコールバックを使用します:

import json
from pathlib import Path
TOKEN_FILE = Path("tokens.json")
def save_tokens(tokens: dict):
TOKEN_FILE.write_text(json.dumps(tokens))
auth = WebAppAuth(
client_id="...",
client_secret="...",
redirect_uri="...",
on_token_refreshed=save_tokens,
)
# 起動時に、利用可能な場合は復元
if TOKEN_FILE.exists():
auth.import_tokens(json.loads(TOKEN_FILE.read_text()))

コールバックはexport_tokens()と同じ辞書形式を受け取り、トークンの更新が成功するたびに実行されます。

非同期クラスの場合、on_token_refreshedは通常の関数またはasync関数のいずれかを使用できます。両方がサポートされています。


トークンの取り消し

ユーザーをサインアウトし、Adobe IMSでトークンを無効にするには:

auth.revoke()

これにより、アクセストークンとリフレッシュトークンの両方についてAdobe IMSに対してベストエフォートの取り消しリクエストが行われ、その後すべてのローカルトークン状態がクリアされます。取り消し後、ユーザーは再認証する必要があります。

非同期クラスの場合は、await auth.revoke()を使用します。


エラー処理

すべての認証エラーはFrameioAuthErrorから継承されるため、広範囲にキャッチするか、特定のケースを処理できます:

from frameio.auth import (
FrameioAuthError,
AuthenticationError,
TokenExpiredError,
ConfigurationError,
NetworkError,
RateLimitError,
)
try:
auth.exchange_code(code="...")
except TokenExpiredError:
# リフレッシュトークンの有効期限が切れています。ユーザーを再度サインインにリダイレクトしてください
pass
except AuthenticationError as e:
# トークン交換に失敗しました
print(f"Error: {e.error_code} - {e.error_description}")
except NetworkError:
# タイムアウトまたは接続失敗(再試行後)
pass
except RateLimitError as e:
# Adobe IMSから429。e.retry_after秒後に再試行してください
pass
except FrameioAuthError:
# その他の認証エラーのキャッチオール
pass

エラーリファレンス

例外発生するタイミング
ConfigurationError設定が不足または無効(例:空のclient_id、非HTTPSリダイレクトURI)
AuthenticationErrorトークン交換またはリフレッシュがAdobe IMSによって却下された(.error_codeと.error_descriptionを持つ)
TokenExpiredErrorリフレッシュトークン自体が期限切れ。ユーザーは再認証が必要
NetworkErrorすべての再試行後のHTTPタイムアウトまたは接続失敗
RateLimitErrorAdobe IMSが429を返した。バックオフガイダンスについては.retry_afterを確認
PKCEErrorPKCE検証が失敗(SPAフロー)

本番環境での期限切れリフレッシュトークンの処理

WebアプリとSPAフローでは、リフレッシュトークンは最終的に期限切れになります。その場合、get_tokenはTokenExpiredErrorを発生させます。これをキャッチして、ユーザーを再度認証フローにリダイレクトする必要があります。

from frameio.auth import TokenExpiredError
try:
client = Frameio(token=auth.get_token)
assets = client.files.list(project_id="...")
except TokenExpiredError:
# 永続化されたトークンをクリアし、ユーザーをログインにリダイレクト
auth.revoke()
return redirect("/login")

設定リファレンス

すべての認証クラスは、これらのオプションパラメータを受け入れます:

パラメータデフォルト説明
scopesフロー固有のデフォルトスペース区切りのOAuthスコープ。S2Sのデフォルトはopenid AdobeID frame.s2s.all;ユーザー向けフローのデフォルトはopenid email profile offline_access additional_info.roles。
ims_base_urlhttps://ims-na1.adobelogin.comAdobe IMSベースURL。ステージングまたは非本番環境での上書き。
http_clientNoneプロキシ、mTLS、または接続プーリング用のカスタムhttpx.Client(またはhttpx.AsyncClient)。
timeout30トークンエンドポイント呼び出しのHTTPリクエストタイムアウト(秒)。
max_retries2一時的な障害(5xx、タイムアウト)の最大再試行回数。レート制限再試行(429)は別途トラッキングされます。
refresh_buffer60トークン有効期限前の積極的な更新をトリガーする秒数。
on_token_refreshedNoneトークンの更新が成功するたびに実行されるコールバック。access_token、refresh_token、expires_atを含む辞書を受け取ります。

ステージング環境

ims_base_urlを上書きしてステージングのAdobe IMSインスタンスを指定します。SDKはDEFAULT_IMS_BASE_URL(https://ims-na1.adobelogin.com)もエクスポートするため、プログラムで本番環境の値を参照する必要がある場合に使用できます。

auth = ServerToServerAuth(
client_id="...",
client_secret="...",
ims_base_url="https://ims-na1-stg1.adobelogin.com",
)

カスタムHTTPクライアント

プロキシサポートやカスタムTLS設定の場合:

import httpx
http_client = httpx.Client(
proxy="http://corporate-proxy:8080",
verify="/path/to/custom-ca-bundle.pem",
)
auth = ServerToServerAuth(
client_id="...",
client_secret="...",
http_client=http_client,
)

スレッドセーフティ

同期認証クラスは完全にスレッドセーフです。複数のスレッドが同時にget_tokenを呼び出し、更新が必要な場合、1つのスレッドのみが更新を実行します。他のスレッドは待機し、同じ結果を受け取ります。外部ロックは必要ありません。

非同期クラスはasyncio.Lockを使用して同じ保証を提供し、単一のイベントループ内の並行コルーチンに対して安全です。