Skip to main content

Documentation Index

Fetch the complete documentation index at: https://daehan-base.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Base Verify란 무엇인가요?

Base Verify를 사용하면 사용자가 자격 증명을 공유하지 않고 X, Coinbase, Instagram, TikTok의 인증된 계정 소유권을 증명할 수 있습니다. 앱은 시빌 저항성을 위한 결정론적 토큰을 받습니다. 지갑의 트랜잭션 수가 적더라도 Base Verify는 X, Instagram, TikTok의 인증된 소셜 계정이나 Coinbase One 구독을 통해 사용자가 가치 있는 사용자인지 확인합니다. 이를 통해 온체인 활동에 관계없이 고품질 사용자를 식별할 수 있습니다. 사용 사례 예시:
  • 토큰 게이티드 에어드롭 또는 일일 보상
  • 독점 콘텐츠 접근 (예: 크리에이터 코인)
  • 신원 기반 보상 및 로열티 프로그램
앱에서 지갑 연결 또는 메시지 서명이 필요한 경우, 사용자 인증, 타입드 데이터 서명 및 검증, 또는 웹 React 퀵스타트부터 시작하세요.

핵심 개념

프로바이더

Base Verify가 연동하는 신원 플랫폼입니다. 현재 X, Coinbase, Instagram, **TikTok**을 지원합니다.

인증(Verification)

지갑이 특정 프로바이더의 계정을 소유하고 있다는 암호학적 증명입니다.

트레이트(Trait)

검증할 수 있는 프로바이더 계정의 특정 속성입니다. 예시:
  • verified: true — X 계정에 파란 체크 표시가 있음
  • coinbase_one_active: true — 활성 Coinbase One 구독
  • followers: gt:1000 — X 계정의 팔로워가 1,000명 초과
  • followers_count: gte:5000 — Instagram 계정의 팔로워가 5,000명 이상
  • video_count: gte:50 — TikTok 계정에 50개 이상의 동영상

액션(Action)

사용자가 인증으로 무엇을 하는지 식별하는 개발자 정의 문자열입니다. 액션을 통해 동일한 앱 내의 다양한 사용 사례에 대해 다른 토큰을 발급할 수 있습니다. 예시:
  • claim_daily_reward — 일일 보상 수령
  • join_allowlist — 독점 허용 목록 참여
  • unlock_premium_content — 게이티드 콘텐츠 접근
  • participate_in_raffle — 래플 참가

액션 작동 방식

액션은 Sign-In with Ethereum (SIWE) 메시지 리소스에 지정됩니다:
SIWE resources with action
resources: [
  'urn:verify:provider:x',
  'urn:verify:action:claim_daily_reward'
]
액션은 API 응답에 반환됩니다:
Verification response with action
{
  "token": "abc123...",
  "action": "claim_daily_reward",
  "wallet": "0x1234..."
}

액션이 중요한 이유

다른 액션은 다른 토큰을 생성합니다. 이를 통해 동일한 인증 계정에서 여러 독립적인 클레임이 가능합니다:
  • 사용자가 claim_airdrop 액션으로 X 계정 인증 → 토큰: abc123
  • 동일한 X 계정으로 join_allowlist 액션 → 토큰: def456 (다름)
  • 동일한 X 계정으로 claim_airdrop 다시 → 토큰: abc123 (첫 번째와 동일)
사용 사례:
  • 여러 캠페인 — 간섭 없이 별도의 에어드롭 진행
  • 기능 게이팅 — 다양한 프리미엄 기능에 대한 다른 토큰
  • 시간 기반 이벤트 — 이벤트별 새 액션 (예: raffle_jan_2025, raffle_feb_2025)

액션 이름 선택

소문자와 밑줄을 사용한 설명적인 이름을 사용하세요:
좋은 예나쁜 예
claim_genesis_airdropairdrop (너무 일반적)
unlock_pro_featuresaction1 (의미 없음)
enter_weekly_rafflebase_verify_token (예약/혼란)
액션 이름을 한 번 사용하면 변경하지 마세요. 액션을 변경하면 동일한 사용자에 대해 다른 토큰이 생성되어 시빌 저항성이 깨집니다.

