authkit
npx skills add https://github.com/picahq/skills --skill authkit
Agent 安装分布
Skill 文档
Pica AuthKit Integration Guide
Complete guide for integrating Pica AuthKit to enable users to connect third-party tools (Gmail, Slack, HubSpot, etc.) in your application.
What is 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
Prerequisites
- Pica API key from https://app.picaos.com/settings/api-keys
- Backend capable of making authenticated API calls
- Frontend capable of running 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
Step 1: Install Packages
Frontend:
npm install @picahq/authkit
Backend:
npm install @picahq/authkit-token
Step 2: Backend Token Endpoint
Create an endpoint that generates AuthKit session tokens.
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
Token Generation
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 |
|---|---|
user |
Personal connections per user |
team |
Shared connections within a team |
organization |
Company-wide shared connections |
project |
Project-scoped isolated connections |
Required CORS Headers
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.
Example Response
The token endpoint should return the token object directly:
{
"token": "akt_xxxxx...",
"expiresAt": "2024-01-01T00:00:00Z"
}
Step 3: Frontend Integration
Using the React Hook
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
// 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
Pass the integration’s display name to skip the integration list:
// 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.
Step 4: Store Connections
When onSuccess fires, save the connection to your database.
Connection Object Structure
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
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
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
Fetch available integrations from Pica API.
API Request
GET https://api.picaos.com/v1/available-connectors?authkit=true&limit=300
Headers:
x-pica-secret: YOUR_PICA_SECRET_KEY
Response Structure
{
"rows": [
{
"platform": "gmail",
"name": "Gmail",
"category": "Communication",
"image": "https://...",
"description": "..."
}
],
"total": 200,
"pages": 1,
"page": 1
}
Key Fields
| Field | Description |
|---|---|
platform |
Platform identifier (use for API calls) |
name |
Display name (use for selectedConnection) |
category |
Category for grouping |
image |
Logo URL |
Step 6: Using Connections
Once stored, use the connection_key to make API calls via Pica.
Passthrough 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
Example: Send Gmail
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 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
Alternative: Use ngrok
Expose your local server via ngrok and use that URL for the token endpoint.
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 |
API Reference
Token Generation
import { AuthKitToken } from "@picahq/authkit-token";
const token = new AuthKitToken(secretKey);
await token.create({ identity, identityType });
Frontend Hook
import { useAuthKit } from "@picahq/authkit";
const { open, isLoading } = useAuthKit({ token, onSuccess, onError, onClose, selectedConnection });
Pica API Endpoints
- Available Connectors:
GET /v1/available-connectors?authkit=true - List Connections:
GET /v1/vault/connections?identity={id}&identityType=user - Passthrough:
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