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

Este guia explica como autenticar com a API do Frame.io usando o SDK TypeScript do 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 TypeScript/JavaScript. Todos os exemplos de código e fluxos abaixo são apenas para o pacote frameio


Tipos de autenticação no SDK TypeScript

O SDK TypeScript oferece suporte a quatro classes de autenticação OAuth, além do uso direto de token:

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 (Express, Fastify, Next.js)SimSim
SPA (PKCE)Aplicativos de navegador que não podem armazenar um segredoSimNão
Aplicativo nativo (PKCE)Aplicativos desktop/móveis com redirecionamentos de esquema de URI personalizadoSimNã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 do TypeScript processa o fluxo /authorize/v2 e /token/v3 do IMS para você. Para Web App você precisa de um client secret; para SPA você usa PKCE.Aplicativo nativo segue o mesmo fluxo PKCE do SPA, mas usa o URI de redirecionamento adobe+<hash>://callback</hash> URI de redirecionamento que a Adobe atribui à sua credencial de aplicativo nativo.Isso permite que o aplicativo intercepte o redirecionamento no nível do SO após a autorização.

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 Web App, SPA e Native App; deve ser registrado no seu projeto da Adobe
  1. Instalar o SDK:
$npm 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) para aplicativos de navegador ou Native App (NativeAppAuth) para aplicativos desktop/para dispositivos móveis.

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:

1import { FrameioClient } from "frameio";
2
3const client = new FrameioClient({ 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:

1import { FrameioClient } from "frameio";
2
3const client = new FrameioClient({
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.

1import { FrameioClient, ServerToServerAuth } from "frameio";
2
3const auth = new ServerToServerAuth({
4 clientId: "YOUR_CLIENT_ID",
5 clientSecret: "YOUR_CLIENT_SECRET",
6});
7
8const client = new FrameioClient({ token: () => auth.getToken() });

É isso. auth.getToken() é uma função assíncrona 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, getToken() 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:

1const auth = new ServerToServerAuth({ clientId: "...", clientSecret: "..." });
2await auth.authenticate(); // throws AuthenticationError if credentials are invalid
3const client = new FrameioClient({ token: () => auth.getToken() });

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 import { WebAppAuth } from "frameio";
2 import crypto from "crypto";
3
4 const auth = new WebAppAuth({
5 clientId: "YOUR_CLIENT_ID",
6 clientSecret: "YOUR_CLIENT_SECRET",
7 redirectUri: "https://yourapp.com/callback",
8 });
9
10 // Generate a cryptographically random state value to prevent CSRF attacks
11 const state = crypto.randomBytes(32).toString("hex");
12
13 const authorizationUrl = auth.getAuthorizationUrl({ state });
14 // Store `state` in the user's session, then redirect them to `authorizationUrl`
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 // In your callback handler (e.g. an Express route):
2 await auth.exchangeCode(req.query.code as string);

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 import { FrameioClient } from "frameio";
2
3 const client = new FrameioClient({ token: () => auth.getToken() });

É isso. A partir deste ponto, getToken() 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 em Express

1import crypto from "crypto";
2import express from "express";
3import session from "express-session";
4import { FrameioClient, WebAppAuth } from "frameio";
5
6const auth = new WebAppAuth({
7 clientId: "YOUR_CLIENT_ID",
8 clientSecret: "YOUR_CLIENT_SECRET",
9 redirectUri: "http://localhost:3000/callback",
10});
11
12const app = express();
13app.use(session({ secret: crypto.randomBytes(32).toString("hex"), resave: false, saveUninitialized: false }));
14
15app.get("/login", (req, res) => {
16 const state = crypto.randomBytes(32).toString("hex");
17 (req.session as any).oauthState = state;
18 res.redirect(auth.getAuthorizationUrl({ state }));
19});
20
21app.get("/callback", async (req, res) => {
22 if (req.query.state !== (req.session as any).oauthState) {
23 return res.status(403).send("Invalid state parameter");
24 }
25
26 await auth.exchangeCode(req.query.code as string);
27
28 const client = new FrameioClient({ token: () => auth.getToken() });
29 const accounts = await client.accounts.index();
30 res.json(accounts);
31});
32
33app.listen(3000);

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 import { SPAAuth } from "frameio";
2
3 const auth = new SPAAuth({
4 clientId: "YOUR_CLIENT_ID",
5 redirectUri: "https://yourapp.com/callback",
6 });
7
8 const state = crypto.randomUUID();
9 const result = await auth.getAuthorizationUrl({ state });
10 // result.url -> redirect the user here
11 // result.codeVerifier -> store this securely until the callback

getAuthorizationUrl retorna um AuthorizationUrlResult contendo a URL completa (com o PKCE code_challenge integrado) e o codeVerifier que você precisa na próxima etapa.

2

Trocar o código pelo verificador

Quando o usuário for redirecionado de volta:

1 await auth.exchangeCode({
2 code: "CODE_FROM_CALLBACK",
3 codeVerifier: result.codeVerifier,
4 });
3

Use o cliente

1 import { FrameioClient } from "frameio";
2
3 const client = new FrameioClient({ token: () => auth.getToken() });

É 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.

O codeVerifier deve ser armazenado com segurança no lado do cliente entre a solicitação de autorização e a troca do código. Use sessionStorage ou equivalente em aplicativos de navegador.


Native App (código de autorização + PKCE)

Use isso para aplicativos de desktop e mobile. Quando você cria uma credencial de Native App no Adobe Developer Console, a Adobe atribui um URI de redirecionamento do formulário adobe+<hash>://callback</hash> — você registra seu aplicativo para processar esse esquema de URI personalizado no nível do sistema operacional. Redirecionamentos de loopback (http://127.0.0.1:<port>/callback</port>) também são compatíveis com desenvolvimento local. O fluxo é idêntico ao SPA: usa PKCE sem client secret.

1import { NativeAppAuth } from "frameio";
2
3const auth = new NativeAppAuth({
4 clientId: "YOUR_CLIENT_ID",
5 redirectUri: "adobe+abc123def456://callback", // from your Adobe Developer Console Native App credential
6 // Also supports loopback: "http://127.0.0.1:8080/callback"
7});
8
9const { url, codeVerifier } = await auth.getAuthorizationUrl({
10 state: crypto.randomUUID(),
11});
12
13// Open system browser to `url`
14// Listen for redirect on your custom URI scheme or loopback server
15
16await auth.exchangeCode({ code: "CODE_FROM_REDIRECT", codeVerifier });
17const client = new FrameioClient({ token: () => auth.getToken() });

Regras de URI de redirecionamento

A Adobe aplica regras de URI de redirecionamento em dois pontos: quando você registra a credencial no Adobe Developer Console e quando o parâmetro redirect_uri chega ao ponto de acesso /authorize/v2. O valor que você passa para redirectUri neste SDK deve corresponder a um dos “Padrões de URI de redirecionamento” registrados na credencial; caso contrário, a Adobe redireciona para a URI de redirecionamento padrão na credencial.

  • Credenciais de Web App e SPA exigem HTTPS.
  • Credenciais Native App usam um redirecionamento não HTTPS, normalmente a URI adobe+<hash>://callback</hash> mostrado no Developer Console para a credencial.

Consulte o Adobe Developer Console para os padrões exatos aceitos para sua credencial.

O SDK para Python não inclui uma classe de credencial Native App, pois o Python não tem uma forma padrão de registrar manipuladores

de esquema de URI personalizado. O SDK para TypeScript oferece suporte a todos os quatro tipos de credenciais, incluindo Native App.


Atualização manual de token

Para fluxos Web App, SPA e Native App, o SDK atualiza tokens automaticamente por meio de getToken(). Se você precisar de controle explícito, pode chamar refresh() diretamente:

1await 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.

refresh() está disponível no WebAppAuth, SPAAuth e NativeAppAuth. Ele gera ConfigurationError se nenhum token de atualização estiver disponível (ou seja, você deve chamar exchangeCode() primeiro). ServerToServerAuth não tem um método refresh() — ele usa authenticate() para buscar um novo token via credenciais do cliente.


Persistência de tokens

Todas as classes de autenticação oferecem suporte a exportTokens() e importTokens() para persistir o estado do token entre reinicializações. Para fluxos Web App, SPA e Native App, 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 exchangeCode(), save the token state
2const tokenData = auth.exportTokens();
3// tokenData is: { 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.importTokens(tokenData);
8const client = new FrameioClient({ token: () => auth.getToken() });
9// The SDK will automatically refresh if the token is near expiry

Armazene os tokens exportados com segurança. Eles contêm tokens de acesso e de atualização que concedem acesso à API. Evite escrever tokens

em arquivos de texto sem formatação na produção.

Persistência automática com onTokenRefreshed

Para persistir tokens automaticamente sempre que forem atualizados, use o callback onTokenRefreshed:

1import fs from "fs/promises";
2
3const TOKEN_FILE = "tokens.json";
4
5const auth = new WebAppAuth({
6 clientId: "...",
7 clientSecret: "...",
8 redirectUri: "...",
9 onTokenRefreshed: (tokens) => {
10 fs.writeFile(TOKEN_FILE, JSON.stringify(tokens));
11 },
12});
13
14// On startup, restore if available
15try {
16 const saved = JSON.parse(await fs.readFile(TOKEN_FILE, "utf-8"));
17 auth.importTokens(saved);
18} catch {
19 // No saved tokens — user will need to authenticate
20}

O callback recebe o mesmo formato de exportTokens() e é acionado após cada atualização de token bem-sucedida.


Revogação de tokens

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

1await auth.revoke();

Isso faz duas solicitações de revogação de melhor esforço ao Adobe IMS, uma para o token de acesso e outra para o token de atualização, em paralelo, e limpa todo o estado local do token.Para clientes confidenciais (WebAppAuth), as solicitações de revogação usam autenticação básica HTTP; para clientes públicos (SPAAuth, NativeAppAuth), o client_id é enviado como parâmetro de consulta. Erros de revogação são registrados, mas não gerados. Após a revogação, o usuário precisará se autenticar novamente.


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:

1import {
2 FrameioAuthError,
3 AuthenticationError,
4 TokenExpiredError,
5 ConfigurationError,
6 NetworkError,
7 RateLimitError,
8} from "frameio";
9
10try {
11 await auth.exchangeCode("...");
12} catch (error) {
13 if (error instanceof TokenExpiredError) {
14 // The refresh token has expired; redirect the user to sign in again
15 } else if (error instanceof AuthenticationError) {
16 // Token exchange failed
17 console.error(`Error: ${error.errorCode} - ${error.errorDescription}`);
18 } else if (error instanceof NetworkError) {
19 // Timeout or connection failure (after retries)
20 } else if (error instanceof RateLimitError) {
21 // 429 from Adobe IMS; retry after error.retryAfter seconds
22 } else if (error instanceof FrameioAuthError) {
23 // Catch-all for any other auth error
24 }
25}

Referência de erros

ExceçãoQuando é gerada
ConfigurationErrorConfiguração ausente ou inválida (por exemplo, clientId vazio, URI de redirecionamento não HTTPS, imsBaseUrl não HTTPS)
AuthenticationErrorTroca ou atualização de token rejeitada pelo Adobe IMS (tem .errorCode e .errorDescription)
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 .retryAfter para orientação de backoff
PKCEErrorDisponível para uso do consumidor em fluxos PKCE; não é gerado internamente pelo SDK

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

Para fluxos Web App, SPA e Native App, o token de atualização acabará expirando.Quando isso acontecer, getToken() gera TokenExpiredError. Você deve capturar isso e redirecionar o usuário pelo fluxo de autorização novamente.

1import { TokenExpiredError } from "frameio";
2
3try {
4 const client = new FrameioClient({ token: () => auth.getToken() });
5 const assets = await client.files.list({ projectId: "..." });
6} catch (error) {
7 if (error instanceof TokenExpiredError) {
8 // Clear persisted tokens and redirect user to login
9 await auth.revoke();
10 return res.redirect("/login");
11 }
12}

Referência de configuração

Esses parâmetros têm padrões sensatos e raramente precisam ser definidos. Se precisar personalizar o comportamento, apontar para um IMS de staging, injetar um fetch personalizado, ajustar tempos-limite ou conectar um logger, passe qualquer um deles como parâmetros opcionais ao construir a classe de autenticação:

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.
imsBaseUrlhttps://ims-na1.adobelogin.comURL base do Adobe IMS. Substitua para ambientes de preparo ou não produção. Deve usar HTTPS.
fetchglobalThis.fetchImplementação personalizada de fetch para proxy, mTLS ou manipulação HTTP personalizada.
timeout30000Tempo-limite de solicitação HTTP em milissegundos para chamadas ao ponto de acesso de token.
maxRetries2Número máximo de novas tentativas para falhas transitórias (5xx, tempos-limite). Novas tentativas por limite de taxa (429) são rastreadas separadamente.
refreshBuffer60Segundos antes da expiração do token para acionar a atualização proativa.
onTokenRefreshedundefinedCallback disparado após cada atualização de token bem-sucedida.Recebe um objeto com access_token, refresh_token e expires_at.
loggerSem operação (silencioso)Instância do logger com métodos debug, info, warn, error (por exemplo console, pino, winston).

Ambientes de preparo

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

1const auth = new ServerToServerAuth({
2 clientId: "...",
3 clientSecret: "...",
4 imsBaseUrl: "https://ims-na1-stg1.adobelogin.com",
5});

Busca personalizada

Para suporte a proxy ou configuração TLS personalizada:

1import { ProxyAgent } from "undici";
2
3const proxyAgent = new ProxyAgent("http://corporate-proxy:8080");
4
5const auth = new ServerToServerAuth({
6 clientId: "...",
7 clientSecret: "...",
8 fetch: (url, init) => fetch(url, { ...init, dispatcher: proxyAgent }),
9});

Segurança de concorrência

O SDK para TypeScript é seguro para uso simultâneo. Quando várias chamadas getToken() acontecem simultaneamente e uma atualização é necessária, apenas uma solicitação de atualização é disparada. As outras aguardam a mesma promise e recebem o mesmo resultado. Nenhum bloqueio externo é necessário. Essa deduplicação usa o loop de eventos de thread única do JavaScript e uma Promise compartilhada. Se uma atualização já estiver em andamento, chamadores simultâneos se juntam a ela em vez de iniciar uma segunda solicitação. Se revoke() for chamado enquanto uma atualização estiver em andamento, a atualização será rejeitada com AuthenticationError e os tokens permanecerão limpos. A revogação sempre vence.