AutoMax
Guides

Auth strategies and storage state

Log in once per user, reuse the browser state across scenarios, and capture state for recording.

What you'll learn

Which authentication strategies AutoMax supports, where storage state is cached, how a leased user's state is applied to a browser context, and how to capture state for the recorder.

Strategies

StrategyHow state is produced
noneno login
forma headless login with the selectors in auth.form, then context.storageState()
tokenfetch a token, place it as a header, cookie or local-storage entry
oauth-client-credentialsclient-credentials grant against tokenUrl
ssointeractive: automax auth capture --interactive opens codegen so a person completes SSO
customyour defineAuth implementation in steps/auth.ts
automax.project.yaml
auth:
  strategy: form
  storageState: true
  maxAgeMinutes: 120
  form:
    loginPath: /
    usernameSelector: '#user-name'
    passwordSelector: '#password'
    submitSelector: '#login-button'
    readyUrl: /inventory.html

Where state lives

projects/demo-shop/.auth/staging/standard-0.json    # gitignored
projects/demo-shop/.auth/staging/standard-1.json

The index is the pool position of the user. A sidecar records when the state was captured; the fixture recaptures form and token state after maxAgeMinutes.

Capture state on demand

bun run automax auth capture -p demo-shop -e staging --user standard
bun run automax auth capture -p demo-shop -e staging --user standard --all
bun run automax auth capture -p demo-shop -e staging --user admin --interactive
bun run automax auth list -p demo-shop -e staging

The recorder uses the same files through --load-storage, so you can record flows as any pool user.

Custom strategy

projects/demo-shop/steps/auth.ts
import { defineAuth } from '@automax/core/auth';

export const auth = defineAuth({
  strategy: 'custom',
  async login({ browser, config, user }) {
    const context = await browser.newContext({ baseURL: config.env.ui.baseUrl });
    const page = await context.newPage();
    await page.goto('/');
    await page.getByLabel('Username').fill(user.username);
    await page.getByLabel('Password').fill(user.password);
    await page.getByRole('button', { name: 'Login' }).click();
    await page.waitForURL('**/inventory.html');
    return context; // AutoMax saves and closes it
  },
});

Next steps

On this page