Auth0 Connector
เชื่อมต่อ Auth0 กับ Brevo ผ่าน Tajo เพื่อซิงค์โปรไฟล์ผู้ใช้ที่ยืนยันตัวตนแล้วเป็นผู้ติดต่อทางการตลาด ทริกเกอร์ระบบอัตโนมัติตามเหตุการณ์การยืนยันตัวตน และเพิ่มความสมบูรณ์ให้ข้อมูลลูกค้าของคุณด้วยข้อมูลเชิงลึกจากการจัดการตัวตนและการเข้าถึง
ภาพรวม
| คุณสมบัติ | ค่า |
|---|---|
| แพลตฟอร์ม | Auth0 (by Okta) |
| หมวดหมู่ | Identity & Access (แบบกำหนดเอง) |
| ความซับซ้อนในการตั้งค่า | ปานกลาง |
| การผสานรวมอย่างเป็นทางการ | ไม่ |
| ข้อมูลที่ซิงค์ | ผู้ใช้ เหตุการณ์ บทบาท ตัวตน |
| วิธีการยืนยันตัวตน | Machine-to-Machine OAuth 2.0 |
ฟีเจอร์
- การซิงค์โปรไฟล์ผู้ใช้ - ซิงค์โปรไฟล์ผู้ใช้ Auth0 กับผู้ติดต่อ Brevo
- เหตุการณ์การยืนยันตัวตน - ทริกเกอร์ระบบอัตโนมัติเมื่อเข้าสู่ระบบ สมัครสมาชิก และรีเซ็ตรหัสผ่าน
- การแบ่งกลุ่มตามบทบาท - แบ่งกลุ่มผู้ติดต่อตามบทบาทและสิทธิ์ Auth0
- ข้อมูลตัวตนจากโซเชียล - เพิ่มความสมบูรณ์ให้ผู้ติดต่อด้วยข้อมูลโปรไฟล์การเข้าสู่ระบบโซเชียล
- การติดตามกิจกรรมการเข้าสู่ระบบ - ติดตามการเข้าสู่ระบบล่าสุด จำนวนการเข้าสู่ระบบ และข้อมูลอุปกรณ์
- รองรับ multi-tenant - ซิงค์ผู้ใช้ข้าม Auth0 tenants หลายรายการ
ข้อกำหนดเบื้องต้น
ก่อนเริ่มต้น ตรวจสอบให้แน่ใจว่าคุณมี:
- บัญชี Auth0 ที่มีสิทธิ์เข้าถึง API
- แอปพลิเคชัน Machine-to-Machine ที่ลงทะเบียนใน Auth0
- สิทธิ์ Management API ที่ให้กับแอปพลิเคชัน M2M
- บัญชี Brevo ที่มีสิทธิ์เข้าถึง API
- บัญชี Tajo ที่มีสิทธิ์ connector
การยืนยันตัวตน
Machine-to-Machine OAuth 2.0
# Create an M2M application in Auth0 Dashboardexport AUTH0_DOMAIN=your-tenant.auth0.comexport AUTH0_CLIENT_ID=your_client_idexport AUTH0_CLIENT_SECRET=your_client_secretexport AUTH0_AUDIENCE=https://your-tenant.auth0.com/api/v2/// Get Management API access tokenconst tokenResponse = await fetch( `https://${process.env.AUTH0_DOMAIN}/oauth/token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ client_id: process.env.AUTH0_CLIENT_ID, client_secret: process.env.AUTH0_CLIENT_SECRET, audience: process.env.AUTH0_AUDIENCE, grant_type: 'client_credentials' }) });
const { access_token } = await tokenResponse.json();// Token is valid for 24 hours by defaultสิทธิ์ API
ให้สิทธิ์เฉพาะ scopes ที่จำเป็นกับแอปพลิเคชัน M2M ของคุณ: read:users, read:user_idp_tokens, read:roles และ read:logs หลีกเลี่ยงการให้สิทธิ์การเขียนหากไม่จำเป็น
การกำหนดค่า
การตั้งค่าพื้นฐาน
connectors: auth0: enabled: true domain: "${AUTH0_DOMAIN}" client_id: "${AUTH0_CLIENT_ID}" client_secret: "${AUTH0_CLIENT_SECRET}" audience: "https://${AUTH0_DOMAIN}/api/v2/"
sync: users: true events: true roles: true schedule: "0 */4 * * *" # Every 4 hours
lists: all_users: 20 verified_users: 21 social_login: 22การแมปฟิลด์
field_mapping: email: email given_name: FIRSTNAME family_name: LASTNAME nickname: NICKNAME picture: AVATAR_URL email_verified: EMAIL_VERIFIED logins_count: LOGIN_COUNT last_login: LAST_LOGIN_DATE created_at: SIGNUP_DATE user_metadata.phone: SMS user_metadata.company: COMPANY app_metadata.plan: SUBSCRIPTION_PLAN app_metadata.role: USER_ROLEAPI Endpoints
| Endpoint | เมธอด | คำอธิบาย |
|---|---|---|
https://{domain}/api/v2/users | GET | แสดงรายการหรือค้นหาผู้ใช้ |
https://{domain}/api/v2/users/{id} | GET | ดูผู้ใช้ |
https://{domain}/api/v2/users/{id} | PATCH | อัปเดต user metadata |
https://{domain}/api/v2/users/{id}/roles | GET | ดูบทบาทผู้ใช้ |
https://{domain}/api/v2/roles | GET | แสดงรายการบทบาททั้งหมด |
https://{domain}/api/v2/logs | GET | ดูเหตุการณ์ log |
https://{domain}/api/v2/stats/active-users | GET | ดูจำนวนผู้ใช้ที่ใช้งานอยู่ |
https://{domain}/api/v2/stats/daily | GET | ดูสถิติรายวัน |
https://{domain}/oauth/token | POST | ดู access token |
ตัวอย่างโค้ด
เริ่มต้น Connector
import { TajoClient } from '@tajo/sdk';
const tajo = new TajoClient({ apiKey: process.env.TAJO_API_KEY, brevoApiKey: process.env.BREVO_API_KEY});
await tajo.connectors.connect('auth0', { domain: process.env.AUTH0_DOMAIN, clientId: process.env.AUTH0_CLIENT_ID, clientSecret: process.env.AUTH0_CLIENT_SECRET});ซิงค์ผู้ใช้กับ Brevo
// Paginate through Auth0 userslet page = 0;const perPage = 50;let hasMore = true;
while (hasMore) { const response = await fetch( `https://${domain}/api/v2/users?` + new URLSearchParams({ page: page.toString(), per_page: perPage.toString(), include_totals: 'true', search_engine: 'v3', q: 'email_verified:true' }), { headers: { 'Authorization': `Bearer ${accessToken}` } } );
const { users, total } = await response.json();
for (const user of users) { await tajo.contacts.sync({ email: user.email, attributes: { FIRSTNAME: user.given_name, LASTNAME: user.family_name, LOGIN_COUNT: user.logins_count, LAST_LOGIN_DATE: user.last_login, SIGNUP_DATE: user.created_at, EMAIL_VERIFIED: user.email_verified }, listIds: [20] }); }
page++; hasMore = (page * perPage) < total;}ติดตามเหตุการณ์การยืนยันตัวตนผ่าน Log Streams
// Set up Auth0 Log Stream webhook// Configure in Auth0 Dashboard > Monitoring > Streams
app.post('/webhooks/auth0', async (req, res) => { // Verify authorization header const authHeader = req.headers.authorization; if (authHeader !== `Bearer ${process.env.AUTH0_WEBHOOK_TOKEN}`) { return res.status(401).send('Unauthorized'); }
const logs = req.body;
for (const log of logs) { switch (log.data.type) { case 's': // Successful login await tajo.events.track({ email: log.data.details.email, event: 'user_login', properties: { ip: log.data.ip, user_agent: log.data.user_agent, connection: log.data.connection } }); break; case 'ss': // Successful signup await tajo.contacts.sync({ email: log.data.details.email, attributes: { SIGNUP_DATE: log.data.date }, listIds: [20] }); break; case 'sp': // Successful password change await tajo.events.track({ email: log.data.details.email, event: 'password_changed' }); break; } }
res.status(200).send('OK');});การแบ่งกลุ่มตามบทบาท
// Sync user roles for segmentationconst rolesResponse = await fetch( `https://${domain}/api/v2/users/${userId}/roles`, { headers: { 'Authorization': `Bearer ${accessToken}` } });
const roles = await rolesResponse.json();const roleNames = roles.map(r => r.name).join(', ');
await tajo.contacts.update(userEmail, { attributes: { USER_ROLE: roleNames, IS_ADMIN: roles.some(r => r.name === 'admin') }});ขีดจำกัดอัตรา
| หมวดหมู่ Endpoint | ขีดจำกัด | หมายเหตุ |
|---|---|---|
| Management API | 50 req/วินาที (Free) | ต่อ tenant |
| Management API | 100 req/วินาที (Paid) | ต่อ tenant |
| Authentication API | แตกต่างกัน | ขึ้นอยู่กับแผน |
| Log Streams | แบบเรียลไทม์ | ไม่มีขีดจำกัดอัตราในการส่ง |
| Pagination | สูงสุด 50 รายการ/หน้า | ใช้พารามิเตอร์ page และ per_page |
ต้องใช้ Pagination
Auth0 Management API ส่งคืนสูงสุด 50 ผลลัพธ์ต่อหน้า ต้องใช้ pagination เสมอโดยใช้พารามิเตอร์ page และ per_page รวม include_totals=true เพื่อดูจำนวนทั้งหมด
การแก้ไขปัญหา
| ปัญหา | สาเหตุ | วิธีแก้ |
|---|---|---|
| 401 Unauthorized | Token หมดอายุ | ขอ M2M token ใหม่ (หมดอายุ 24 ชั่วโมง) |
| 403 Forbidden | Scopes หายไป | ให้สิทธิ์ที่จำเป็นกับแอปพลิเคชัน M2M |
| รายการผู้ใช้ว่างเปล่า | ข้อผิดพลาด search query | ใช้ Lucene query syntax สำหรับ v3 engine |
| Metadata หายไป | Metadata ไม่ได้ตั้งค่า | ตรวจสอบ user_metadata และ app_metadata |
| ขีดจำกัดอัตรา 429 | คำขอมากเกินไป | ใช้ backoff พร้อม retry headers |
โหมด Debug
connectors: auth0: debug: true log_level: verbose log_sync: trueแนวทางปฏิบัติที่ดีที่สุด
- ใช้ Log Streams - การสตรีมเหตุการณ์แบบเรียลไทม์แทนการ polling Logs API
- ใช้ pagination - ต้อง paginate คำถาม user list เสมอสำหรับ tenants ขนาดใหญ่
- Cache M2M tokens - ใช้ tokens ซ้ำจนใกล้หมดอายุ (อายุการใช้งานเริ่มต้น 24 ชั่วโมง)
- ใช้ search engine v3 - ใช้ Lucene query syntax สำหรับการค้นหาผู้ใช้ที่มีประสิทธิภาพ
- ซิงค์เฉพาะผู้ใช้ที่ยืนยันแล้ว - กรองด้วย
email_verified:trueเพื่อหลีกเลี่ยงผู้ติดต่อที่ยังไม่ยืนยัน - ใช้ประโยชน์จาก user metadata - จัดเก็บแอตทริบิวต์แบบกำหนดเองใน Auth0 user_metadata สำหรับการซิงค์
ความปลอดภัย
- Machine-to-Machine OAuth - Client credentials grant สำหรับการยืนยันตัวตนระหว่างเซิร์ฟเวอร์
- สิทธิ์แบบกำหนดขอบเขต - ให้ scopes Management API ขั้นต่ำที่จำเป็น
- การหมุนเวียน Token - M2M tokens หมดอายุหลังจาก 24 ชั่วโมงตามค่าเริ่มต้น
- การยืนยันตัวตน Log Stream - ใช้การตรวจสอบ bearer token สำหรับ webhook endpoints
- การแยก Tenant - การกำหนดค่าแยกต่างหากต่อ Auth0 tenant
- การส่งข้อมูลที่เข้ารหัส - TLS 1.2+ สำหรับการสื่อสาร API ทั้งหมด