Auth0 커넥터
커넥터 상태: 예정 아직 구축되지 않았습니다. Tajo는 현재 이 커넥터를 실행하지 않습니다.
예시 그림 · 샘플 데이터
동기화 예시
원본
Auth0
커넥터 상태: 예정
대상
다른 도구
커넥터 상태: 사용자 지정 도구
필드 매핑
| 원본 필드 | 대상 필드 | 예시 값 |
|---|---|---|
record.id | source_id | record_1042 |
record.updated_at | updated_at | 2026-10-18T08:00:00Z |
record.value | value | sample_value |
- 초안
- 레코드 한 건 검토
- 이 버전 승인
상태는 개별 커넥터에 대한 것으로, 이 동기화가 준비됐다는 보장은 아닙니다. 표시된 필드는 예시입니다. 동기화 실행 전에 실제 스키마와 권한을 확인하세요.
Tajo를 통해 Auth0를 Brevo에 연결하여 인증된 사용자 프로필을 마케팅 연락처로 동기화하고, 인증 이벤트 기반의 자동화를 트리거하며, 신원 및 액세스 관리 인사이트로 고객 데이터를 풍부하게 만드세요.
개요
| 속성 | 값 |
|---|---|
| 플랫폼 | Auth0 (by Okta) |
| 카테고리 | Identity & Access (Custom) |
| 설정 난이도 | 보통 |
| 공식 통합 | 아니오 |
| 동기화되는 데이터 | 사용자, 이벤트, 역할, 신원 |
| 인증 방식 | Machine-to-Machine OAuth 2.0 |
주요 기능
- 사용자 프로필 동기화 - Auth0 사용자 프로필을 Brevo 연락처에 동기화합니다
- 인증 이벤트 - 로그인, 가입, 비밀번호 재설정 시 자동화를 트리거합니다
- 역할 기반 세분화 - Auth0 역할 및 권한을 기반으로 연락처를 세분화합니다
- 소셜 신원 데이터 - 소셜 로그인 프로필 정보로 연락처를 풍부하게 만듭니다
- 로그인 활동 추적 - 마지막 로그인, 로그인 횟수, 디바이스 데이터를 추적합니다
- 멀티 테넌트 지원 - 여러 Auth0 테넌트의 사용자를 동기화합니다
사전 준비 사항
시작하기 전에 다음 사항이 준비되어 있어야 합니다.
- API 액세스가 있는 Auth0 계정
- Auth0에 등록된 Machine-to-Machine 애플리케이션
- M2M 애플리케이션에 부여된 Management API 권한
- API 액세스가 활성화된 Brevo 계정
- 커넥터 권한이 있는 Tajo 계정
인증
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 defaultAPI 권한
M2M 애플리케이션에는 필요한 스코프만 부여하세요: read:users, read:user_idp_tokens, read:roles, read:logs. 필요하지 않은 경우 write 권한 부여는 피하세요.
설정
기본 설정
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 엔드포인트
| 엔드포인트 | Method | 설명 |
|---|---|---|
https://{domain}/api/v2/users | GET | 사용자 목록 또는 검색 |
https://{domain}/api/v2/users/{id} | GET | 사용자 조회 |
https://{domain}/api/v2/users/{id} | PATCH | 사용자 메타데이터 업데이트 |
https://{domain}/api/v2/users/{id}/roles | GET | 사용자 역할 조회 |
https://{domain}/api/v2/roles | GET | 모든 역할 목록 |
https://{domain}/api/v2/logs | GET | 로그 이벤트 조회 |
https://{domain}/api/v2/stats/active-users | GET | 활성 사용자 수 조회 |
https://{domain}/api/v2/stats/daily | GET | 일일 통계 조회 |
https://{domain}/oauth/token | POST | 액세스 토큰 조회 |
코드 예제
커넥터 초기화
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') }});요청 제한
| 엔드포인트 카테고리 | 제한 | 비고 |
|---|---|---|
| Management API | 초당 50회 (Free) | 테넌트당 |
| Management API | 초당 100회 (Paid) | 테넌트당 |
| Authentication API | 다양 | 플랜에 따라 다름 |
| Log Streams | 실시간 | 전송에 요청 제한 없음 |
| 페이지네이션 | 페이지당 최대 50개 항목 | page와 per_page 파라미터 사용 |
페이지네이션 필수
Auth0 Management API는 페이지당 최대 50개의 결과를 반환합니다. 항상 page와 per_page 파라미터를 사용해 페이지네이션을 구현하세요. 전체 개수를 얻으려면 include_totals=true를 포함하세요.
문제 해결
| 문제 | 원인 | 해결 방법 |
|---|---|---|
| 401 Unauthorized | 토큰 만료 | 새 M2M 토큰 요청 (24시간 만료) |
| 403 Forbidden | 스코프 누락 | M2M 앱에 필요한 권한을 부여하세요 |
| 빈 사용자 목록 | 검색 쿼리 오류 | v3 엔진용 Lucene 쿼리 구문을 사용하세요 |
| 메타데이터 누락 | 메타데이터가 설정되지 않음 | user_metadata와 app_metadata를 확인하세요 |
| Rate limit 429 | 요청이 너무 많음 | retry 헤더를 사용해 백오프를 구현하세요 |
디버그 모드
connectors: auth0: debug: true log_level: verbose log_sync: true모범 사례
- Log Streams 사용 - Logs API를 폴링하는 대신 실시간 이벤트 스트리밍을 사용하세요
- 페이지네이션 구현 - 대규모 테넌트의 경우 항상 사용자 목록 쿼리를 페이지네이션하세요
- M2M 토큰 캐싱 - 만료 직전까지 토큰을 재사용하세요 (기본 수명 24시간)
- 검색 엔진 v3 사용 - 효율적인 사용자 검색을 위해 Lucene 쿼리 구문을 사용하세요
- 검증된 사용자만 동기화 - 미검증 연락처를 피하기 위해
email_verified:true로 필터링하세요 - 사용자 메타데이터 활용 - 동기화를 위해 Auth0 user_metadata에 커스텀 속성을 저장하세요
보안
- Machine-to-Machine OAuth - 서버 간 인증을 위한 client credentials grant
- 스코프 기반 권한 - 최소한의 필요한 Management API 스코프를 부여하세요
- 토큰 순환 - M2M 토큰은 기본적으로 24시간 후 만료됩니다
- Log Stream 인증 - 웹훅 엔드포인트에 대해 bearer 토큰 검증을 사용하세요
- 테넌트 격리 - Auth0 테넌트별로 구성을 분리하세요
- 암호화된 전송 - 모든 API 통신에 TLS 1.2+ 사용