토큰 — 시빌 저항성

지갑이 아닌 프로바이더 계정에 연결된 결정론적 식별자입니다. 이것이 핵심 반-시빌 메커니즘입니다.

작동 방식

  1. 지갑 A가 X 계정 인증 → Base Verify가 토큰: abc123 반환 → 이전에 본 적 없으므로 에어드롭 지급.
  2. 동일한 X 계정이 지갑 B로 다시 시도 → Base Verify가 토큰: abc123 반환 → 이미 본 적 있으므로 중복 클레임 차단.
Base Verify 없이는 사용자가 다른 지갑으로 여러 번 클레임할 수 있습니다. Base Verify를 사용하면 하나의 인증 계정 = 하나의 토큰 = 하나의 클레임입니다.

토큰 속성

  • 결정론적 — 동일한 프로바이더 계정은 항상 동일한 토큰을 생성합니다
  • 프로바이더별 고유 — 사용자의 X 토큰은 Instagram 토큰과 다릅니다
  • 앱별 고유 — 앱은 다른 앱과 다른 토큰을 받습니다 (개인 정보 보호)
  • 액션 특정 — 토큰은 SIWE 메시지의 액션에 따라 달라집니다
  • 영구적 — 토큰은 만료되거나 변경되지 않습니다 (사용자가 인증을 삭제하지 않는 한)
  • 트레이트 독립적 — 트레이트가 변경되어도 토큰은 동일합니다 (예: 팔로워 수 증가)

토큰 저장 방법

Verification token storage record
{
  token: "abc123...",
  walletAddress: "0x1234...",
  provider: "x",
  claimedAt: "2024-01-15",
}

이중 클레임 방지

Prevent duplicate claims by token
async function claimAirdrop(verificationToken: string, walletAddress: string) {
  const existingClaim = await db.findClaimByToken(verificationToken);

  if (existingClaim) {
    return { error: "This X account already claimed" };
  }

  await db.createClaim({
    token: verificationToken,
    wallet: walletAddress,
    claimedAt: new Date()
  });

  return { success: true };
}

아키텍처 및 흐름

Base Verify architecture and verification flow
                    ┌─────────────┐
                    │             │  1. User connects wallet
                    │   Your      │
                    │   App  │
                    │  (Frontend) │
                    └──────┬──────┘

                           │ 2. App generates SIWE message (frontend)
                           │    • Includes wallet address
                           │    • Includes provider (x, coinbase, instagram, tiktok)
                           │    • Includes traits (verified:true, followers:gt:1000)
                           │    • Includes action (e.g. claim_airdrop)

                           │ 3. User signs SIWE message with wallet

                           │ 4. Send signature + message to YOUR backend


                    ┌──────────────┐
                    │  App    │  • Validates trait requirements
                    │  Backend     │  • Verifies signature with Base Verify API
                    │  (Your API)  │
                    └──────┬───────┘



   200 OK ←───────┌──────────────────┐───────→ 400
   Verified!      │                  │         User has account
   (DONE)         │  Base Verify API │         but traits not met
                  │  verify.base.dev │         (DONE)
                  └────────┬─────────┘

                           │ 404 Not Found


    5. Redirect to Base Verify App


                    ┌──────────────────────┐
                    │  Base Verify         │  6. User completes OAuth
                    │  App            │     (X, Coinbase, Instagram, TikTok)
                    │  verify.base.dev     │  7. Base Verify stores verification
                    └──────────┬───────────┘

                               │ 8. Redirects back to your app

                        ┌─────────────┐
                        │  Your       │  9. Check again (step 4)
                        │  App   │     → Now returns 200 or 400
                        └─────────────┘

