SuperAPI AI Directory

sigcli-auth-proxy

General & other

View repository

Updated 10-15 22:34

About this skill

sigcli Auth Proxy Skill

Skill by ara.so — Devtools Skills collection.

Overview

sigcli is an authentication CLI and proxy that handles browser-based SSO, OAuth2 flows, and credential injection for AI agents. It extracts credentials (cookies, localStorage, OAuth tokens), encrypts them locally with AES-256-GCM, and injects them into HTTP requests — so agents can access authenticated APIs without ever seeing secrets.

Key capabilities:

  • Browser SSO authentication for any website/SSO provider
  • OAuth2 Client Credentials flow with automatic token refresh
  • Encrypted credential storage (~/.sig/credentials/)
  • Transparent HTTP proxy for agents (sig proxy)
  • Direct authenticated requests (sig request)
  • Command execution with injected credentials (sig run)
  • Multi-provider support in single commands

Installation

npm install -g @sigcli/cli

Initialize configuration:

sig init  # creates ~/.sig/config.yaml

Core Commands

Authentication

# Browser-based SSO (auto-provision)
sig login https://jira.example.com

# OAuth2 Client Credentials
sig login https://api.example.com \
  --strategy oauth2 \
  --token-url https://api.example.com/oauth/token \
  --client-id $CLIENT_ID \
  --client-secret $CLIENT_SECRET

# Check authentication status
sig status                    # all providers
sig status jira-example       # specific provider

# View credentials (redacted by default)
sig get jira-example          # shows redacted credentials
sig get jira-example --no-redaction  # shows raw tokens

# Logout (clears credentials, keeps config)
sig logout jira-example

Making Authenticated Requests

# Direct HTTP request
sig request https://jira.example.com/rest/api/2/myself

# POST with JSON body
sig request https://jira.example.com/rest/api/2/search \
  --method POST \
  --body '{"jql":"assignee=currentUser()"}'

# Multiple providers in one request
sig request https://api.example.com/data \
  --provider jira-example,github-enterprise

Running Commands with Auth

# Execute command with credentials injected
sig run jira-example -- curl https://jira.example.com/rest/api/2/myself

# Multi-provider execution
sig run github-enterprise,jira-example -- node script.js

# Environment variables are automatically injected based on apply[] rules

HTTP Proxy Mode

# Start MITM proxy (injects credentials transparently)
sig proxy --port 8080

# In another terminal or agent config:
export HTTP_PROXY=http://localhost:8080
export HTTPS_PROXY=http://localhost:8080

curl https://jira.example.com/rest/api/2/myself
# Credentials auto-injected by sig proxy

Configuration

Configuration lives in ~/.sig/config.yaml. Providers are auto-provisioned for SSO sites, or manually configured for public sites and OAuth2.

Auto-Provisioned SSO (Zero Config)

# ~/.sig/config.yaml (generated by sig login)
jira-example:
  domains:
    - jira.example.com
  entryUrl: https://jira.example.com/
  strategy: browser
  extract:
    - from: cookies
      as: session
      match: '*'
  apply:
    - in: header
      name: Cookie
      value: '${session}'

Public Sites with Validation

Public sites need validateUrl and/or validateRule to distinguish auth cookies from tracking cookies:

reddit:
  domains:
    - www.reddit.com
    - reddit.com
  entryUrl: https://www.reddit.com/
  validateUrl: https://www.reddit.com/prefs/friends
  strategy: browser
  extract:
    - from: cookies
      as: cookie
      match: '*'
  apply:
    - in: header
      name: Cookie
      value: '${cookie}'

Validation Rule (JavaScript Expression)

For APIs that return 200 even when unauthenticated:

douyin:
  domains:
    - www.douyin.com
  entryUrl: https://www.douyin.com
  validateUrl: https://www.douyin.com/aweme/v1/web/notice/count/
  validateRule: 'res.body.status_code === 0'
  strategy: browser
  extract:
    - from: cookies
      as: cookie
      match: '*'
  apply:
    - in: header
      name: Cookie
      value: '${cookie}'

