Frame.io Python SDK - Guia de autenticação

Este guia explica como autenticar com a API do Frame.io usando o SDK Python Frame.io (frameio). A API Frame.io V4 usa o Adobe Identity Management Service (IMS), a plataforma de identidade OAuth 2.0 da Adobe. Esta é uma referência independente para desenvolvedores Python. Todos os exemplos de código e fluxos abaixo são apenas para o pacote frameio


Tipos de autenticação no SDK Python

O SDK Python é compatível com quatro opções de autenticação:

MétodoCaso de usoInteração do usuário?Requer client secret?
Token estáticoScripts rápidos, testes ou quando você já tem um tokenNãoNão
Servidor para servidorServiços de backend, cron jobs, automaçãoNãoSim
Aplicativo webAplicativos do lado do servidor (Flask, Django, FastAPI)SimSim
SPA (PKCE)Aplicativos de navegador, CLIs ou qualquer aplicativo que não possa armazenar um segredoSimNão
Server-to-Server permite que o aplicativo atue como uma conta de serviço sem interação do usuário.Está disponível somente para contas do Frame.io V4 administradas por meio do Adobe Admin Console.Web App e SPA permitem que o aplicativo atue como um usuário específico.Ambos usam Adobe IMS por baixo: o usuário autoriza o aplicativo, e o SDK troca o código resultante por tokens.O SDK Python manipula o fluxo IMS /authorize/v2 e /token/v3 para você. Para Web App você precisa de um client secret; para SPA você usa PKCE.

A credencial Native App da Adobe exige manipuladores de esquema de URI personalizado, por exemplo, adobe+<hash>://…</hash>) que interceptam redirecionamentos no nível do sistema operacional.O Python não tem uma forma padrão de registrar esses manipuladores, portanto o SDK Python não oferece uma classe NativeAppAuth.Para aplicativos Python com interação do usuário, use WebAppAuth com um servidor de callback local, como Flask ou FastAPI.Para cargas de trabalho não interativas, use ServerToServerAuth.


Usuários de conta de serviço

Ao usar autenticação Server-to-Server, seu aplicativo atua como um usuário de conta de serviço, um tipo distinto de conta que pode executar ações em nome do serviço. Eles ficam visíveis para outros usuários no Frame.io: quando uma conta de serviço executa uma ação, seu nome é exibido na IU. Você pode conceder e revogar o acesso da conta de serviço pelo Adobe Admin Console e Developer Console. Os nomes de conta de serviço são gerenciados pela IU do Frame.io. Por padrão, a primeira conexão S2S é nomeada Usuários de conta de serviço, a segunda Usuários de conta de serviço 2 e assim por diante.


Início rápido

Pré-requisitos

  1. Credenciais do Adobe Developer Console:
  • ID do cliente — obrigatório para todos os fluxos OAuth - Segredo do cliente — obrigatório para fluxos servidor a servidor e aplicativo web - URI de redirecionamento — obrigatório para fluxos de aplicativo web e SPA; deve estar registrado no Projeto do Adobe
  1. Instalar o SDK:
$pip install frameio

Escolha de um método

  • **Nenhum usuário envolvido?**Use Server-to-Server (ServerToServerAuth).
  • **Usuário envolvido e você pode armazenar um segredo?**Use Web App (WebAppAuth).
  • **Usuário envolvido, mas você não pode armazenar um segredo?**Use SPA (SPAAuth).

Token de acesso

Se você já tiver um token de acesso de outro sistema OAuth ou de uma troca anterior, por exemplo, pelo nosso API Explorer, poderá passá-lo diretamente:

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

Essa é a abordagem mais simples, mas o token acabará expirando e o SDK não o atualizará para você.

Tokens de desenvolvedor legados

Para contas migradas para a V4 que ainda não são administradas pelo Adobe Admin Console, você pode continuar usando Tokens de desenvolvedor legados do site de desenvolvedores do Frame.io. Você deve incluir o cabeçalho x-frameio-legacy-token-auth e defini-lo como true:

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

Tokens de desenvolvedor legados não expiram, mas são um mecanismo de transição. Para novas integrações e cargas de trabalho de produção, recomendamos usar um dos fluxos OAuth 2.0 abaixo. Consulte o Guia de migração para obter detalhes.