앱의 책임

  • 트레이트 요구 사항이 포함된 SIWE 메시지 생성
  • 사용자 지갑 연결 처리
  • 인증이 없을 때 Base Verify 앱으로 리디렉션
  • 재사용 방지를 위해 반환된 인증 토큰 저장
  • 백엔드에서 시크릿 키 안전하게 보관

Base Verify의 책임

  • SIWE 서명 검증
  • 프로바이더 인증 저장 (X, Coinbase, Instagram, TikTok)
  • 인증이 트레이트 요구 사항을 충족하는지 확인
  • 프로바이더와의 OAuth 흐름 지원
  • 시빌 저항성을 위한 결정론적 토큰 반환

응답 코드

코드의미액션
200 OK지갑이 프로바이더 계정을 인증했으며 모든 트레이트 요구 사항을 충족합니다. 고유 토큰을 반환합니다.접근 허용, 토큰 저장.
404 Not Found지갑이 이 프로바이더를 인증한 적이 없습니다.사용자를 Base Verify 앱으로 리디렉션.
400 Bad Request (verification_traits_not_satisfied)지갑이 프로바이더를 인증했지만 트레이트 요구 사항을 충족하지 않습니다.사용자에게 요구 사항을 충족하지 않음을 알립니다. 리디렉션하지 마세요.

시작하기

사전 요구 사항

  1. API 키관심 양식을 작성하여 접근 권한 받기
  2. 지갑 연동 — 사용자가 연결하고 메시지에 서명할 수 있어야 합니다. 사용자 인증 또는 웹 React 퀵스타트 참고
  3. 백엔드 서버 — Base Verify API를 안전하게 호출하고 시크릿 키를 비공개로 유지하기 위해 필요합니다. 유사한 프론트엔드-백엔드 서명 패턴은 타입드 데이터 서명 및 검증 참고

앱 등록

Base Verify 팀에 다음을 제공하세요:
  1. 앱 도메인
  2. 리디렉션 URI — 인증 후 사용자가 돌아올 위치 (예: https://yourapp.com)
시크릿 키는 절대 프론트엔드 코드에 노출되어서는 안 됩니다. 모든 Base Verify API 호출은 백엔드를 통해 이루어져야 합니다.

구현

1

앱 설정

Base Verify 연동을 위한 설정 파일을 생성합니다:
lib/config.ts
export const config = {
  appUrl: 'https://your-app.com',
  baseVerifySecretKey: process.env.BASE_VERIFY_SECRET_KEY,
  baseVerifyApiUrl: 'https://verify.base.dev/v1',
  baseVerifyMiniAppUrl: 'https://verify.base.dev',
}
시크릿 키를 .env.local에 추가합니다:
.env.local
BASE_VERIFY_SECRET_KEY=your_secret_key_here
2

SIWE 서명 생성 (프론트엔드)

프로바이더, 트레이트 요구 사항, 액션이 포함된 SIWE 메시지를 구성합니다:
lib/signature-generator.ts
import { SiweMessage, generateNonce } from 'siwe'
import { config } from './config'

export async function generateSignature(
  signMessageFunction: (message: string) => Promise<string>,
  address: string
) {
  const resources = [
    'urn:verify:provider:x',
    'urn:verify:provider:x:verified:eq:true',
    'urn:verify:provider:x:followers:gte:100',
    'urn:verify:action:claim_airdrop'
  ]

  const siweMessage = new SiweMessage({
    domain: new URL(config.appUrl).hostname,
    address,
    statement: 'Verify your X account',
    uri: config.appUrl,
    version: '1',
    chainId: 8453,
    nonce: generateNonce(),
    issuedAt: new Date().toISOString(),
    expirationTime: new Date(Date.now() + 6 * 60 * 60 * 1000).toISOString(),
    resources,
  })

  const message = siweMessage.prepareMessage()
  const signature = await signMessageFunction(message)

  return { message, signature, address }
}
3

인증 확인 (프론트엔드 → 백엔드)

프론트엔드가 서명을 생성하고 사용자의 백엔드로 전송하면, 백엔드가 Base Verify API를 호출합니다.프론트엔드:
Frontend verification check
async function checkVerification(address: string) {
  const signature = await generateSignature(
    async (msg) => {
      return new Promise((resolve, reject) => {
        signMessage(
          { message: msg },
          { onSuccess: resolve, onError: reject }
        )
      })
    },
    address
  )

  const response = await fetch('/api/check-verification', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      signature: signature.signature,
      message: signature.message,
      address: address
    })
  })

  const data = await response.json();
  return data;
}
백엔드 (API 엔드포인트):
pages/api/check-verification.ts
import { validateTraits } from '../../lib/trait-validator';