validateRule context:

  • res.status - HTTP status code
  • res.body - parsed JSON or raw string
  • res.headers - response headers

OAuth2 Client Credentials

api-example:
  domains:
    - api.example.com
  strategy: oauth2
  tokenUrl: https://api.example.com/oauth/token
  clientId: ${CLIENT_ID}
  clientSecret: ${CLIENT_SECRET}
  scopes:
    - read:data
    - write:data
  extract:
    - from: oauth2
      as: access_token
  apply:
    - in: header
      name: Authorization
      value: 'Bearer ${access_token}'

localStorage Extraction

For apps that store tokens in localStorage:

app-slack:
  domains:
    - your-org.enterprise.slack.com
  entryUrl: https://app.slack.com/client/T12345
  strategy: browser
  extract:
    - from: cookies
      as: session
      match: '*'
    - from: localStorage
      as: xoxc-token
      match: localConfig_v2
      jsonPath: teams.T12345.token
  apply:
    - in: header
      name: Cookie
      value: '${session}'
    - in: header
      name: Authorization
      value: 'Bearer ${xoxc-token}'

Multi-Domain Providers

For sites that use multiple domains (e.g., twitter.com → x.com migration):

x:
  domains:
    - x.com
    - twitter.com
  entryUrl: https://x.com/
  validateUrl: https://x.com/i/api/2/notifications/all.json?count=1
  strategy: browser
  extract:
    - from: cookies
      as: cookie
      match: '*'
    - from: cookies
      as: ct0
      match: 'ct0'
  apply:
    - in: header
      name: Cookie
      value: '${cookie}'
    - in: header
      name: x-csrf-token
      value: '${ct0}'

Network Proxy (for VPN/SOCKS)

If the browser needs to go through a proxy:

x:
  networkProxy: socks5://127.0.0.1:3333
  # ... rest of config

Real-World Usage Patterns

Pattern 1: Agent Accessing Jira

// agent-jira.ts
import { execSync } from 'child_process';

function getJiraIssue(issueKey: string): object {
  const url = `https://jira.example.com/rest/api/2/issue/${issueKey}`;
  const result = execSync(`sig request ${url}`, { encoding: 'utf8' });
  return JSON.parse(result);
}

function searchJiraIssues(jql: string): object {
  const url = 'https://jira.example.com/rest/api/2/search';
  const body = JSON.stringify({ jql });
  const result = execSync(
    `sig request ${url} --method POST --body '${body}'`,
    { encoding: 'utf8' }
  );
  return JSON.parse(result);
}

// Usage
const issue = getJiraIssue('PROJ-123');
const myIssues = searchJiraIssues('assignee=currentUser()');

Pattern 2: OAuth2 API with Auto-Refresh

// oauth-api-client.ts
import { execSync } from 'child_process';

class AuthenticatedAPIClient {
  constructor(private provider: string) {}

  private exec(cmd: string): string {
    return execSync(cmd, { encoding: 'utf8' });
  }

  async makeRequest(endpoint: string, method = 'GET', body?: object): Promise<any> {
    let cmd = `sig request https://api.example.com${endpoint} --method ${method}`;
    if (body) {
      cmd += ` --body '${JSON.stringify(body)}'`;
    }
    
    try {
      const result = this.exec(cmd);
      return JSON.parse(result);
    } catch (error) {
      // sig automatically refreshes OAuth2 tokens on 401
      throw error;
    }
  }

  checkStatus(): void {
    const status = this.exec(`sig status ${this.provider}`);
    console.log(status);
  }
}

// Usage
const client = new AuthenticatedAPIClient('oauth-mock');
const data = await client.makeRequest('/api/data');

Pattern 3: Proxy Mode for HTTP Client

// proxy-mode-agent.ts
import axios from 'axios';
import { spawn } from 'child_process';

// Start sig proxy
const proxy = spawn('sig', ['proxy', '--port', '8080'], {
  stdio: 'inherit'
});

// Configure axios to use proxy
const client = axios.create({
  proxy: {
    host: 'localhost',
    port: 8080,
  },
});

// All requests auto-authenticated
async function fetchData() {
  const response = await client.get('https://jira.example.com/rest/api/2/myself');
  return response.data;
}

