Skip to main content

Overview

Pensar Apex includes a specialized AuthenticationAgent that handles complex authentication flows automatically. It supports:
  • Form-based authentication (username/password POST)
  • JSON API authentication (REST API login)
  • HTTP Basic/Bearer authentication
  • OAuth 2.0 flows (authorization code, implicit, device code)
  • Browser-based authentication (SPAs, JavaScript-rendered forms)
  • Email verification (automated inbox checking)
  • Multi-factor authentication (when possible)
  • CSRF token handling
The authentication agent operates fully autonomously—no human intervention required. It discovers login endpoints, handles redirects, extracts session cookies, and exports credentials for downstream testing.

Quick Start

1

Provide Credentials to Apex

During session creation, pass authentication credentials:
const session = await sessions.create({
  name: "Authenticated Pentest",
  targets: ["https://app.example.com"],
  config: {
    authCredentials: {
      loginUrl: "https://app.example.com/login",
      username: "[email protected]",
      password: "TestPassword123!",
    },
  },
});
2

Run Authentication Agent

import { runAuthenticationAgent } from "@pensar/apex";

const result = await runAuthenticationAgent({
  target: "https://app.example.com",
  model: "claude-sonnet-4-5",
  session,
});

console.log(`Auth ${result.success ? "succeeded" : "failed"}: ${result.summary}`);
3

Use Authenticated Session

After successful authentication, the session contains exportable cookies and headers:
console.log("Cookies:", result.exportedCookies);
console.log("Headers:", result.exportedHeaders);
// Use these for authenticated requests in subsequent testing

How Authentication Works

Credential Management

Apex uses a CredentialManager to securely handle credentials without exposing raw passwords to the AI:
// From src/core/agents/specialized/authenticationAgent/agent.ts
const session = await sessions.create({
  name: "Auth test",
  targets: ["https://example.com"],
  config: {
    authCredentials: {
      username: "admin",
      password: "admin",
      loginUrl: "https://example.com/login"
    },
  },
});

// Session auto-provisions a CredentialManager
const prompt = session.credentialManager.formatForPrompt();
// Prompt contains credential IDs, NOT raw passwords
When the agent needs to use credentials, it references them by ID:
// From src/core/agents/offSecAgent/tools/authenticateSession.ts
if (credentialId && ctx.credentialManager) {
  const stored = ctx.credentialManager.resolve(credentialId);
  username = stored.username;
  password = stored.password;  // Resolved securely at execution time
}
The AI never sees raw passwords. Credentials are resolved server-side during tool execution.

Authentication Flow

The AuthenticationAgent follows a deterministic strategy:
1

Detect Auth Mechanism

If no loginUrl is provided, the agent probes the target:
# Via execute_command tool
curl -i -s -o /dev/null -w "%{http_code}" https://target.com
Indicators:
  • 401/403 → API authentication
  • 302 redirect to /login → Form-based auth
  • WWW-Authenticate header → HTTP Basic/Bearer
  • JSON error → REST API auth
2

Attempt Authentication

Based on detection, the agent tries:API Path:
authenticate_session({
  loginUrl: "https://example.com/api/login",
  credentialId: "cred_xyz",  // Not raw password!
  method: "json_post",
  usernameField: "email",
  passwordField: "password"
});
Browser Path (for SPAs/OAuth):
browser_navigate({ url: "https://example.com/login" });
browser_snapshot();  // Get element refs
browser_fill({ ref: "e3", credentialId: "cred_xyz", credentialField: "username" });
browser_click({ ref: "e5" });  // Submit
browser_get_cookies();  // Extract session
3

Validate Session

After authentication, the agent validates the session:
curl -H "Cookie: session=abc123" https://example.com/api/me
If successful, returns user data. If 401, auth failed.
4

Export Credentials

The agent calls complete_authentication to persist credentials:
complete_authentication({
  success: true,
  summary: "Successfully authenticated as [email protected]",
  exportedCookies: "session=abc123; secure; httpOnly",
  exportedHeaders: { "Authorization": "Bearer eyJhbGc..." },
  strategy: "browser",
});
This writes auth-data.json to the session directory for reuse.

Authentication Methods

Form-Based Authentication

For traditional HTML login forms:
const result = await runAuthenticationAgent({
  target: "https://app.example.com",
  model: "claude-sonnet-4-5",
  session,
  authHints: {
    authScheme: "form",
    browserRequired: false,  // Can use simple POST
  },
});
Apex will:
  1. POST credentials to the login form endpoint
  2. Extract session cookies from Set-Cookie headers
  3. Validate the session by making an authenticated request

JSON API Authentication

For REST APIs:
const session = await sessions.create({
  name: "API Auth",
  targets: ["https://api.example.com"],
  config: {
    authCredentials: {
      loginUrl: "https://api.example.com/auth/login",
      username: "[email protected]",
      password: "password123",
    },
  },
});
Apex will:
  1. POST JSON: {"email": "[email protected]", "password": "password123"}
  2. Extract bearer token from response: {"token": "eyJhbGc..."}
  3. Export header: {"Authorization": "Bearer eyJhbGc..."}