export default async function handler(req, res) {
  const { signature, message, address } = req.body;

  const expectedTraits = {
    'verified': 'true',
    'followers': 'gte:100'
  };

  const validation = validateTraits(message, 'x', expectedTraits);

  if (!validation.valid) {
    return res.status(400).json({
      error: 'Invalid trait requirements in message',
      details: validation.error
    });
  }

  const response = await fetch('https://verify.base.dev/v1/base_verify_token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${process.env.BASE_VERIFY_SECRET_KEY}`,
    },
    body: JSON.stringify({
      signature: signature,
      message: message,
    })
  });

  if (response.ok) {
    const data = await response.json();
    return res.status(200).json({ verified: true, token: data.token });
  } else if (response.status === 404) {
    return res.status(404).json({ verified: false, needsVerification: true });
  } else if (response.status === 400) {
    const data = await response.json();
    if (data.message === 'verification_traits_not_satisfied') {
      return res.status(400).json({ verified: false, traitsNotMet: true });
    }
  }

  return res.status(500).json({ error: 'Verification check failed' });
}
백엔드는 SIWE 메시지의 트레이트 요구 사항이 백엔드가 기대하는 것과 일치하는지 반드시 검증해야 합니다. 이는 사용자가 프론트엔드에서 트레이트 요구 사항을 수정하여 접근 제어를 우회하는 것을 방지합니다. 자세한 내용은 보안 모범 사례를 참고하세요.
4

Base Verify로 리디렉션 (프론트엔드)

404 응답을 받으면 사용자를 Base Verify 앱으로 리디렉션하여 OAuth를 완료하도록 합니다:
Open the Base Verify App
function redirectToVerifyMiniApp(provider: string) {
  const params = new URLSearchParams({
    redirect_uri: config.appUrl,
    providers: provider,
  })

  const miniAppUrl = `${config.baseVerifyMiniAppUrl}?${params.toString()}`

  const deepLink = `cbwallet://miniapp?url=${encodeURIComponent(miniAppUrl)}`
  window.open(deepLink, '_blank')
}
인증 후 사용자는 ?success=true와 함께 redirect_uri로 돌아옵니다. 다시 확인(3단계)을 실행하면 이제 토큰과 함께 200이 반환됩니다. Base 앱을 위해 빌드하는 경우, 더 넓은 앱 구조 및 생명주기 지침은 Apps 개요를 참고하세요.

오류 처리

응답처리 방법
404사용자가 인증하지 않음. Base Verify 앱으로 리디렉션.
400 (verification_traits_not_satisfied)사용자가 계정을 가지고 있지만 요구 사항을 충족하지 않음. 메시지 표시 — 리디렉션하거나 재시도하지 마세요.
200토큰을 저장하고 접근 허용.
404 응답을 재시도하지 마세요 — 사용자가 아직 인증하지 않은 것입니다. verification_traits_not_satisfied가 포함된 400 응답을 재시도하지 마세요 — 사용자의 계정 지표가 변경되지 않는 한 재시도해도 도움이 되지 않습니다 (예: 팔로워 증가).

API 레퍼런스

인증

모든 API 요청은 Authorization 헤더에 시크릿 키가 필요합니다:
Authorization header
Authorization: Bearer YOUR_SECRET_KEY

POST /v1/base_verify_token

지갑이 특정 인증을 가지고 있는지 확인하고 인증 토큰을 검색합니다.

요청