Servidor para servidor (Credenciais do cliente)

Use isso para serviços de backend e scripts que precisam de acesso ao Frame.io sem interação do usuário. Esse fluxo só está disponível para contas Frame.io V4 administradas pelo Adobe Admin Console. Seu aplicativo se autentica como um usuário de conta de serviço sem intervenção 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)

É isso. Auth.get_token é um callable que o SDK invoca em cada solicitação. Se o token atual ainda for válido, ele retornará imediatamente. Se estiver prestes a expirar, ele buscará um novo primeiro, de forma totalmente transparente.

Como funciona

Suas credenciais do cliente (ID + segredo do cliente) nunca expiram. Você só precisa alterná-las manualmente por higiene de segurança. S2S oferece acesso à API efetivamente permanente e ininterrupto, sem nenhuma intervenção manual.

Nos bastidores:

  1. Na primeira chamada da API, get_token solicita um novo token de acesso do Adobe IMS usando a concessão client_credentials.
  2. O token é armazenado em cache na memória. Tokens de acesso individuais expiram (normalmente em 24 horas), mas isso é tratado para você.
  3. Quando um token em cache está dentro do buffer de atualização (padrão: 60 segundos antes da expiração), o SDK busca um novo automaticamente usando as mesmas credenciais de cliente.
  4. Não há tokens de atualização envolvidos. As próprias credenciais de cliente são o segredo de longa duração e sempre podem ser usadas para emitir um novo token de acesso.

Autenticação explícita

Se quiser buscar o token antecipadamente, por exemplo, para falhar rapidamente com credenciais incorretas na inicialização:

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

Aplicativo web (Código de autorização)

Use isso para aplicativos do lado do servidor em que os usuários fazem logon com sua Adobe ID. Este fluxo requer um segredo do cliente, que deve ser armazenado com segurança no servidor.

1

Redirecionar o usuário para o Adobe IMS

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

Processar o callback

Quando o Adobe IMS redireciona o usuário de volta para o redirectUri, extraia os parâmetros code e state.Verifique se o estado corresponde ao que você armazenou e troque o código por tokens:

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

Isso troca o código de autorização por um token de acesso e um token de atualização, armazenando ambos internamente.

3

Use o cliente

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

É isso. A partir deste ponto, get_token gerencia o ciclo de vida do token automaticamente. Quando o token de acesso se aproxima do vencimento, o SDK usa o token de atualização para obter um novo. Nenhuma interação do usuário necessária.

Exemplo completo do 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."

Aplicativo de página única / PKCE (Código de autorização + PKCE)

Use isso para aplicativos baseados em navegador, aplicativos para desktop ou ferramentas de CLI que não conseguem armazenar um client secret com segurança. Este fluxo usa PKCE (RFC 7636) para proteger a troca de código de autorização.

1

Gerar a URL de autorização

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 retorna um AuthorizationUrlResult contendo a URL completa (com o PKCE code_challenge integrado) e o code_verifier que você precisa na próxima etapa.

2

Trocar o código pelo verificador

Quando o usuário for redirecionado de volta:

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

Use o cliente

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

É isso. A atualização funciona da mesma forma que no Web App - o SDK usa o token de atualização automaticamente. A diferença é que nenhum client secret é enviado durante a atualização, pois o fluxo SPA foi projetado para clientes públicos.


Uso assíncrono

Toda classe de autenticação tem uma contraparte assíncrona com prefixo Async. Os exemplos de código acima incluem abas Sync e Async quando aplicável.

SincronizarAssíncrono
ServerToServerAuthAsyncServerToServerAuth
WebAppAuthAsyncWebAppAuth
SPAAuthAsyncSPAAuth
A API é idêntica. get_authorization_url permanece síncrono (sem I/O), enquanto exchange_code, refresh, revoke e get_token são todos async. Use as classes assíncronas com AsyncFrameio.

Atualização manual de token

Para fluxos de aplicativo web e SPA, o SDK atualiza tokens automaticamente via get_token. Se você precisar de controle explícito, pode chamar refresh() diretamente:

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

Isso é útil quando você quer forçar uma atualização antes de uma operação crítica, em vez de depender do buffer de atualização automática.


Persistência de tokens