Browser-Based Authentication (SPAs)

For single-page apps with JavaScript-rendered forms:
const result = await runAuthenticationAgent({
  target: "https://spa.example.com",
  model: "claude-sonnet-4-5",
  session,
  authHints: {
    authScheme: "form",
    browserRequired: true,  // Must use browser automation
  },
});
Apex will:
  1. Launch a headless browser with Playwright
  2. Navigate to the login page
  3. Fill the form fields using accessibility tree refs
  4. Click the submit button
  5. Extract cookies (including httpOnly)
  6. Extract tokens from localStorage/sessionStorage
Browser automation is automatic—Apex detects when JavaScript rendering is required.

OAuth 2.0 Flows

For OAuth providers:
const result = await runAuthenticationAgent({
  target: "https://app.example.com",
  model: "claude-sonnet-4-5",
  session,
  authHints: {
    authScheme: "oauth",
    browserRequired: true,
  },
});
Apex will:
  1. Navigate to the OAuth authorization URL
  2. Fill consent form if needed
  3. Handle redirect back to the app
  4. Extract authorization code from URL
  5. Exchange code for access token
  6. Export bearer token for API requests
OAuth consent barriers (like “Allow access?”) are handled automatically when possible. If a CAPTCHA is present, the agent will report failure.

Email Verification

For flows that require email confirmation:
const session = await sessions.create({
  name: "Email Verification Test",
  targets: ["https://app.example.com"],
  config: {
    authCredentials: {
      loginUrl: "https://app.example.com/register",
      username: "[email protected]",
      password: "TestPass123!",
    },
    emailInboxes: [
      {
        address: "[email protected]",
        type: "gmail",
        accessToken: process.env.GMAIL_ACCESS_TOKEN,
        refreshToken: process.env.GMAIL_REFRESH_TOKEN,
        clientId: process.env.GMAIL_CLIENT_ID,
        clientSecret: process.env.GMAIL_CLIENT_SECRET,
      },
    ],
  },
});
Apex will:
  1. Register a new account
  2. Use email_search_messages to find the verification email
  3. Extract the verification link from the email body
  4. Navigate to the link to confirm the account
  5. Log in with the verified credentials
Email verification is fully automated using the Gmail or Outlook adapter. See Email Tools below.

Authentication Tools

The AuthenticationAgent has access to these specialized tools:

API Authentication

authenticate_session

Performs credential-based authentication:
authenticate_session({
  loginUrl: "https://example.com/api/login",
  credentialId: "cred_xyz",  // References stored credential
  method: "json_post",        // or "form_post", "basic_auth"
  usernameField: "email",
  passwordField: "password",
  additionalFields: { "remember": "true" }  // Optional extra fields
});
Returns:
{
  "success": true,
  "authenticated": true,
  "sessionCookie": "session=abc123; Secure; HttpOnly",
  "statusCode": 200,
  "message": "Successfully authenticated as [email protected]"
}

Browser Authentication

browser_navigate

Loads a page in the headless browser:
browser_navigate({ url: "https://example.com/login" });

browser_snapshot

Captures the accessibility tree with element refs:
browser_snapshot();
// Returns:
// textbox "Email" [ref=e3]
// textbox "Password" [ref=e5] (password)
// button "Sign in" [ref=e7]
Always call browser_snapshot before browser_fill or browser_click to get fresh element refs.

browser_fill

Fills a form field using its ref:
browser_fill({
  ref: "e3",              // From browser_snapshot
  credentialId: "cred_xyz",
  credentialField: "username"  // Or "password"
});
The credential is resolved securely—the AI never sees the raw value.

browser_click

Clicks a button or link:
browser_click({ ref: "e7" });

browser_get_cookies

Extracts all cookies (including httpOnly):
browser_get_cookies();
// Returns:
// {
//   "cookies": [{"name": "session", "value": "abc123", "httpOnly": true}],
//   "cookieHeader": "session=abc123"
// }

browser_evaluate

Runs JavaScript to extract tokens:
browser_evaluate({
  script: `
    (() => {
      const tokens = {};
      ['token', 'access_token', 'jwt'].forEach(key => {
        const val = localStorage.getItem(key) || sessionStorage.getItem(key);
        if (val) tokens[key] = val;
      });
      return JSON.stringify(tokens);
    })()
  `
});
// Returns: {"access_token": "eyJhbGc..."}

Email Verification Tools

When emailInboxes are configured in the session:

email_list_inboxes

Lists available email inboxes:
email_list_inboxes();
// Returns: [{"address": "[email protected]", "type": "gmail"}]

email_search_messages

Searches for emails matching a query:
email_search_messages({
  inbox: "[email protected]",
  query: "subject:Verify your email",
  since: new Date(Date.now() - 60000)  // Last 1 minute
});

email_get_message

Fetches full email content:
email_get_message({
  inbox: "[email protected]",
  messageId: "msg_123"
});
// Returns:
// {
//   "subject": "Verify your email",
//   "bodyText": "Click here to verify: https://example.com/verify?token=abc123",
//   "bodyHtml": "<a href='https://example.com/verify?token=abc123'>Verify</a>"
// }