POST /v1/base_verify_token request body
{
  signature: string,   // SIWE signature from wallet
  message: string      // SIWE message (includes provider/traits in resources)
}

요청 예시

POST /v1/base_verify_token cURL example
curl -X POST https://verify.base.dev/v1/base_verify_token \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -d '{
    "signature": "0x1234...",
    "message": "verify.base.dev wants you to sign in..."
  }'

응답

200 OK — 인증됨:
200 OK response
{
  "token": "abc123...",
  "action": "claim_airdrop",
  "wallet": "0x1234..."
}
필드타입설명
tokenstring시빌 저항성을 위한 결정론적 인증 토큰. 동일한 프로바이더 계정 + 동일한 액션 = 동일한 토큰.
actionstringSIWE 메시지에 지정된 커스텀 액션. 다른 액션은 다른 토큰을 생성합니다.
walletstring사용자의 지갑 주소.
404 Not Found — 인증 없음:
404 not found response
{
  "error": "verification_not_found"
}
사용자를 Base Verify 앱으로 리디렉션하여 인증을 완료하도록 합니다. 400 Bad Request — 트레이트 미충족:
400 traits not satisfied response
{
  "code": 9,
  "message": "verification_traits_not_satisfied",
  "details": []
}
사용자가 프로바이더 계정을 가지고 있지만 트레이트 요구 사항을 충족하지 않습니다. 리디렉션하지 마세요. 401 Unauthorized — 잘못된 키:
401 unauthorized response
{
  "error": "unauthorized"
}
시크릿 키가 올바른지, Authorization 헤더에 포함되어 있는지 확인하세요.

앱 리디렉션

사용자를 Base Verify 인증으로 리디렉션하려면:
Base Verify redirect URL format
https://verify.base.dev?redirect_uri={your_app_url}&providers={provider}
파라미터필수설명예시
redirect_uri인증 후 사용자를 보낼 위치https://yourapp.com
providers인증할 프로바이더x, coinbase, instagram, tiktok

트레이트 카탈로그

트레이트는 검증할 수 있는 프로바이더 계정의 특정 속성입니다. SIWE 메시지 리소스에 다음 형식으로 지정됩니다:
Trait resource format
urn:verify:provider:{provider}:{trait_name}:{operation}:{value}

연산자

연산자기호적용 대상설명예시
같음eq모든 타입정확히 일치verified:eq:true
초과gt정수엄격하게 큼followers:gt:1000
이상gte정수크거나 같음followers:gte:1000
미만lt정수엄격하게 작음followers:lt:5000
이하lte정수작거나 같음followers:lte:5000
포함 (목록)in문자열쉼표로 구분된 목록의 값verified_type:in:blue,government

타입 시스템

불리언 트레이트:
  • 값: "true" 또는 "false" (문자열)
  • eq 연산자만 지원
  • 예시: verified:eq:true
정수 트레이트:
  • 값: 문자열로 된 숫자
  • 지원: eq, gt, gte, lt, lte
  • 예시: followers:gte:1000
문자열 트레이트:
  • 값: 텍스트 문자열
  • 지원: eq, in
  • 예시: verified_type:eq:blue 또는 verified_type:in:blue,government

트레이트 조합

동일한 프로바이더에 대해 여러 트레이트를 지정하면 모두 충족되어야 합니다 (AND 논리):
Multiple traits for one provider
resources: [
  'urn:verify:provider:x',
  'urn:verify:provider:x:verified:eq:true',
  'urn:verify:provider:x:followers:gte:10000'
]
요청당 하나의 프로바이더만 확인할 수 있습니다. 여러 프로바이더를 확인하려면 별도의 API 호출을 사용하세요.

일반 패턴

계층형 접근:
Tiered access trait rules
// Bronze tier: any verified account
traits: { 'verified': 'true' }

// Silver tier: 1k+ followers
traits: { 'followers': 'gte:1000' }

// Gold tier: 10k+ followers
traits: { 'followers': 'gte:10000' }

