Guía de autenticación del SDK para Python de Frame.io

Esta guía explica cómo autenticarse con la API de Frame.io mediante el SDK para Python de Frame.io (frameio). La API V4 de Frame.io usa Adobe Identity Management Service (IMS), la plataforma de identidad OAuth 2.0 de Adobe. Esta es una referencia independiente para desarrolladores de Python. Todos los ejemplos de código y flujos que aparecen a continuación son solo para el paquete frameio.


Tipos de autenticación en el SDK de Python

El SDK de Python admite cuatro opciones de autenticación:

MétodoCaso de uso¿Hay interacción del usuario?¿Requiere secreto de cliente?
Token estáticoScripts rápidos, pruebas o ya tiene un tokenNoNo
Servidor a servidorServicios backend, trabajos cron, automatizaciónNo
Web AppAplicaciones del lado del servidor (Flask, Django, FastAPI)
SPA (PKCE)Aplicaciones de navegador, CLI o cualquier aplicación que no pueda almacenar un secretoNo
Servidor a servidor permite que la aplicación actúe como una cuenta de servicio sin interacción del usuario. Solo está disponible para cuentas de Frame.io V4 administradas mediante Adobe Admin Console. Web App y SPA permiten que su aplicación actúe como un usuario específico. Ambos utilizan Adobe IMS de forma independiente: el usuario autoriza la aplicación y el SDK intercambia el código resultante por tokens. El SDK de Python maneja el flujo de IMS /authorize/v2 y /token/v3 por usted. Para Web App necesita un secreto de cliente; para SPA, utiliza PKCE en su lugar.