Completion Tools

complete_authentication

Persists authentication data for downstream agents:
complete_authentication({
  success: true,
  summary: "Successfully authenticated via OAuth",
  exportedCookies: "session=abc123; Secure; HttpOnly",
  exportedHeaders: { "Authorization": "Bearer eyJhbGc..." },
  strategy: "oauth",
  authBarrier: undefined  // Or {type: "captcha", reason: "..."}
});
This writes ~/.pensar/sessions/<session>/auth/auth-data.json:
{
  "authenticated": true,
  "summary": "Successfully authenticated via OAuth",
  "cookies": "session=abc123; Secure; HttpOnly",
  "headers": { "Authorization": "Bearer eyJhbGc..." },
  "strategy": "oauth",
  "timestamp": "2026-03-05T12:00:00.000Z"
}

Auth Barriers

The agent detects and reports authentication barriers:
Barrier TypeDescriptionExample
captchaCAPTCHA challenge presentreCAPTCHA, hCaptcha
mfaMulti-factor authentication requiredSMS code, TOTP
oauth_consentOAuth consent screen”Allow XYZ to access your account?“
email_verificationEmail confirmation required”Check your inbox to verify”
phone_verificationPhone number verificationSMS code to phone
When a barrier is encountered:
const result = await runAuthenticationAgent({...});

if (!result.success && result.authBarrier) {
  console.log(`Auth failed: ${result.authBarrier.type}`);
  console.log(`Reason: ${result.authBarrier.reason}`);
}
CAPTCHA and MFA are reported as failures—Apex operates autonomously and cannot solve human challenges.

Best Practices

1. Use Credential Manager (Automatic)

Always provide credentials via authCredentials in the session config:
// ✅ Good: Credentials are managed securely
const session = await sessions.create({
  config: {
    authCredentials: {
      loginUrl: "https://example.com/login",
      username: "[email protected]",
      password: "pass123",
    },
  },
});

// ❌ Bad: Don't pass raw passwords to the agent prompt
const prompt = `Log in with username: [email protected], password: pass123`;

2. Provide Auth Hints

Help the agent by providing hints when known:
await runAuthenticationAgent({
  target: "https://app.example.com",
  model: "claude-sonnet-4-5",
  session,
  authHints: {
    authScheme: "oauth",           // Type of auth
    browserRequired: true,          // Needs browser automation
    csrfRequired: true,             // CSRF token needed
    protectedEndpoints: [           // Test these after auth
      "https://app.example.com/api/me",
      "https://app.example.com/dashboard",
    ],
  },
});

3. Review Auth Data

After successful authentication, review the exported data:
cat ~/.pensar/sessions/<session>/auth/auth-data.json
Ensure:
  • Cookies are present and valid
  • Headers include bearer tokens if needed
  • Strategy matches the expected auth method

4. Test Authenticated Endpoints

Use the exported credentials for subsequent testing:
const authData = JSON.parse(
  fs.readFileSync("~/.pensar/sessions/<session>/auth/auth-data.json")
);

const response = await fetch("https://example.com/api/protected", {
  headers: {
    Cookie: authData.cookies,
    ...authData.headers,
  },
});

Examples

Testing OAuth Flow

const session = await sessions.create({
  name: "OAuth Test",
  targets: ["https://app.example.com"],
  config: {
    authCredentials: {
      username: "[email protected]",
      password: "pass123",
    },
  },
});

const result = await runAuthenticationAgent({
  target: "https://app.example.com",
  model: "claude-sonnet-4-5",
  session,
  authHints: {
    authScheme: "oauth",
    browserRequired: true,
    protectedEndpoints: ["https://app.example.com/api/me"],
  },
});

console.log(`OAuth auth: ${result.success ? "success" : "failed"}`);
console.log(`Bearer token: ${result.exportedHeaders.Authorization}`);

Testing Email Verification

const session = await sessions.create({
  name: "Email Verification Test",
  targets: ["https://app.example.com"],
  config: {
    authCredentials: {
      loginUrl: "https://app.example.com/register",
      username: "[email protected]",
      password: "TestPass123!",
    },
    emailInboxes: [
      {
        address: "[email protected]",
        type: "gmail",
        accessToken: process.env.GMAIL_ACCESS_TOKEN,
        refreshToken: process.env.GMAIL_REFRESH_TOKEN,
        clientId: process.env.GMAIL_CLIENT_ID,
        clientSecret: process.env.GMAIL_CLIENT_SECRET,
      },
    ],
  },
});

const result = await runAuthenticationAgent({
  target: "https://app.example.com",
  model: "claude-sonnet-4-5",
  session,
});

if (result.success) {
  console.log("Account registered and verified!");
  console.log("Session cookie:", result.exportedCookies);
}

Next Steps

Blackbox Testing

Test authenticated endpoints with blackbox testing

Whitebox Testing

Analyze authentication logic in source code

Docker Setup

Run authenticated tests in the Kali container

vLLM Setup

Use local models for authentication testing

Build docs developers (and LLMs) love