Coinbase

프로바이더: coinbase (Coinbase)
트레이트타입연산자설명예시 값
coinbase_one_activeBooleaneq활성 Coinbase One 구독"true", "false"
coinbase_one_billedBooleaneqCoinbase One 청구된 사용자"true", "false"
Coinbase trait examples
// Check for Coinbase One subscribers
{
  provider: 'coinbase',
  traits: { 'coinbase_one_active': 'true' }
}

// Check for billed Coinbase One subscribers
{
  provider: 'coinbase',
  traits: { 'coinbase_one_billed': 'true' }
}

X

프로바이더: x (X)
트레이트타입연산자설명예시 값
verifiedBooleaneq어떤 유형의 인증이든 보유"true", "false"
verified_typeStringeq인증 유형"blue", "government", "business", "none"
followersIntegereq, gt, gte, lt, lte팔로워 수"1000", "50000"
X trait examples
// Check for any verified account
{
  provider: 'x',
  traits: { 'verified': 'true' }
}

// Check for specific verification type
{
  provider: 'x',
  traits: { 'verified_type': 'blue' }
}

// Check for follower count (greater than or equal to)
{
  provider: 'x',
  traits: { 'followers': 'gte:1000' }
}

// Combine multiple traits
{
  provider: 'x',
  traits: {
    'verified': 'true',
    'followers': 'gte:10000'
  }
}

Instagram

프로바이더: instagram (Instagram)
트레이트타입연산자설명예시 값
usernameStringeqInstagram 사용자명"john_doe"
followers_countIntegereq, gt, gte, lt, lte팔로워 수"1000", "50000"
instagram_idStringeq고유 Instagram 사용자 ID"1234567890"
Instagram trait examples
// Check for follower count (greater than)
{
  provider: 'instagram',
  traits: { 'followers_count': 'gt:1000' }
}

// Check for follower count (greater than or equal to)
{
  provider: 'instagram',
  traits: { 'followers_count': 'gte:5000' }
}

// Combine multiple traits
{
  provider: 'instagram',
  traits: {
    'username': 'john_doe',
    'followers_count': 'gte:10000'
  }
}

TikTok

프로바이더: tiktok (TikTok)
트레이트타입연산자설명예시 값
open_idStringeqTikTok Open ID (앱별 고유)"abc123..."
union_idStringeqTikTok Union ID (앱 전반 고유)"def456..."
display_nameStringeqTikTok 표시 이름"John Doe"
follower_countIntegereq, gt, gte, lt, lte팔로워 수"1000", "50000"
following_countIntegereq, gt, gte, lt, lte팔로잉 계정 수"500", "2000"
likes_countIntegereq, gt, gte, lt, lte총 받은 좋아요 수"10000", "100000"
video_countIntegereq, gt, gte, lt, lte게시된 동영상 수"50", "200"
TikTok trait examples
// Check for follower count
{
  provider: 'tiktok',
  traits: { 'follower_count': 'gt:1000' }
}

// Check for likes count
{
  provider: 'tiktok',
  traits: { 'likes_count': 'gte:10000' }
}

// Combine multiple traits (e.g., active creator)
{
  provider: 'tiktok',
  traits: {
    'follower_count': 'gte:5000',
    'likes_count': 'gte:100000',
    'video_count': 'gte:100'
  }
}

보안 및 개인 정보 보호

SIWE 서명 요구 사항

모든 API 호출은 지갑 소유자의 유효한 SIWE 서명이 필요합니다. 이는 다음을 방지합니다:
  • 인증 상태의 임의 조회
  • 제3자가 지갑의 인증 여부 확인
  • 열거 공격
사용자는 지갑을 제어하고 특정 트레이트 확인에 동의한다는 것을 증명하는 구조화된 메시지에 서명합니다:
SIWE payload example
{
  domain: "your-app.com",
  address: "0x1234...",
  chainId: 8453,
  resources: [
    "urn:verify:provider:x",
    "urn:verify:provider:x:verified:eq:true",
    "urn:verify:action:claim_airdrop"
  ]
}