La credencial de Native App de Adobe requiere controladores de esquema de URI personalizados (por ejemplo, adobe+<hash>://…</hash>) que intercepten las redirecciones a nivel del sistema operativo. Python no tiene una forma estándar de registrar dichos controladores, por lo que el SDK de Python no ofrece una clase NativeAppAuth. Para aplicaciones Python con interacción del usuario, utilice WebAppAuth con un servidor de devolución de llamada local (por ejemplo, Flask o FastAPI). Para cargas de trabajo no interactivas, utilice ServerToServerAuth.


Usuarios de cuenta de servicio

Cuando se usa la autenticación de servidor a servidor, la aplicación actúa como usuario de cuenta de servicio, un tipo de cuenta independiente que puede realizar acciones en nombre del servicio. Estos usuarios son visibles para otros usuarios en Frame.io: cuando una cuenta de servicio realiza una acción, su nombre se muestra en la IU. Puede conceder y revocar el acceso de cuentas de servicio mediante Adobe Admin Console y Developer Console. Los nombres de las cuentas de servicio se gestionan desde la IU de Frame.io. De forma predeterminada, la primera conexión S2S se denomina Service Account User, la segunda Service Account User 2, y así sucesivamente.


Inicio rápido

Requisitos previos

  1. Credenciales de Adobe Developer Console:
  • ID de cliente: Obligatorio para todos los flujos Oauth. - Secreto de cliente: Obligatorio para los flujos de servidor a servidor y Web App. - URI de redireccionamiento: Obligatorio para los flujos Web App y SPA; debe estar registrado en el proyecto de Adobe
  1. Instale el SDK:
$pip install frameio

Elección de un método

  • ¿No interviene ningún usuario? Use Server-to-Server (ServerToServerAuth).
  • ¿Interviene un usuario y puede almacenar un secreto? Use Web App (WebAppAuth).
  • ¿Interviene un usuario, pero no puede almacenar un secreto? Use SPA (SPAAuth).

Token de acceso

Si ya dispone de un token de acceso, procedente de otro sistema OAuth o de un intercambio anterior, por ejemplo, mediante nuestro API Explorer, puede pasarlo directamente:

1from frameio import Frameio
2
3client = Frameio(token="YOUR_ACCESS_TOKEN")

Este es el enfoque más sencillo, pero el token caducará en algún momento y el SDK no lo actualizará automáticamente.

Tokens de desarrollador heredados

En el caso de las cuentas migradas a V4 que aún no se administran mediante Adobe Admin Console, puede seguir usando tokens de desarrollador heredados del sitio para desarrolladores de Frame.io. Debe incluir el encabezado x-frameio-legacy-token-auth y establecerlo en true:

1from frameio import Frameio
2
3client = Frameio(
4 token="YOUR_LEGACY_DEVELOPER_TOKEN",
5 headers={"x-frameio-legacy-token-auth": "true"},
6)

Los tokens de desarrollador heredados no caducan, pero son un mecanismo de transición. Para integraciones nuevas y cargas de trabajo de producción, recomendamos usar uno de los flujos OAuth 2.0 que se indican a continuación. Consulte la Guía de migración para obtener más información.


Servidor a servidor (credenciales de cliente)

Use este método para servicios backend y scripts que necesiten acceso a Frame.io sin interacción del usuario. Este flujo solo está disponible para cuentas de Frame.io V4 administradas mediante Adobe Admin Console. La aplicación se autentica como usuario de cuenta de servicio sin intervención humana.

1 from frameio import Frameio
2 from frameio.auth import ServerToServerAuth
3
4 auth = ServerToServerAuth(
5 client_id="YOUR_CLIENT_ID",
6 client_secret="YOUR_CLIENT_SECRET",
7 )
8
9 client = Frameio(token=auth.get_token)

Eso es todo. auth.getToken() es un elemento invocable que el SDK invoca en cada solicitud. Si el token actual sigue siendo válido, se devuelve inmediatamente. Si está a punto de caducar, primero se obtiene uno nuevo de forma totalmente transparente.

Funcionamiento

Las credenciales de cliente, es decir, el ID de cliente y el secreto, nunca caducan. Solo se rotan manualmente por motivos de seguridad. S2S proporciona acceso a la API prácticamente permanente e ininterrumpido, sin intervención manual.

En segundo plano:

  1. En la primera llamada de API, get_token solicita un nuevo token de acceso a Adobe IMS mediante la concesión client_credentials.
  2. El token se almacena en caché en memoria. Los tokens de acceso individuales caducan (normalmente en 24 horas), pero el SDK se encarga de gestionarlo.
  3. Cuando un token almacenado en caché se encuentra dentro del búfer de actualización, cuyo valor predeterminado es 60 segundos antes de la caducidad, el SDK obtiene automáticamente uno nuevo con las mismas credenciales de cliente.
  4. No intervienen tokens de actualización. Las propias credenciales de cliente son el secreto de larga duración y siempre se pueden usar para emitir un nuevo token de acceso.

Autenticación explícita

Si desea obtener el token de forma anticipada (por ejemplo, para detectar rápidamente credenciales incorrectas al iniciar):

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

Web App (código de autorización)

Use este método para aplicaciones del lado del servidor en las que los usuarios inician sesión con su Adobe ID. Este flujo requiere un secreto de cliente, que debe almacenarse de forma segura en el servidor.

1

Redirección del usuario a Adobe IMS

1 auth.refresh() # fetches a new access token using the refresh token
2

Gestión de la devolución de llamada

Cuando Adobe IMS redirija al usuario de vuelta a redirect_uri, extraiga los parámetros code y state. Verifique que state coincida con el valor almacenado y, a continuación, intercambie code por tokens:

1 auth.refresh() # fetches a new access token using the refresh token

Esto intercambia el código de autorización por un token de acceso y un token de actualización, y almacena ambos internamente.

3

Uso del cliente

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

Eso es todo. A partir de este momento, get_token gestiona automáticamente el ciclo de vida del token. Cuando el token de acceso se acerca a la caducidad, el SDK usa el token de actualización para obtener uno nuevo. No se requiere interacción del usuario.

Ejemplo completo de Flask

1import secrets
2from flask import Flask, redirect, request, session
3from frameio import Frameio
4from frameio.auth import WebAppAuth
5
6app = Flask(__name__)
7app.secret_key = secrets.token_bytes(32)
8
9auth = WebAppAuth(
10 client_id="YOUR_CLIENT_ID",
11 client_secret="YOUR_CLIENT_SECRET",
12 redirect_uri="http://localhost:5000/callback",
13)
14
15@app.route("/login")
16def login():
17 state = secrets.token_urlsafe(32)
18 session["oauth_state"] = state
19 return redirect(auth.get_authorization_url(state=state))
20
21@app.route("/callback")
22def callback():
23 if request.args.get("state") != session.pop("oauth_state", None):
24 return "Invalid state parameter", 403
25
26 auth.exchange_code(code=request.args["code"])
27
28 client = Frameio(token=auth.get_token)
29 accounts = client.accounts.index()
30 return f"Authenticated — {len(accounts.data)} account(s) accessible."

Single Page App/PKCE (código de autorización + PKCE)

Use este método para aplicaciones basadas en explorador, aplicaciones de escritorio o herramientas de CLI que no puedan almacenar de forma segura un secreto de cliente. Este flujo usa PKCE (RFC 7636) para proteger el intercambio del código de autorización.

1

Generación de la URL de autorización

1 from frameio.auth import SPAAuth
2
3 auth = SPAAuth(
4 client_id="YOUR_CLIENT_ID",
5 redirect_uri="https://yourapp.com/callback",
6 )
7
8 import secrets
9 state = secrets.token_urlsafe(32)
10
11 result = auth.get_authorization_url(state=state)
12 # result.url -> redirect the user here
13 # result.code_verifier -> store this securely until the callback

get_authorization_url devuelve un AuthorizationUrlResult que contiene la URL completa (con code_challenge de PKCE insertado) y el code_verifier que necesitará en el paso siguiente.

2

Intercambio del código con el verificador

Cuando se redirija al usuario de vuelta:

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

Uso del cliente

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

Eso es todo. La actualización funciona igual que en Web App: el SDK usa automáticamente el token de actualización. La diferencia es que no se envía ningún secreto de cliente durante la actualización, ya que el flujo SPA está diseñado para clientes públicos.


Uso asíncrono

Todas las clases de autenticación tienen una equivalente asíncrona con el prefijo Async. Los ejemplos de código anteriores incluyen las pestañas Síncrono y Asíncrono cuando corresponde.

SíncronoAsíncrono
ServerToServerAuthAsyncServerToServerAuth
WebAppAuthAsyncWebAppAuth
SPAAuthAsyncSPAAuth
La API es idéntica. get_authorization_url sigue siendo síncrono, ya que no realiza E/S, mientras que exchange_code, refresh, revoke y get_token son asíncronos. Use las clases asíncronas con AsyncFrameio.

Actualización manual de tokens

En los flujos Web App y SPA, el SDK actualiza los tokens automáticamente mediante get_token. Si necesita control explícito, puede llamar directamente a refresh():

1 auth.refresh() # fetches a new access token using the refresh token

Esto resulta útil si desea forzar una actualización antes de una operación crítica en lugar de depender del búfer de actualización automático.


Persistencia de tokens

Todas las clases de autenticación admiten export_tokens() e import_tokens() para conservar el estado de los tokens entre reinicios. En los flujos Web App y SPA, esto es especialmente importante, ya que los tokens de acceso y de actualización se almacenan en memoria de forma predeterminada. Si la aplicación se reinicia, los usuarios tendrían que volver a autenticarse a menos que los tokens se conserven. En Server-to-Server, la persistencia es opcional, ya que las credenciales de cliente siempre pueden emitir un token nuevo, pero importar un token almacenado en caché evita un recorrido adicional al iniciar.

Exportación e importación

1# After exchange_code(), save the token state
2token_data = auth.export_tokens()
3# token_data is a dict: {"access_token": "...", "refresh_token": "...", "expires_at": 1234567890.0}
4# Save it to your database, file, or secret store
5
6# On next startup, restore it
7auth.import_tokens(token_data)
8client = Frameio(token=auth.get_token)
9# The SDK will automatically refresh if the token is near expiry

Persistencia automática con on_token_refreshed

Para conservar los tokens automáticamente cada vez que se actualicen, use la devolución de llamada on_token_refreshed:

1import json
2from pathlib import Path
3
4TOKEN_FILE = Path("tokens.json")
5
6def save_tokens(tokens: dict):
7 TOKEN_FILE.write_text(json.dumps(tokens))
8
9auth = WebAppAuth(
10 client_id="...",
11 client_secret="...",
12 redirect_uri="...",
13 on_token_refreshed=save_tokens,
14)
15
16# On startup, restore if available
17if TOKEN_FILE.exists():
18 auth.import_tokens(json.loads(TOKEN_FILE.read_text()))

La devolución de llamada recibe la misma estructura de diccionario que export_tokens() y se activa después de cada actualización correcta del token. En las clases asíncronas, on_token_refreshed puede ser una función normal o una función asíncrona. Ambas son compatibles.


Revocación de tokens

Para cerrar la sesión de un usuario e invalidar sus tokens con Adobe IMS:

1auth.revoke()

Esto realiza una solicitud de revocación con el máximo esfuerzo a Adobe IMS tanto para el token de acceso como para el token de actualización y, a continuación, borra todo el estado local de los tokens. Después de la revocación, el usuario tendrá que volver a autenticarse.

En las clases asíncronas, use await auth.revoke().


Gestión de errores

Todos los errores de autenticación heredan de FrameioAuthError, por lo que puede capturarlos de forma general o gestionar casos específicos:

1from frameio.auth import (
2 FrameioAuthError,
3 AuthenticationError,
4 TokenExpiredError,
5 ConfigurationError,
6 NetworkError,
7 RateLimitError,
8)
9
10try:
11 auth.exchange_code(code="...")
12except TokenExpiredError:
13 # The refresh token has expired; redirect the user to sign in again
14 pass
15except AuthenticationError as e:
16 # Token exchange failed
17 print(f"Error: {e.error_code} - {e.error_description}")
18except NetworkError:
19 # Timeout or connection failure (after retries)
20 pass
21except RateLimitError as e:
22 # 429 from Adobe IMS; retry after e.retry_after seconds
23 pass
24except FrameioAuthError:
25 # Catch-all for any other auth error
26 pass

Referencia de errores

ExcepciónCuándo se genera
ConfigurationErrorConfiguración ausente o no válida (por ejemplo, client_id vacío o URI de redireccionamiento que no usa HTTPS)
AuthenticationErrorAdobe IMS rechaza el intercambio o la actualización del token (tiene .error_code y .error_description)
TokenExpiredErrorEl propio token de actualización ha caducado; el usuario debe volver a autenticarse
NetworkErrorTiempo de espera HTTP agotado o error de conexión tras todos los reintentos
RateLimitErrorAdobe IMS ha devuelto 429; consulte .retry_after para orientarse sobre la espera
PKCEErrorError en la verificación de PKCE (flujo SPA)

Gestión de tokens de actualización caducados en producción

En los flujos Web App y SPA, el token de actualización acabará caducando. Cuando esto ocurra, get_token generará TokenExpiredError. Debe capturarlo y redirigir al usuario de nuevo a través del flujo de autorización.

1from frameio.auth import TokenExpiredError
2
3try:
4 client = Frameio(token=auth.get_token)
5 assets = client.files.list(project_id="...")
6except TokenExpiredError:
7 # Clear persisted tokens and redirect user to login
8 auth.revoke()
9 return redirect("/login")

Referencia de configuración

Todas las clases de autenticación aceptan estos parámetros opcionales:

ParámetroPredeterminadoDescripción
scopesValores predeterminados específicos del flujoÁmbitos OAuth separados por espacios. S2S usa de forma predeterminada openid AdobeID frame.s2s.all; los flujos orientados al usuario usan de forma predeterminada openid email profile offline_access additional_info.roles.
ims_base_urlhttps://ims-na1.adobelogin.comURL base de Adobe IMS. Sobrescríbala para entornos de ensayo o no productivos.
http_clientNonehttpx personalizado.Cliente (o httpx.AsyncClient) para proxy, mTLS o agrupación de conexiones.
timeout30Tiempo de espera de peticiones HTTP en segundos para llamadas al punto final de token.
max_retries2Número máximo de reintentos para errores transitorios (como 5xx o tiempos de espera) agotados. Los reintentos por límite de frecuencia (429) se registran por separado.
refresh_buffer60Segundos antes de la caducidad del token para activar una actualización proactiva.
on_token_refreshedNoneDevolución de llamada que se activa después de cada actualización correcta del token. Recibe un diccionario con access_token, refresh_token y expires_at.

Entornos de ensayo

Apunte a una instancia de ensayo de Adobe IMS sobrescribiendo ims_base_url. El SDK también exporta DEFAULT_IMS_BASE_URL (https://ims-na1.adobelogin.com) por si necesita hacer referencia al valor de producción mediante programación.

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

Cliente HTTP personalizado

Para compatibilidad con proxy o configuración de TLS personalizada:

1import httpx
2
3http_client = httpx.Client(
4 proxy="http://corporate-proxy:8080",
5 verify="/path/to/custom-ca-bundle.pem",
6)
7
8auth = ServerToServerAuth(
9 client_id="...",
10 client_secret="...",
11 http_client=http_client,
12)

Seguridad de subprocesos

Las clases de autenticación síncronas son totalmente seguras para subprocesos. Cuando varios subprocesos llaman a get_token simultáneamente y se necesita una actualización, solo uno de ellos realiza la actualización. Los demás esperan y reciben el mismo resultado. No se requiere ningún bloqueo externo. Las clases asíncronas ofrecen la misma garantía mediante asyncio.Lock, lo que resulta seguro para corrutinas concurrentes dentro de un único bucle de eventos.