@andco/passport

La estrategia de Passport construida sobre la configuración del SDK.

bash
npm install @andco/sdk @andco/passport passport

AndCoStrategy.create

ts
import { AndCoStrategy } from "@andco/passport";

passport.use(
  "andco",
  AndCoStrategy.create(
    {
      client: andco,
      callbackURL: new URL("/auth/callback", process.env.APP_ORIGIN),
      scope: ["email", "profile"],
    },
    verify,
  ),
);

Es una fábrica y no un constructor porque la estrategia necesita la descripción que el servidor de autorización publica de sí mismo. Esa descripción se lee del servidor, pero al construir el SDK y no en tiempo de ejecución, así que create es síncrona y no hace ninguna petición.

Opción Qué es
client la instancia confidencial creada con @andco/sdk/server
callbackURL la URL registrada exacta
name el nombre de la estrategia. Por omisión "andco"
sessionKey la clave de sesión donde Passport guarda el estado y el PKCE
scope los scopes por omisión cuando una ruta no los indica
authorizationTransport fuerza petición directa o PAR

Se construye sobre la implementación oficial de openid-client/passport, de modo que el protocolo no se reescribe y la configuración es la misma del SDK.

Autorizaciones por ruta

ts
app.get(
  "/auth/andco/banco",
  passport.authenticate("andco", {
    scope: ["email", "bank_accounts:read"],
    loginHint: "persona@ejemplo.cl",
    authorizations: [{ resourceServerId: "bank", resource: "https://bank.andco.cl" }],
  }),
);

Cuando la petición lleva loginHint o contribuciones de autorización, la estrategia usa PAR: ni el correo de una persona ni el detalle de los permisos deben quedar en el historial ni en los registros.

El verify

ts
const verify = (tokens, done) => {
  const rest = andco.with(tokens.access_token).rest;
  void rest.http.GET("/userinfo").then(({ data, error }) => {
    if (error) return done(error);
    done(null, { ...data, andco: { accessToken: tokens.access_token, refreshToken: tokens.refresh_token } });
  });
};

Si no pasas uno, AndCoStrategy.defaultVerify(oauth) hace exactamente esto: lee el perfil mínimo y no toca ningún recurso privilegiado.

AndCoPassportUser

ts
import { AndCoPassportUser } from "@andco/passport";

const user = AndCoPassportUser.unwrap(request.user);

Comprueba que request.user tenga la forma que el resto de tu código espera y lanza un TypeError claro si no. Con una petición anónima devuelve undefined en vez de fallar.