Use credentials for scripted login, auth profiles for saved browser state, andlibrettoAuthenticateto recover when a saved session is missing or expired.
credentials are secrets such as usernames, passwords, API keys, and TOTP shared secrets. Use them when the workflow can log in with Playwright.authProfile is named browser state for a signed-in session. Use it when a workflow should start from an existing login or preserve login state across runs.123456789101112131415161718192021222324252627282930313233343536373839import { librettoAuthenticate, workflow } from "libretto"; import { z } from "zod"; export default workflow("portalReport", { startUrl: "https://portal.example.com", credentials: ["username", "password"], authProfile: { name: "portal", refresh: true, }, input: z.object({ reportId: z.string(), }), output: z.object({ title: z.string(), }), async handler(ctx, input) { const { page } = ctx; await librettoAuthenticate(ctx, { credentials: input.credentials, isSignedIn: async ({ page }) => await page .getByRole("button", { name: /account|sign out/i }) .isVisible() .catch(() => false), signIn: async ({ page }, credentials) => { await page.goto("https://portal.example.com/login"); await page.getByLabel("Email").fill(credentials.username); await page.getByLabel("Password").fill(credentials.password); await page.getByRole("button", { name: /log in/i }).click(); }, }); await page.goto(`https://portal.example.com/reports/${input.reportId}`); const title = await page.locator("h1").innerText(); return { title }; }, });
signIn step handles the recovery case where the profile is missing, expired, or logged out. If sign-in succeeds and refresh: true is set, the run saves the updated browser state back to the profile for future runs.input.credentials. Do not pass secrets through --params..env:123LIBRETTO_CLOUD_USERNAME=alice@example.com LIBRETTO_CLOUD_PASSWORD=secret LIBRETTO_CLOUD_TOTP_SECRET=JBSWY3DPEHPK3PXP
LIBRETTO_CLOUD_ prefix and lowercases the rest, so LIBRETTO_CLOUD_USERNAME becomes input.credentials.username..env locally and Libretto Cloud credentials in hosted runs..libretto/profiles/<name>.json; hosted profiles are provider-native browser profiles managed by Libretto Cloud and the active browser provider.authProfile option:123456authProfile: "portal" authProfile: { name: "portal", refresh: true, }
{ name, refresh: true } when successful runs should persist updated browser state back to the profile. On local runs, this updates the local .libretto/profiles/<name>.json file. On hosted runs, it asks the browser provider to persist changes to the provider-native profile.123npx libretto open https://portal.example.com --headed --session portal-login # Log in manually in the browser window. npx libretto save portal --session portal-login --sites portal.example.com
claimSmsOtp. Once an auth profile is saved, the workflow can use authProfile: "portal" or authProfile: { name: "portal", refresh: true } without repeating the manual login every run.1npx libretto import-chrome-profiles portal --cdp-url http://127.0.0.1:9222 --sites portal.example.com
--sites only when saving or importing a local profile. It controls which site storage is copied into the local profile. See CLI profiles..libretto/profiles/<name>.json files. They use provider-native profiles with the workflow's authProfile.name. libretto cloud deploy registers missing profile names, and hosted runs populate or refresh the provider profile when sign-in succeeds.librettoAuthenticate when a workflow has an auth profile and scripted sign-in. The helper runs your isSignedIn check, calls your signIn function if needed, and checks again before the workflow continues.claimSmsOtp inside signIn (or any scripted login) when the portal texts a one-time code. Provision the inbox outside the workflow, claim it before send-code, then wait for the code.