Skip to content

SOP 007: Credentials API

Fresh
FieldValue
SOP IDSOP-007
Version1.0
StatusActive (Beta)
SourceSteel Credentials API

Overview

Securely store and inject login credentials into browser sessions without exposing them to agents or the page. Uses enterprise-grade envelope encryption (AES-256-GCM).

Prerequisites

  • Steel account with API key
  • Target site login URL and credentials

Credential Injection Flow

Procedure

Step 1: Create Credentials

typescript
await client.credentials.create({
  origin: "https://app.example.com",
  value: {
    username: "test@example.com",
    password: "password123"
  }
});

Step 2: With TOTP Support

typescript
await client.credentials.create({
  origin: "https://app.example.com",
  value: {
    username: "test@example.com",
    password: "password123",
    totpSecret: "JBSWY3DPEHPK3PXP"
  }
});

Step 3: Create Session with Credential Injection

typescript
const session = await client.sessions.create({
  namespace: "default",
  credentials: {}  // Empty object = use defaults
});

// Custom options
const session = await client.sessions.create({
  namespace: "default",
  credentials: {
    autoSubmit: true,    // Auto-submit login form
    blurFields: true,    // Blur fields to prevent agent reading
    exactOrigin: true    // Only inject on exact origin match
  }
});

Step 4: Navigate and Wait

typescript
await page.goto("https://app.example.com/login");
await page.waitForSelector("form");
await page.waitForTimeout(2000);  // Wait for injection
await page.waitForSelector(".dashboard");  // Confirm login

Namespaces

Use namespaces to manage multiple credentials for the same origin:

typescript
// Create Fred's credentials
await client.credentials.create({
  namespace: "example:fred",
  origin: "https://app.example.com",
  value: { username: "fred@example.com", password: "hunter2" }
});

// Create Jane's credentials
await client.credentials.create({
  namespace: "example:jane",
  origin: "https://app.example.com",
  value: { username: "jane@example.com", password: "letmein" }
});

// Use Fred's credentials
const session = await client.sessions.create({
  namespace: "example:fred",
  credentials: {}
});

Security Architecture

  • Envelope encryption: Each credential gets its own AES-256-GCM key
  • KMS-backed: Data keys encrypted by org-specific KMS master key
  • AAD binding: Ciphertext bound to org ID and origin (prevents replay attacks)
  • Field blurring: Inputs blurred after fill to prevent vision agents reading PII
  • No logging: Credentials never logged or stored in plaintext

Verification Checklist

  • [ ] Credential created with correct origin
  • [ ] Session created with matching namespace
  • [ ] Credential injection occurs within ~2 seconds
  • [ ] Login form auto-submitted (if autoSubmit: true)
  • [ ] Agent cannot read credential values from DOM

Troubleshooting

IssueSolution
Credentials not injectingCheck origin matches exactly, verify namespace
Wrong credentials usedEnsure namespace matches between credential and session
TOTP not fillingVerify totpSecret is the base32-encoded secret
Login fails after fillDisable autoSubmit and debug manually

See Also

SOP Documentation Hub - Built from Steel.dev Official Docs