Todas as classes de autenticação oferecem suporte a export_tokens() e import_tokens() para persistir o estado do token entre reinicializações. Para fluxos Web App e SPA, isso é especialmente importante, pois os tokens de acesso e de atualização ficam na memória por padrão. Se o aplicativo reiniciar, os usuários precisarão se autenticar novamente, a menos que você persista esses tokens. Para servidor para servidor, a persistência é opcional (as credenciais de cliente sempre podem emitir um novo token), mas importar um token em cache evita uma ida e volta extra na inicialização.

Exportar e importar

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

Persistência automática com on_token_refreshed

Para persistir tokens automaticamente sempre que forem atualizados, use o callback 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()))

O callback recebe a mesma forma de dict que export_tokens() e é executado após cada atualização de token bem-sucedida.Para as classes async, on_token_refreshed pode ser uma função regular ou uma função assíncrona. Ambas são compatíveis.


Revogação de tokens

Para encerrar a sessão de um usuário e invalidar seus tokens com o Adobe IMS:

1auth.revoke()

Isso faz uma solicitação de revogação de melhor esforço ao Adobe IMS para o token de acesso e o token de atualização, e depois limpa todo o estado local do token. Após a revogação, o usuário precisará se autenticar novamente.

Para as classes assíncronas, use await auth.revoke().


Tratamento de erros

Todos os erros de autenticação herdam de FrameioAuthError, portanto você pode capturá-los de forma ampla ou tratar 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

Referência de erros

ExceçãoQuando é gerada
ConfigurationErrorConfiguração ausente ou inválida, por exemplo, client_id vazio ou URI de redirecionamento não HTTPS
AuthenticationErrorTroca ou atualização de token rejeitada pelo Adobe IMS (tem .error_code e .error_description)
TokenExpiredErrorO próprio token de atualização expirou; o usuário deve se autenticar novamente
NetworkErrorTempo-limite HTTP ou falha de conexão após todas as novas tentativas
RateLimitErrorO Adobe IMS retornou 429; verifique .retry_after para orientação de backoff
PKCEErrorFalha na verificação PKCE (fluxo SPA)

Tratamento de tokens de atualização expirados em produção

Para fluxos Web App e SPA, o token de atualização acabará expirando.Quando isso acontece, get_token gerará TokenExpiredError. Você deve capturar isso e redirecionar o usuário pelo fluxo de autorização novamente.

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")

Referência de configuração

Todas as classes de auth aceitam estes parâmetros opcionais:

ParâmetroPadrãoDescrição
scopesPadrões específicos do fluxoEscopos OAuth separados por espaços. S2S usa por padrão openid AdobeID frame.s2s.all; fluxos voltados ao usuário têm como padrão openid email profile offline_access additional_info.roles.
ims_base_urlhttps://ims-na1.adobelogin.comURL base do Adobe IMS. Substitua para ambientes de preparo ou não produção.
http_clientNenhumhttpx personalizado.Client (ou httpx.AsyncClient) para proxy, mTLS ou pooling de conexões.
timeout30Tempo-limite de solicitação HTTP em segundos para chamadas ao ponto de acesso de token.
max_retries2Número máximo de novas tentativas para falhas transitórias (5xx, tempos-limite). Novas tentativas por limite de taxa (429) são rastreadas separadamente.
refresh_buffer60Segundos antes da expiração do token para acionar a atualização proativa.
on_token_refreshedNenhumCallback disparado após cada atualização de token bem-sucedida. Recebe um dict com access_token, refresh_token e expires_at.

Ambientes de preparo

Aponte para uma instância de preparo do Adobe IMS substituindo ims_base_url. O SDK também exporta DEFAULT_IMS_BASE_URL (https://ims-na1.adobelogin.com) se precisar referenciar o valor de produção programaticamente.

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

Cliente HTTP personalizado

Para suporte a proxy ou configuração 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)

Segurança de threads

As classes de autenticação sincronizadas são totalmente thread-safe. Quando várias threads chamam get_token simultaneamente e uma atualização é necessária, apenas uma thread executa a atualização. As outras aguardam e recebem o mesmo resultado. Nenhum bloqueio externo é necessário. As classes assíncronas fornecem a mesma garantia usando `asyncio.Lock“ seguro para corrotinas simultâneas dentro de um único loop de eventos.