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

Esta guía explica cómo autenticarse con la API de Frame.io mediante el SDK para TypeScript 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 TypeScript/JavaScript. 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 TypeScript

El SDK de TypeScript admite cuatro clases de autenticación OAuth, además del uso directo de tokens:

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 (Express, Fasttify, Next.js)
SPA (PKCE)Aplicaciones de navegador que no pueden almacenar un secretoNo
Native App (PKCE)Aplicaciones de escritorio/móviles con redirecciones de esquema de URI personalizadoNo
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 TypeScript 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. Native App sigue el mismo flujo de PKCE que SPA, pero utiliza adobe+<hash>://callback</hash> URI de redireccionamiento que Adobe asigna a su credencial de Native App .Esto permite que la aplicación intercepte el redireccionamiento a nivel del sistema operativo después de la autorización.

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, SPA y Native App; debe estar registrado en el proyecto de Adobe.
  1. Instale el SDK:
$npm 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) para aplicaciones de explorador o Native App (NativeAppAuth) para aplicaciones de escritorio o móviles.

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:

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

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

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() });

Eso es todo. auth.getToken() es una función asíncrona 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, getToken() 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):

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

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

Gestión de la devolución de llamada

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

1 // In your callback handler (e.g. an Express route):
2 await auth.exchangeCode(req.query.code as string);

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

Eso es todo. A partir de este momento, getToken() 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 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);

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 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 devuelve un AuthorizationUrlResult que contiene la URL completa (con code_challenge dePKCE insertado) y el codeVerifier que necesitará en el paso siguiente.

2

Intercambio del código con el verificador

Cuando se redirija al usuario de vuelta:

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

Uso del cliente

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

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.

codeVerifier debe almacenarse de forma segura en el lado del cliente entre la solicitud de autorización y el intercambio de código. Use sessionStorage o un equivalente en aplicaciones de explorador.


Native App (código de autorización + PKCE)

Use este método para aplicaciones de escritorio y móviles. Al crear una credencial de Native App en Adobe Developer Console, Adobe asigna un URI de redireccionamiento con el formato adobe+<hash>://callback</hash>; debe registrar la aplicación para gestionar ese esquema de URI personalizado en el sistema operativo. También se admiten redireccionamientos de bucle invertido, como (http://127.0.0.1:<port>/callback</port>) para desarrollo local. El flujo es idéntico al de SPA: usa PKCE sin secreto de cliente.

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() });

Reglas de URI de redireccionamiento

Adobe aplica las reglas de URI de redireccionamiento en dos puntos: al registrar la credencial en Adobe Developer Console y cuando el parámetro redirect_uri llega al punto final /authorize/v2. El valor que se pase a redirectUri en este SDK debe coincidir con uno de los Redirect URI patterns registrados en la credencial; de lo contrario, Adobe redirige al Default Redirect URI de la credencial.

  • Las credenciales de Web App y SPA requieren HTTPS.
  • Las credenciales de Native App usan un redireccionamiento que no es HTTPS, normalmente el URI adobe+<hash>://callback</hash> mostrado en Developer Console para la credencial.

Consulte Adobe Developer Console para ver los patrones exactos que acepta la credencial.

El SDK para Python no incluye una clase de credencial de Native App, ya que Python no dispone de una forma estándar de registrar controladores de esquemas de

URI personalizados. El SDK para TypeScript admite los cuatro tipos de credencial, incluida Native App.


Actualización manual de tokens

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

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

refresh() está disponible en WebAppAuth, SPAAuth y NativeAppAuth. Genera ConfigurationError si no hay ningún token de actualización disponible, es decir, primero debe llamar a exchangeCode(). ServerToServerAuth no tiene ningún método refresh(): utiliza authenticate() para obtener un token nuevo mediante credenciales de cliente.


Persistencia de tokens

Todas las clases de autenticación admiten exportTokens() e importTokens() para conservar el estado de los tokens entre reinicios. En los flujos Web App, SPA y Native App, 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 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

Almacene los tokens exportados de forma segura. Contienen tokens de acceso y actualización que conceden acceso a la API. Evite escribir tokens

en archivos de texto sin formato en producción.

Persistencia automática con onTokenRefreshed

Para conservar los tokens automáticamente cada vez que se actualicen, use la devolución de llamada 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}

La devolución de llamada recibe la misma estructura que exportTokens() y se activa después de cada actualización correcta del token.


Revocación de tokens

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

1await auth.revoke();

Esto realiza dos solicitudes de revocación a Adobe IMS con el máximo esfuerzo: una para el token de acceso y otra para el token de actualización (en paralelo), y borra todo el estado local de los tokens. En clientes confidenciales (WebAppAuth), las solicitudes de revocación usan HTTP Basic Auth. En clientes públicos (SPAAuth, NativeAppAuth), client_id se envía como parámetro de consulta. Los errores de revocación se registran, pero no se generan. Después de la revocación, el usuario tendrá que volver a autenticarse.


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:

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}

Referencia de errores

ExcepciónCuándo se genera
ConfigurationErrorConfiguración ausente o no válida (por ejemplo, clientId vacío, URI de redireccionamiento que no usa HTTPS o imsBaseUrl que no usa HTTPS)
AuthenticationErrorAdobe IMS rechaza el intercambio o la actualización del token (tiene .errorCode y .errorDescription)
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 .retryAfter para orientarse sobre la espera
PKCEErrorDisponible para el uso del consumidor en flujos PKCE; el SDK no lo genera internamente.

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

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

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}

Referencia de configuración

Estos parámetros tienen valores predeterminados razonables y rara vez es necesario configurarlos. Si necesita personalizar el comportamiento, como apuntar a un IMS de ensayo, inyectar un fetch personalizado, ajustar los tiempos de espera o conectar un registrador, pase cualquiera de ellos como parámetro opcional al construir la clase de autenticación:

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.
imsBaseUrlhttps://ims-na1.adobelogin.comURL base de Adobe IMS. Sobrescríbala para entornos de ensayo o no productivos. Debe usar HTTPS.
fetchglobalThis.fetchImplementación de fetch personalizada para proxy, mTLS o gestión HTTP personalizada.
timeout30000Tiempo de espera de peticiones HTTP en milisegundos para llamadas al extremo de token.
maxRetries2Nú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.
refreshBuffer60Segundos antes de la caducidad del token para activar una actualización proactiva.
onTokenRefreshedundefinedDevolución de llamada que se activa después de cada actualización correcta del token. Recibe un objeto con access_token, refresh_token y expires_at.
loggerNo-op (silencioso)Instancia de registrador con los métodos debug, info, warn, error (por ejemplo, console, pino, winston).

Entornos de ensayo

Apunte a una instancia de ensayo de Adobe IMS sobrescribiendo imsBaseUrl. 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.

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

Fetch personalizado

Para compatibilidad con proxy o configuración de 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});

Seguridad de concurrencia

El SDK para TypeScript es seguro para el uso concurrente. Cuando se producen varias llamadas simultáneas a getToken() y se necesita una actualización, solo se envía una solicitud de actualización. Las demás esperan a la misma promesa y reciben el mismo resultado. No se requiere ningún bloqueo externo. Esta deduplicación utiliza el bucle de eventos de un solo subproceso de JavaScript y una Promise compartida: si ya hay una actualización en curso, los llamadores concurrentes se unen a ella en lugar de iniciar una segunda solicitud. Si se llama a revoke() mientras hay una actualización en curso, la actualización se rechaza con un AuthenticationError y los tokens permanecen borrados; la revocación siempre tiene prioridad.