// Cleanup
process.on('exit', () => proxy.kill());

Pattern 4: Multi-Provider Request

// multi-provider-sync.ts
import { execSync } from 'child_process';

function syncDataAcrossSystems(): void {
  // Single request with credentials from multiple providers
  const result = execSync(
    `sig request https://api.example.com/sync \
      --provider jira-example,github-enterprise \
      --method POST \
      --body '{"sync": true}'`,
    { encoding: 'utf8' }
  );
  
  console.log('Sync result:', JSON.parse(result));
}

Pattern 5: Running External Tools

# Use sig run to inject credentials into any command

# cURL
sig run jira-example -- curl https://jira.example.com/rest/api/2/myself

# Python script
sig run github-enterprise -- python sync_repos.py

# Node.js script with multiple providers
sig run jira-example,slack-enterprise -- node agent.js

Common Validation URLs

Service validateUrl
Reddit https://www.reddit.com/prefs/friends
X (Twitter) https://x.com/i/api/2/notifications/all.json?count=1
LinkedIn https://www.linkedin.com/voyager/api/me
YouTube https://www.youtube.com/account
V2EX https://www.v2ex.com/notifications
Zhihu https://www.zhihu.com/api/v4/me

Troubleshooting

Provider auto-provision fails

Symptom: sig login completes but provider not created.

Solution: Add validateUrl for public sites:

reddit:
  validateUrl: https://www.reddit.com/prefs/friends

Credentials extracted but validation fails

Symptom: Browser login succeeds but sig reports "not authenticated".

Solution 1: Check if API returns 200 with error in body. Add validateRule:

validateRule: 'res.body.status_code === 0'

Solution 2: Ensure validateUrl is a protected endpoint (returns 401/403 when logged out).

OAuth2 token not refreshing

Symptom: Token expires and requests fail.

Solution: Verify tokenUrl, clientId, clientSecret in config. Check that the OAuth2 server supports grant_type=client_credentials.

sig logout oauth-provider  # clear old token
sig get oauth-provider     # force re-authentication

localStorage extraction returns null

Symptom: from: localStorage extracts nothing.

Solution: Check jsonPath syntax. Open browser DevTools → Application → Local Storage and verify the key structure:

extract:
  - from: localStorage
    as: token
    match: appConfig           # localStorage key
    jsonPath: user.auth.token  # nested path

Proxy mode not injecting credentials

Symptom: HTTP_PROXY set but requests are unauthenticated.

Solution: Ensure domains match. The proxy only injects credentials for domains listed in provider config:

provider-name:
  domains:
    - api.example.com
    - auth.example.com  # add all relevant domains

Certificate errors in proxy mode

Symptom: SSL certificate verification fails.

Solution: sig proxy uses MITM. Either:

  1. Trust the sig CA certificate (see sig proxy --help)
  2. Disable SSL verification in your HTTP client (development only)

Credentials file corruption

Symptom: Error reading credentials or decryption fails.

Solution: Re-authenticate:

rm ~/.sig/credentials/provider-name.json
sig login https://provider.example.com

Security Notes

  • Credentials encrypted with AES-256-GCM
  • Stored in ~/.sig/credentials/ (mode 600)
  • Audit log in ~/.sig/logs/
  • Never pass credentials through environment variables or shell history
  • sig get --no-redaction shows raw tokens (use carefully)

AI Agent Integration

Agents should:

  1. Run sig status <provider> before making requests
  2. Use sig request for single authenticated calls
  3. Use sig proxy for long-running sessions or multiple requests
  4. Check exit codes: 0 = success, non-zero = failure
  5. Parse JSON output from sig request directly

Example agent pattern:

function ensureAuthenticated(provider: string): boolean {
  try {
    execSync(`sig status ${provider}`, { encoding: 'utf8' });
    return true;
  } catch {
    console.error(`Not authenticated. Run: sig login https://${provider}.com`);
    return false;
  }
}

if (ensureAuthenticated('jira-example')) {
  const data = execSync('sig request https://jira.example.com/rest/api/2/myself');
  // process data
}