authkit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Pica 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

前置条件



Architecture Overview

架构概述

┌─────────────┐     ┌─────────────────┐     ┌─────────────┐
│   Frontend  │────▶│  Your Backend   │────▶│  Pica API   │
│  (AuthKit)  │     │ (Token Endpoint)│     │             │
└─────────────┘     └─────────────────┘     └─────────────┘
       │                                           │
       └───────────── OAuth Flow ──────────────────┘
  1. Frontend calls your token endpoint
  2. Your backend generates a Pica session token
  3. AuthKit uses token to manage OAuth flow
  4. On success, you receive connection details to store

┌─────────────┐     ┌─────────────────┐     ┌─────────────┐
│   Frontend  │────▶│  Your Backend   │────▶│  Pica API   │
│  (AuthKit)  │     │ (Token Endpoint)│     │             │
└─────────────┘     └─────────────────┘     └─────────────┘
       │                                           │
       └───────────── OAuth Flow ──────────────────┘
  1. 前端调用你的令牌端点
  2. 你的后端生成Pica会话令牌
  3. AuthKit使用该令牌管理OAuth流程
  4. 成功后,你将收到连接详情并进行存储

Step 1: Install Packages

步骤1:安装包

Frontend:
bash
npm install @picahq/authkit
Backend:
bash
npm install @picahq/authkit-token

前端:
bash
npm install @picahq/authkit
后端:
bash
npm install @picahq/authkit-token

Step 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

身份类型

TypeUse Case
user
Personal connections per user
team
Shared connections within a team
organization
Company-wide shared connections
project
Project-scoped isolated connections
类型使用场景
user
每个用户的个人连接
team
团队内共享连接
organization
全公司共享连接
project
项目范围的独立连接

Required CORS Headers

必需的CORS头

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, x-user-id
Important: Include any custom headers you use (like
x-user-id
) in the allowed headers.
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, x-user-id
重要提示: 请将你使用的所有自定义头(如
x-user-id
)加入允许的头列表中。

Example 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: undefined
Note: 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
onSuccess
fires, save the connection to your database.
onSuccess
触发时,将连接信息保存到你的数据库中。

Connection 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_KEY
GET https://api.picaos.com/v1/available-connectors?authkit=true&limit=300
Headers:
  x-pica-secret: YOUR_PICA_SECRET_KEY

Response 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

关键字段

FieldDescription
platform
Platform identifier (use for API calls)
name
Display name (use for
selectedConnection
)
category
Category for grouping
image
Logo URL

字段描述
platform
平台标识符(用于API调用)
name
显示名称(用于
selectedConnection
category
分组类别
image
Logo URL

Step 6: Using Connections

步骤6:使用连接

Once stored, use the
connection_key
to make API calls via Pica.
存储连接后,使用
connection_key
通过Pica发起API调用。

Passthrough 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/json
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/json

Example: 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:
  1. Go to
    chrome://flags
  2. Search for "Block insecure private network requests"
  3. Set to Disabled
  4. Restart Chrome
Chrome可能会阻止AuthKit iframe调用localhost。解决方法:
  1. 打开
    chrome://flags
  2. 搜索"Block insecure private network requests"
  3. 设置为Disabled
  4. 重启Chrome

Alternative: Use ngrok

替代方案:使用ngrok

Expose your local server via ngrok and use that URL for the token endpoint.

通过ngrok暴露你的本地服务器,并使用该URL作为令牌端点。

Troubleshooting

故障排除

IssueCauseSolution
405 Method Not AllowedMissing OPTIONS handlerAdd OPTIONS endpoint with CORS headers
CORS errorMissing or wrong CORS headersInclude all custom headers in Access-Control-Allow-Headers
Token fetch failsInvalid PICA_SECRET_KEYVerify key at app.picaos.com/settings/api-keys
Opens list instead of integrationWrong selectedConnection valueUse display name ("Gmail") not platform ID ("gmail")
Connection not savingonSuccess not storing dataSave connection in onSuccess callback
Foreign key erroruser_id references non-existent userRemove 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

文档