트레이트 요구 사항 검증

백엔드가 프론트엔드에서 SIWE 메시지를 받으면, 메시지의 트레이트 요구 사항이 백엔드가 기대하는 것과 일치하는지 반드시 검증해야 합니다. 이는 사용자가 프론트엔드에서 트레이트 요구 사항을 수정하여 접근 제어를 우회하는 것을 방지합니다.
검증 없는 공격 예시:
  1. 앱에서 사용자가 팔로워 100명 이상을 요구함
  2. 사용자가 프론트엔드를 수정하여 팔로워 10명만 요청
  3. 수정된 메시지에 서명
  4. 검증 없이 백엔드가 요청을 Base Verify로 전달
  5. 사용자가 100명 미만의 팔로워로 접근 획득
구현:
Validate traits on the backend
import { validateTraits } from './lib/trait-validator';

const expectedTraits = {
  'followers': 'gte:100'
};

const validation = validateTraits(message, 'x', expectedTraits);

if (!validation.valid) {
  return res.status(400).json({
    error: 'Invalid trait requirements in message',
    details: validation.error
  });
}

시크릿 키 보호

절대 하지 말아야 할 것:
  • 프론트엔드 코드에 시크릿 키 포함
  • 브라우저에 노출되는 NEXT_PUBLIC_* 또는 유사한 환경 변수 사용
  • 버전 관리에 시크릿 키 커밋
  • 채팅, 이메일, 문서에 시크릿 키 공유
반드시 해야 할 것:
  • 백엔드 환경 변수에만 시크릿 키 저장
  • gitignore된 .env 파일 사용
  • 실수로 노출된 경우 즉시 키 교체
  • 백엔드에서만 Base Verify API 호출

OAuth 보안 모델

Base Verify는 OAuth를 통해 프로바이더 계정을 검증합니다:
  1. 사용자가 Base Verify 앱에서 OAuth 시작
  2. 프로바이더 (X, Instagram 등)가 사용자 인증
  3. 프로바이더가 Base Verify에 OAuth 토큰 반환
  4. Base Verify가 OAuth 토큰으로 계정 데이터 가져오기
  5. Base Verify가 사용자의 지갑과 연결된 인증 저장
  6. OAuth 토큰이 암호화되어 안전하게 저장됨
앱은 OAuth 토큰을 처리하거나 리디렉션하지 않습니다 — 이 모든 것은 Base Verify 앱 내에서 처리됩니다.

데이터 저장

Base Verify가 저장하는 것:
  • 인증된 프로바이더 계정과 연결된 지갑 주소
  • 프로바이더 계정 메타데이터 (사용자명, 팔로워 수, 인증 상태)
  • OAuth 토큰 (암호화됨, 앱과 공유되지 않음)
  • 인증 타임스탬프
Base Verify가 저장하지 않는 것:
  • 사용자의 개인 키
  • 프로바이더 계정 비밀번호
  • 사용자 활동 또는 브라우징 내역
  • 인증에 필요한 것 이상의 데이터
앱이 받는 것: /v1/base_verify_token을 호출하면 token, action, wallet만 받습니다. 개인 식별 정보(PII)는 반환되지 않습니다.

사용자 제어

사용자는 언제든지 인증을 삭제할 수 있습니다:
  • 저장된 모든 프로바이더 데이터 제거
  • 향후 토큰 생성 무효화
  • 앱에 저장된 토큰이 의미 없어짐 (사용자가 동일한 계정으로 재인증 불가)

캐싱

API 호출을 줄이기 위해 인증 결과를 캐시하세요:
  • 사용자 세션 동안 캐시 (영구적으로 아님)
  • 사용자가 지갑 연결을 해제할 때 캐시 지우기
  • 모든 페이지 로드마다 인증 확인하지 않기

지원

Base Verify 연동에 관심이 있으신가요? 관심 양식을 작성하면 팀에서 API 접근 권한을 제공해 드립니다.