sigcli-auth-proxy
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesesigcli Auth Proxy Skill
sigcli 认证代理 Skill
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
sigcli 是一款认证CLI和代理工具,可为AI Agent处理基于浏览器的SSO、OAuth2流程以及凭证注入。它提取凭证(Cookie、localStorage、OAuth令牌),使用AES-256-GCM在本地加密,并将其注入HTTP请求——这样Agent就可以访问需认证的API,且全程不会接触到机密信息。
核心功能:
- 支持任意网站/SSO提供商的浏览器SSO认证
- 带自动令牌刷新的OAuth2客户端凭证流程
- 加密凭证存储()
~/.sig/credentials/ - 面向Agent的透明HTTP代理()
sig proxy - 直接发送认证请求()
sig request - 注入凭证执行命令()
sig run - 单命令支持多提供商
Installation
安装
bash
npm install -g @sigcli/cliInitialize configuration:
bash
sig init # creates ~/.sig/config.yamlbash
npm install -g @sigcli/cli初始化配置:
bash
sig init # 创建 ~/.sig/config.yamlCore Commands
核心命令
Authentication
认证
bash
undefinedbash
undefinedBrowser-based SSO (auto-provision)
基于浏览器的SSO(自动配置)
sig login https://jira.example.com
sig login https://jira.example.com
OAuth2 Client Credentials
OAuth2客户端凭证
sig login https://api.example.com
--strategy oauth2
--token-url https://api.example.com/oauth/token
--client-id $CLIENT_ID
--client-secret $CLIENT_SECRET
--strategy oauth2
--token-url https://api.example.com/oauth/token
--client-id $CLIENT_ID
--client-secret $CLIENT_SECRET
sig login https://api.example.com
--strategy oauth2
--token-url https://api.example.com/oauth/token
--client-id $CLIENT_ID
--client-secret $CLIENT_SECRET
--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
sig status # 所有提供商
sig status jira-example # 指定提供商
View credentials (redacted by default)
查看凭证(默认脱敏)
sig get jira-example # shows redacted credentials
sig get jira-example --no-redaction # shows raw tokens
sig get jira-example # 显示脱敏凭证
sig get jira-example --no-redaction # 显示原始令牌
Logout (clears credentials, keeps config)
登出(清除凭证,保留配置)
sig logout jira-example
undefinedsig logout jira-example
undefinedMaking Authenticated Requests
发送认证请求
bash
undefinedbash
undefinedDirect HTTP request
直接发送HTTP请求
sig request https://jira.example.com/rest/api/2/myself
sig request https://jira.example.com/rest/api/2/myself
POST with JSON body
带JSON体的POST请求
sig request https://jira.example.com/rest/api/2/search
--method POST
--body '{"jql":"assignee=currentUser()"}'
--method POST
--body '{"jql":"assignee=currentUser()"}'
sig request https://jira.example.com/rest/api/2/search
--method POST
--body '{"jql":"assignee=currentUser()"}'
--method POST
--body '{"jql":"assignee=currentUser()"}'
Multiple providers in one request
单请求使用多提供商凭证
sig request https://api.example.com/data
--provider jira-example,github-enterprise
--provider jira-example,github-enterprise
undefinedsig request https://api.example.com/data
--provider jira-example,github-enterprise
--provider jira-example,github-enterprise
undefinedRunning Commands with Auth
带认证信息执行命令
bash
undefinedbash
undefinedExecute command with credentials injected
注入凭证执行命令
sig run jira-example -- curl https://jira.example.com/rest/api/2/myself
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
sig run github-enterprise,jira-example -- node script.js
Environment variables are automatically injected based on apply[] rules
会根据apply[]规则自动注入环境变量
undefinedundefinedHTTP Proxy Mode
HTTP代理模式
bash
undefinedbash
undefinedStart MITM proxy (injects credentials transparently)
启动MITM代理(自动注入凭证)
sig proxy --port 8080
sig proxy --port 8080
In another terminal or agent config:
在另一个终端或Agent配置中:
export HTTP_PROXY=http://localhost:8080
export HTTPS_PROXY=http://localhost:8080
export HTTP_PROXY=http://localhost:8080
export HTTPS_PROXY=http://localhost:8080
Credentials auto-injected by sig proxy
凭证由sig proxy自动注入
undefinedundefinedConfiguration
配置
Configuration lives in . Providers are auto-provisioned for SSO sites, or manually configured for public sites and OAuth2.
~/.sig/config.yaml配置文件位于 。SSO站点会自动配置提供商,公共站点和OAuth2需手动配置。
~/.sig/config.yamlAuto-Provisioned SSO (Zero Config)
自动配置SSO(零配置)
yaml
undefinedyaml
undefined~/.sig/config.yaml (generated by sig login)
~/.sig/config.yaml(由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}'
undefinedjira-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}'
undefinedPublic Sites with Validation
带验证的公共站点
Public sites need and/or to distinguish auth cookies from tracking cookies:
validateUrlvalidateRuleyaml
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}'公共站点需要和/或来区分认证Cookie和跟踪Cookie:
validateUrlvalidateRuleyaml
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)
验证规则(JavaScript表达式)
For APIs that return 200 even when unauthenticated:
yaml
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:
- - HTTP status code
res.status - - parsed JSON or raw string
res.body - - response headers
res.headers
针对未认证时仍返回200的API:
yaml
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上下文:
- - HTTP状态码
res.status - - 解析后的JSON或原始字符串
res.body - - 响应头
res.headers
OAuth2 Client Credentials
OAuth2客户端凭证
yaml
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}'yaml
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
localStorage提取
For apps that store tokens in localStorage:
yaml
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}'针对将令牌存储在localStorage中的应用:
yaml
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):
yaml
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}'针对使用多个域名的站点(例如twitter.com → x.com迁移):
yaml
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)
网络代理(适用于VPN/SOCKS)
If the browser needs to go through a proxy:
yaml
x:
networkProxy: socks5://127.0.0.1:3333
# ... rest of config如果浏览器需要通过代理访问:
yaml
x:
networkProxy: socks5://127.0.0.1:3333
# ... 其余配置Real-World Usage Patterns
实际使用场景
Pattern 1: Agent Accessing Jira
场景1:Agent访问Jira
typescript
// 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()');typescript
// 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);
}
// 使用示例
const issue = getJiraIssue('PROJ-123');
const myIssues = searchJiraIssues('assignee=currentUser()');Pattern 2: OAuth2 API with Auto-Refresh
场景2:带自动刷新的OAuth2 API
typescript
// 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');typescript
// 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) {
// 遇到401时,sig会自动刷新OAuth2令牌
throw error;
}
}
checkStatus(): void {
const status = this.exec(`sig status ${this.provider}`);
console.log(status);
}
}
// 使用示例
const client = new AuthenticatedAPIClient('oauth-mock');
const data = await client.makeRequest('/api/data');Pattern 3: Proxy Mode for HTTP Client
场景3:HTTP客户端代理模式
typescript
// 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());typescript
// proxy-mode-agent.ts
import axios from 'axios';
import { spawn } from 'child_process';
// 启动sig代理
const proxy = spawn('sig', ['proxy', '--port', '8080'], {
stdio: 'inherit'
});
// 配置axios使用代理
const client = axios.create({
proxy: {
host: 'localhost',
port: 8080,
},
});
// 所有请求自动认证
async function fetchData() {
const response = await client.get('https://jira.example.com/rest/api/2/myself');
return response.data;
}
// 清理进程
process.on('exit', () => proxy.kill());Pattern 4: Multi-Provider Request
场景4:多提供商请求
typescript
// 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));
}typescript
// multi-provider-sync.ts
import { execSync } from 'child_process';
function syncDataAcrossSystems(): void {
// 单请求使用多提供商凭证
const result = execSync(
`sig request https://api.example.com/sync \
--provider jira-example,github-enterprise \
--method POST \
--body '{"sync": true}'`,
{ encoding: 'utf8' }
);
console.log('同步结果:', JSON.parse(result));
}Pattern 5: Running External Tools
场景5:运行外部工具
bash
undefinedbash
undefinedUse sig run to inject credentials into any command
使用sig run将凭证注入任意命令
cURL
cURL
sig run jira-example -- curl https://jira.example.com/rest/api/2/myself
sig run jira-example -- curl https://jira.example.com/rest/api/2/myself
Python script
Python脚本
sig run github-enterprise -- python sync_repos.py
sig run github-enterprise -- python sync_repos.py
Node.js script with multiple providers
带多提供商凭证的Node.js脚本
sig run jira-example,slack-enterprise -- node agent.js
undefinedsig run jira-example,slack-enterprise -- node agent.js
undefinedCommon Validation URLs
常用验证URL
| Service | validateUrl |
|---|---|
| |
| X (Twitter) | |
| |
| YouTube | |
| V2EX | |
| Zhihu | |
| 服务 | validateUrl |
|---|---|
| |
| X (Twitter) | |
| |
| YouTube | |
| V2EX | |
| 知乎 | |
Troubleshooting
故障排查
Provider auto-provision fails
提供商自动配置失败
Symptom: completes but provider not created.
sig loginSolution: Add for public sites:
validateUrlyaml
reddit:
validateUrl: https://www.reddit.com/prefs/friends症状: 执行完成但未创建提供商。
sig login解决方案: 为公共站点添加:
validateUrlyaml
reddit:
validateUrl: https://www.reddit.com/prefs/friendsCredentials 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 :
validateRuleyaml
validateRule: 'res.body.status_code === 0'Solution 2: Ensure is a protected endpoint (returns 401/403 when logged out).
validateUrl症状: 浏览器登录成功但sig提示“未认证”。
解决方案1: 检查API是否返回200但响应体包含错误信息。添加:
validateRuleyaml
validateRule: 'res.body.status_code === 0'解决方案2: 确保是受保护的端点(未登录时返回401/403)。
validateUrlOAuth2 token not refreshing
OAuth2令牌未自动刷新
Symptom: Token expires and requests fail.
Solution: Verify , , in config. Check that the OAuth2 server supports .
tokenUrlclientIdclientSecretgrant_type=client_credentialsbash
sig logout oauth-provider # clear old token
sig get oauth-provider # force re-authentication症状: 令牌过期后请求失败。
解决方案: 验证配置中的、、。确认OAuth2服务器支持。
tokenUrlclientIdclientSecretgrant_type=client_credentialsbash
sig logout oauth-provider # 清除旧令牌
sig get oauth-provider # 强制重新认证localStorage extraction returns null
localStorage提取返回null
Symptom: extracts nothing.
from: localStorageSolution: Check syntax. Open browser DevTools → Application → Local Storage and verify the key structure:
jsonPathyaml
extract:
- from: localStorage
as: token
match: appConfig # localStorage key
jsonPath: user.auth.token # nested path症状: 未提取到任何内容。
from: localStorage解决方案: 检查语法。打开浏览器开发者工具→Application→Local Storage,验证键结构:
jsonPathyaml
extract:
- from: localStorage
as: token
match: appConfig # localStorage键名
jsonPath: user.auth.token # 嵌套路径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:
yaml
provider-name:
domains:
- api.example.com
- auth.example.com # add all relevant domains症状: 已设置HTTP_PROXY但请求未认证。
解决方案: 确保域名匹配。代理仅会为提供商配置中列出的域名注入凭证:
yaml
provider-name:
domains:
- api.example.com
- auth.example.com # 添加所有相关域名Certificate errors in proxy mode
代理模式下证书错误
Symptom: SSL certificate verification fails.
Solution: sig proxy uses MITM. Either:
- Trust the sig CA certificate (see )
sig proxy --help - Disable SSL verification in your HTTP client (development only)
症状: SSL证书验证失败。
解决方案: sig proxy使用MITM技术。可选择:
- 信任sig CA证书(查看)
sig proxy --help - 在HTTP客户端中禁用SSL验证(仅开发环境)
Credentials file corruption
凭证文件损坏
Symptom: or decryption fails.
Error reading credentialsSolution: Re-authenticate:
bash
rm ~/.sig/credentials/provider-name.json
sig login https://provider.example.com症状: 出现或解密失败。
Error reading credentials解决方案: 重新认证:
bash
rm ~/.sig/credentials/provider-name.json
sig login https://provider.example.comSecurity Notes
安全说明
- Credentials encrypted with AES-256-GCM
- Stored in (mode 600)
~/.sig/credentials/ - Audit log in
~/.sig/logs/ - Never pass credentials through environment variables or shell history
- shows raw tokens (use carefully)
sig get --no-redaction
- 凭证使用AES-256-GCM加密
- 存储在(权限600)
~/.sig/credentials/ - 审计日志位于
~/.sig/logs/ - 切勿通过环境变量或Shell历史传递凭证
- 会显示原始令牌(谨慎使用)
sig get --no-redaction
AI Agent Integration
AI Agent集成
Agents should:
- Run before making requests
sig status <provider> - Use for single authenticated calls
sig request - Use for long-running sessions or multiple requests
sig proxy - Check exit codes: 0 = success, non-zero = failure
- Parse JSON output from directly
sig request
Example agent pattern:
typescript
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
}Agent应遵循以下步骤:
- 发送请求前运行检查认证状态
sig status <provider> - 使用发送单次认证请求
sig request - 对于长期会话或多次请求,使用
sig proxy - 检查退出码:0=成功,非0=失败
- 直接解析返回的JSON输出
sig request
示例Agent模式:
typescript
function ensureAuthenticated(provider: string): boolean {
try {
execSync(`sig status ${provider}`, { encoding: 'utf8' });
return true;
} catch {
console.error(`未认证。请执行:sig login https://${provider}.com`);
return false;
}
}
if (ensureAuthenticated('jira-example')) {
const data = execSync('sig request https://jira.example.com/rest/api/2/myself');
// 处理数据
}