authkit
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePica AuthKit Integration Guide
Pica AuthKit 集成指南
Complete guide for integrating Pica AuthKit to enable users to connect third-party tools (Gmail, Slack, HubSpot, etc.) in your application.
本指南详细介绍如何在你的应用中集成Pica AuthKit,让用户能够连接第三方工具(Gmail、Slack、HubSpot等)。
What is AuthKit?
什么是AuthKit?
AuthKit is a drop-in OAuth component that:
- Provides pre-built UI for 200+ integration OAuth flows
- Handles token management and refresh automatically
- Works with any frontend framework (React, Vue, vanilla JS)
- Requires a backend token endpoint
AuthKit是一款即插即用的OAuth组件,具备以下特性:
- 为200+集成的OAuth流程提供预构建UI
- 自动处理令牌管理与刷新
- 兼容任意前端框架(React、Vue、原生JS)
- 需要后端令牌端点
Prerequisites
前置条件
- Pica API key from https://app.picaos.com/settings/api-keys
- Backend capable of making authenticated API calls
- Frontend capable of running JavaScript
- 从https://app.picaos.com/settings/api-keys获取Pica API密钥
- 能够发起认证API请求的后端服务
- 能够运行JavaScript的前端
Architecture Overview
架构概述
┌─────────────┐ ┌─────────────────┐ ┌─────────────┐
│ Frontend │────▶│ Your Backend │────▶│ Pica API │
│ (AuthKit) │ │ (Token Endpoint)│ │ │
└─────────────┘ └─────────────────┘ └─────────────┘
│ │
└───────────── OAuth Flow ──────────────────┘- Frontend calls your token endpoint
- Your backend generates a Pica session token
- AuthKit uses token to manage OAuth flow
- On success, you receive connection details to store
┌─────────────┐ ┌─────────────────┐ ┌─────────────┐
│ Frontend │────▶│ Your Backend │────▶│ Pica API │
│ (AuthKit) │ │ (Token Endpoint)│ │ │
└─────────────┘ └─────────────────┘ └─────────────┘
│ │
└───────────── OAuth Flow ──────────────────┘- 前端调用你的令牌端点
- 你的后端生成Pica会话令牌
- AuthKit使用该令牌管理OAuth流程
- 成功后,你将收到连接详情并进行存储
Step 1: Install Packages
步骤1:安装包
Frontend:
bash
npm install @picahq/authkitBackend:
bash
npm install @picahq/authkit-token前端:
bash
npm install @picahq/authkit后端:
bash
npm install @picahq/authkit-tokenStep 2: Backend Token Endpoint
步骤2:后端令牌端点
Create an endpoint that generates AuthKit session tokens.
创建一个生成AuthKit会话令牌的端点。
Requirements
要求
- Must accept POST requests
- Must return token object directly (not wrapped)
- Must include CORS headers (AuthKit iframe calls this endpoint)
- Should identify the user via header or body parameter
- 必须接受POST请求
- 必须直接返回令牌对象(不包装)
- 必须包含CORS头(AuthKit iframe会调用此端点)
- 应通过请求头或请求体参数识别用户
Token Generation
令牌生成
typescript
import { AuthKitToken } from "@picahq/authkit-token";
const authKitToken = new AuthKitToken(PICA_SECRET_KEY);
const token = await authKitToken.create({
identity: userId, // Your user's unique identifier
identityType: "user", // "user" | "team" | "organization" | "project"
});
// Return token directly
return token;typescript
import { AuthKitToken } from "@picahq/authkit-token";
const authKitToken = new AuthKitToken(PICA_SECRET_KEY);
const token = await authKitToken.create({
identity: userId, // Your user's unique identifier
identityType: "user", // "user" | "team" | "organization" | "project"
});
// Return token directly
return token;Identity Types
身份类型
| Type | Use Case |
|---|---|
| Personal connections per user |
| Shared connections within a team |
| Company-wide shared connections |
| Project-scoped isolated connections |
| 类型 | 使用场景 |
|---|---|
| 每个用户的个人连接 |
| 团队内共享连接 |
| 全公司共享连接 |
| 项目范围的独立连接 |
Required CORS Headers
必需的CORS头
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, x-user-idImportant: Include any custom headers you use (like ) in the allowed headers.
x-user-idAccess-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, x-user-id重要提示: 请将你使用的所有自定义头(如)加入允许的头列表中。
x-user-idExample Response
示例响应
The token endpoint should return the token object directly:
json
{
"token": "akt_xxxxx...",
"expiresAt": "2024-01-01T00:00:00Z"
}令牌端点应直接返回令牌对象:
json
{
"token": "akt_xxxxx...",
"expiresAt": "2024-01-01T00:00:00Z"
}Step 3: Frontend Integration
步骤3:前端集成
Using the React Hook
使用React Hook
typescript
import { useAuthKit } from "@picahq/authkit";
function ConnectButton() {
const { open, isLoading } = useAuthKit({
token: {
url: "https://your-domain.com/api/authkit/token", // MUST be full URL
headers: {
"x-user-id": currentUserId,
},
},
selectedConnection: "Gmail", // Optional: skip list, go directly to this integration
onSuccess: (connection) => {
// connection.key - unique identifier for this connection
// connection.platform - e.g., "gmail"
// connection.environment - "live" or "test"
// connection.state - "operational", "degraded", "failed", "unknown"
saveConnectionToDatabase(connection);
},
onError: (error) => {
console.error("Connection failed:", error);
},
onClose: () => {
console.log("Modal closed");
},
});
return (
<button onClick={() => open()} disabled={isLoading}>
Connect Integration
</button>
);
}typescript
import { useAuthKit } from "@picahq/authkit";
function ConnectButton() {
const { open, isLoading } = useAuthKit({
token: {
url: "https://your-domain.com/api/authkit/token", // MUST be full URL
headers: {
"x-user-id": currentUserId,
},
},
selectedConnection: "Gmail", // Optional: skip list, go directly to this integration
onSuccess: (connection) => {
// connection.key - unique identifier for this connection
// connection.platform - e.g., "gmail"
// connection.environment - "live" or "test"
// connection.state - "operational", "degraded", "failed", "unknown"
saveConnectionToDatabase(connection);
},
onError: (error) => {
console.error("Connection failed:", error);
},
onClose: () => {
console.log("Modal closed");
},
});
return (
<button onClick={() => open()} disabled={isLoading}>
Connect Integration
</button>
);
}Critical: Token URL Must Be Full URL
关键注意事项:令牌URL必须是完整URL
typescript
// CORRECT - Full URL
url: "https://your-domain.com/api/authkit/token"
url: `${window.location.origin}/api/authkit/token`
// INCORRECT - Will fail
url: "/api/authkit/token"typescript
// CORRECT - Full URL
url: "https://your-domain.com/api/authkit/token"
url: `${window.location.origin}/api/authkit/token`
// INCORRECT - Will fail
url: "/api/authkit/token"selectedConnection Parameter
selectedConnection参数
Pass the integration's display name to skip the integration list:
typescript
// Opens directly to Gmail auth flow
selectedConnection: "Gmail"
// Opens directly to Slack auth flow
selectedConnection: "Slack"
// Opens to integration list (user picks)
selectedConnection: undefinedNote: Use the display name (e.g., "Gmail", "Google Calendar", "HubSpot"), not the platform ID.
传入集成的显示名称以跳过集成列表:
typescript
// Opens directly to Gmail auth flow
selectedConnection: "Gmail"
// Opens directly to Slack auth flow
selectedConnection: "Slack"
// Opens to integration list (user picks)
selectedConnection: undefined注意: 使用显示名称(如"Gmail"、"Google Calendar"、"HubSpot"),而非平台ID。
Step 4: Store Connections
步骤4:存储连接
When fires, save the connection to your database.
onSuccess当触发时,将连接信息保存到你的数据库中。
onSuccessConnection Object Structure
连接对象结构
typescript
interface Connection {
key: string; // "live::gmail::default::abc123" - use this for API calls
platform: string; // "gmail"
environment: string; // "live" or "test"
state: string; // "operational", "degraded", "failed", "unknown"
}typescript
interface Connection {
key: string; // "live::gmail::default::abc123" - use this for API calls
platform: string; // "gmail"
environment: string; // "live" or "test"
state: string; // "operational", "degraded", "failed", "unknown"
}Recommended Database Schema
推荐数据库表结构
sql
CREATE TABLE user_connections (
id UUID PRIMARY KEY,
user_id TEXT NOT NULL, -- Your user identifier
platform TEXT NOT NULL, -- "gmail", "slack", etc.
connection_key TEXT UNIQUE, -- Pica connection key
environment TEXT DEFAULT 'live', -- "live" or "test"
state TEXT DEFAULT 'operational',
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);sql
CREATE TABLE user_connections (
id UUID PRIMARY KEY,
user_id TEXT NOT NULL, -- Your user identifier
platform TEXT NOT NULL, -- "gmail", "slack", etc.
connection_key TEXT UNIQUE, -- Pica connection key
environment TEXT DEFAULT 'live', -- "live" or "test"
state TEXT DEFAULT 'operational',
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);Save on Success
成功时保存
typescript
onSuccess: async (connection) => {
await fetch("/api/connections", {
method: "POST",
body: JSON.stringify({
user_id: currentUserId,
platform: connection.platform,
connection_key: connection.key,
environment: connection.environment,
state: connection.state,
}),
});
refreshConnectionsList();
}typescript
onSuccess: async (connection) => {
await fetch("/api/connections", {
method: "POST",
body: JSON.stringify({
user_id: currentUserId,
platform: connection.platform,
connection_key: connection.key,
environment: connection.environment,
state: connection.state,
}),
});
refreshConnectionsList();
}Step 5: List Available Integrations
步骤5:获取可用集成列表
Fetch available integrations from Pica API.
从Pica API获取可用集成。
API Request
API请求
GET https://api.picaos.com/v1/available-connectors?authkit=true&limit=300
Headers:
x-pica-secret: YOUR_PICA_SECRET_KEYGET https://api.picaos.com/v1/available-connectors?authkit=true&limit=300
Headers:
x-pica-secret: YOUR_PICA_SECRET_KEYResponse Structure
响应结构
json
{
"rows": [
{
"platform": "gmail",
"name": "Gmail",
"category": "Communication",
"image": "https://...",
"description": "..."
}
],
"total": 200,
"pages": 1,
"page": 1
}json
{
"rows": [
{
"platform": "gmail",
"name": "Gmail",
"category": "Communication",
"image": "https://...",
"description": "..."
}
],
"total": 200,
"pages": 1,
"page": 1
}Key Fields
关键字段
| Field | Description |
|---|---|
| Platform identifier (use for API calls) |
| Display name (use for |
| Category for grouping |
| Logo URL |
| 字段 | 描述 |
|---|---|
| 平台标识符(用于API调用) |
| 显示名称(用于 |
| 分组类别 |
| Logo URL |
Step 6: Using Connections
步骤6:使用连接
Once stored, use the to make API calls via Pica.
connection_key存储连接后,使用通过Pica发起API调用。
connection_keyPassthrough API
透传API
POST https://api.picaos.com/v1/passthrough/{platform}/{action}
Headers:
x-pica-secret: YOUR_PICA_SECRET_KEY
x-pica-connection-key: CONNECTION_KEY_FROM_DATABASE
Content-Type: application/jsonPOST https://api.picaos.com/v1/passthrough/{platform}/{action}
Headers:
x-pica-secret: YOUR_PICA_SECRET_KEY
x-pica-connection-key: CONNECTION_KEY_FROM_DATABASE
Content-Type: application/jsonExample: Send Gmail
示例:发送Gmail邮件
typescript
const response = await fetch(
"https://api.picaos.com/v1/passthrough/gmail/messages/send",
{
method: "POST",
headers: {
"x-pica-secret": PICA_SECRET_KEY,
"x-pica-connection-key": user.gmailConnectionKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
to: "recipient@example.com",
subject: "Hello",
body: "Message content",
}),
}
);typescript
const response = await fetch(
"https://api.picaos.com/v1/passthrough/gmail/messages/send",
{
method: "POST",
headers: {
"x-pica-secret": PICA_SECRET_KEY,
"x-pica-connection-key": user.gmailConnectionKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
to: "recipient@example.com",
subject: "Hello",
body: "Message content",
}),
}
);Local Development
本地开发
Chrome Security Flag
Chrome安全设置
Chrome may block the AuthKit iframe from calling localhost. To fix:
- Go to
chrome://flags - Search for "Block insecure private network requests"
- Set to Disabled
- Restart Chrome
Chrome可能会阻止AuthKit iframe调用localhost。解决方法:
- 打开
chrome://flags - 搜索"Block insecure private network requests"
- 设置为Disabled
- 重启Chrome
Alternative: Use ngrok
替代方案:使用ngrok
Expose your local server via ngrok and use that URL for the token endpoint.
通过ngrok暴露你的本地服务器,并使用该URL作为令牌端点。
Troubleshooting
故障排除
| Issue | Cause | Solution |
|---|---|---|
| 405 Method Not Allowed | Missing OPTIONS handler | Add OPTIONS endpoint with CORS headers |
| CORS error | Missing or wrong CORS headers | Include all custom headers in Access-Control-Allow-Headers |
| Token fetch fails | Invalid PICA_SECRET_KEY | Verify key at app.picaos.com/settings/api-keys |
| Opens list instead of integration | Wrong selectedConnection value | Use display name ("Gmail") not platform ID ("gmail") |
| Connection not saving | onSuccess not storing data | Save connection in onSuccess callback |
| Foreign key error | user_id references non-existent user | Remove foreign key constraint or ensure user exists |
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 405 Method Not Allowed | 缺少OPTIONS请求处理器 | 添加带有CORS头的OPTIONS端点 |
| CORS错误 | CORS头缺失或错误 | 在Access-Control-Allow-Headers中包含所有自定义头 |
| 令牌获取失败 | PICA_SECRET_KEY无效 | 在app.picaos.com/settings/api-keys验证密钥 |
| 打开的是集成列表而非指定集成 | selectedConnection值错误 | 使用显示名称(如"Gmail")而非平台ID("gmail") |
| 连接未保存 | onSuccess未存储数据 | 在onSuccess回调中保存连接信息 |
| 外键错误 | user_id引用不存在的用户 | 移除外键约束或确保用户存在 |
API Reference
API参考
Token Generation
令牌生成
typescript
import { AuthKitToken } from "@picahq/authkit-token";
const token = new AuthKitToken(secretKey);
await token.create({ identity, identityType });typescript
import { AuthKitToken } from "@picahq/authkit-token";
const token = new AuthKitToken(secretKey);
await token.create({ identity, identityType });Frontend Hook
前端Hook
typescript
import { useAuthKit } from "@picahq/authkit";
const { open, isLoading } = useAuthKit({ token, onSuccess, onError, onClose, selectedConnection });typescript
import { useAuthKit } from "@picahq/authkit";
const { open, isLoading } = useAuthKit({ token, onSuccess, onError, onClose, selectedConnection });Pica API Endpoints
Pica API端点
- Available Connectors:
GET /v1/available-connectors?authkit=true - List Connections:
GET /v1/vault/connections?identity={id}&identityType=user - Passthrough:
POST /v1/passthrough/{platform}/{action}
- 可用连接器:
GET /v1/available-connectors?authkit=true - 列出连接:
GET /v1/vault/connections?identity={id}&identityType=user - 透传:
POST /v1/passthrough/{platform}/{action}
Documentation
文档
- Pica Docs: https://docs.picaos.com
- AuthKit Setup: https://docs.picaos.com/authkit/setup
- Available Connectors: https://docs.picaos.com/available-connectors