Provides expert OAuth 2.0 implementation, troubleshooting, and token management for Twenty CRM with Google/Microsoft OAuth and email/calendar sync integration.
数据来源:ClawHub。 在 ClawSkills 查看
选择你使用的 Agent
方法一:命令行安装(推荐)
推荐(无需提前安装 clawhub)
npx clawhub@latest --dir ~/.claude/skills install twenty-oauth-mastery或使用 clawhub CLI(需提前安装)
clawhub --dir ~/.claude/skills install twenty-oauth-mastery⚠️ 需要 Node.js 18+,没有 Node?请使用下方方法二直接下载 ZIP。 安装 Node.js →
方法二:手动下载安装(无需 Node)
下载 ZIP,解压后将文件夹放到以下路径,重启 Agent 即可:
安装路径
~/.claude/skills/twenty-oauth-mastery/💡解压后将文件夹放到上方路径,重启 Agent 即可生效
Author: Generated from extensive OAuth debugging sessions in OpenCode Last Updated: 2026-02-08 Version: 1.0
---
name: twenty-oauth-mastery
description: Expert-level OAuth authentication knowledge for Twenty CRM including implementation, troubleshooting, and best practices
expertise_level: Expert/Mastery
category: Authentication
applicable_to:
- Twenty CRM authentication
- Google/Microsoft OAuth
- Token refresh management
- Domain restrictions
- Email/Calendar sync integration
prerequisites:
- Knowledge of TypeScript/JavaScript
- Understanding of OAuth 2.0 protocol
- Familiarity with NestJS framework
keywords:
- oauth
- authentication
- twenty-crm
- google-oauth
- microsoft-oauth
- token-refresh
- sync-integration
- domain-restriction
---
You should use this skill when working on:
✅ Implementing new OAuth providers ✅ Fixing OAuth login issues ✅ Setting up automatic Gmail/Calendar sync after OAuth ✅ Debugging token refresh failures ✅ Configuring domain restrictions ✅ Troubleshooting redirect loops
| Issue | File to Check | Quick Fix | |-------|---------------|-----------| | Redirect loop | auth.service.ts | Rebuild: npx nx build twenty-server | | .co domain blocked | google-auth.controller.ts | Add to allowlist: ['company.com', 'company.co'] | | Sync not starting | google.auth.strategy.ts | Return tokens in validate() | | Cookie not readable | Controller cookie settings | Set httpOnly: false | | Infinite loop | SignInUpGlobalScopeFormEffect.tsx | Track processed token signatures |
---
Key Files: twenty/packages/twenty-server/src/engine/core-modules/auth/
Structure:
auth/
├── strategies/ # Passport strategies (Google, Microsoft)
├── controllers/ # OAuth endpoints and callbacks
├── services/ # Auth logic, sync setup, token management
├── guards/ # Auth guards and validation
└── utils/ # Scope configuration, utilities
---
@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor(twentyConfigService: TwentyConfigService) {
super({
clientID: twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'),
clientSecret: twentyConfigService.get('AUTH_GOOGLE_CLIENT_SECRET'),
callbackURL: twentyConfigService.get('AUTH_GOOGLE_CALLBACK_URL'),
scope: getGoogleApisOauthScopes(),
passReqToCallback: true, // 🔴 CRITICAL: Required for request state
});
}
async validate(
request: GoogleRequest,
_accessToken: string,
_refreshToken: string,
profile: GoogleProfile,
) {
// 🔴 CRITICAL: Include tokens in return object
// Without this, automatic sync setup fails
return {
...profile,
accessToken: _accessToken,
refreshToken: _refreshToken,
hostedDomain: request.query.hosted_domain || profile.emails?.[0]?.value?.split('@')[1],
};
}
}
Why This Matters:
passReqToCallback: true: Enables access to request state---
Symptoms: OAuth completes but user stuck on welcome page
Root Causes:
Fix: ```bash npx nx build twenty-server docker restart fratres-twenty ```
Check: ```bash docker exec fratres-twenty cat /app/dist/engine/core-modules/auth/services/auth.service.js | grep isSingleDomainMode ```
Fix: ```typescript // auth.service.ts - Remove explicit domain attribute res.cookie('tokenPair', JSON.stringify(authTokens), { path: '/', secure: true, sameSite: 'lax', httpOnly: false, // 🔴 Must be false for JavaScript access }); ```
---
Symptoms: @company.co rejected, only @company.com allowed
Three Places to Fix:
google.auth.strategy.ts):```typescript // ❌ WRONG - Hardcoded hd: 'company.com'
// ✅ CORRECT - Remove hd parameter // (no hd parameter) ```
google-auth.controller.ts):```typescript // ❌ WRONG - Hardcoded check if (hostedDomain !== 'company.com') { throw ... }
// ✅ CORRECT - Allowlist const allowedOAuthDomains = ['company.com', 'company.co']; if (!hostedDomain || !allowedOAuthDomains.includes(hostedDomain)) { throw new UnauthorizedException( Only ${allowedOAuthDomains.map(d => @${d}).join(', ')} allowed ); } ```
workspaceMetadata table):```sql INSERT INTO "workspaceMetadata" ("id", "workspaceId", "key", "value", "createdAt", "updatedAt") VALUES (gen_random_uuid(), 'workspace-id', 'approvedAccessDomains', '["company.com", "company.co"]', NOW(), NOW()); ```
---
Symptoms: User logs in but connected account/sync channels not created
Root Cause: Tokens lost in validate() method
Fix:
// google.auth.strategy.ts validate()
async validate(request, accessToken, refreshToken, profile) {
// ❌ WRONG - Tokens lost
return { ...profile };
// ✅ CORRECT - Tokens preserved
return {
...profile,
accessToken,
refreshToken,
};
}
Additional Checks:
auth.service.ts calls oauthSyncService.setupSyncForOAuthUser() after logingmail.readonly and calendar.eventsCALENDAR_PROVIDER_GOOGLE_ENABLED=true---
Symptoms: SignInUpGlobalScopeFormEffect runs repeatedly, infinite API calls
Root Cause: Same token processed multiple times
Fix:
// SignInUpGlobalScopeFormEffect.tsx
useEffect(() => {
const tokenPairFromUrl = getAuthPairFromUrl();
if (tokenPairFromUrl) {
const tokenSignature = JSON.stringify(tokenPairFromUrl);
// 🔴 CRITICAL: Skip if already processed
if (processedTokenSignatures.current.has(tokenSignature)) {
return;
}
// Track this signature
processedTokenSignatures.current.add(tokenSignature);
// Now process the token
setAuthTokens(tokenPairFromUrl);
}
}, []);
---
When to Use: Users should have Gmail/Calendar auto-connected after OAuth login
Implementation:
```typescript async setupSyncForOAuthUser(input: { workspaceId: string; userId: string; workspaceMemberId: string; email: string; accessToken: string; refreshToken: string; scopes: string[]; }) { // 1. Create/update connected account with tokens // 2. Create message channel // 3. Create calendar channel (if enabled) // 4. Queue initial sync jobs } ```
...
安装 Twenty CRM OAuth Mastery 后,可以对 AI 说这些话来触发它
Send a Slack message to the #engineering channel about the deployment
Formats and sends the message with relevant context, tagging the right people
Summarize all unread messages in my inbox from today
Reads messages across connected channels and returns a prioritized summary
Draft a reply to this customer complaint and send it for review
Writes an empathetic, professional response and routes it to the approval queue
将技能文件夹放到 ~/.claude/skills/twenty-oauth-mastery/ 目录(个人级,所有项目可用),或 .claude/skills/twenty-oauth-mastery/(项目级)。重启 AI 客户端后,用 /twenty-oauth-mastery 主动调用,或让 AI 根据上下文自动发现并使用。
Twenty CRM OAuth Mastery 支持 Claude、Cursor、OpenClaw,可与这些 AI 平台无缝集成,扩展其能力。
Twenty CRM OAuth Mastery 可免费安装使用。请查阅仓库了解许可证信息。
Provides expert OAuth 2.0 implementation, troubleshooting, and token management for Twenty CRM with Google/Microsoft OAuth and email/calendar sync integration.
Twenty CRM OAuth Mastery 属于「Communication」分类,该分类的技能帮助 AI 智能体在此领域执行专业任务。