01 SOFTWARE
API

API Authentication

01 SOFTWARE API 인증 방법 및 보안 가이드

API Authentication

01 SOFTWARE API는 JWT 토큰과 API 키 두 가지 인증 방식을 지원합니다.

인증 방식

1. JWT Token (권장)

사용자 인증 기반의 토큰 방식입니다.

토큰 획득

curl -X POST "https://api.01.software/api/users/login" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "password"
  }'

응답:

{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": {
    "id": "user_id",
    "email": "user@example.com",
    "role": "tenant-admin"
  },
  "exp": 1736251200
}

토큰 사용

curl "https://api.01.software/api/products" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

2. API Key (Server-side only)

서버 환경에서 사용하는 API 키 방식입니다.

주의: API Key는 절대 클라이언트에 노출하지 마세요!

curl "https://api.01.software/api/products" \
  -H "X-API-Key: your_secret_key_here"

Client Key vs Secret Key

Client Key (Public)

  • 용도: 브라우저/모바일 앱
  • 노출: 클라이언트에 노출 가능
  • 권한: 읽기 전용
  • 형식: pk_live_... 또는 pk_test_...
// ✅ 브라우저에서 사용 가능
const client = createBrowserClient({
  clientKey: process.env.NEXT_PUBLIC_SOFTWARE_CLIENT_KEY,
})

Secret Key (Private)

  • 용도: 서버 환경만
  • 노출: 절대 노출 금지
  • 권한: 읽기/쓰기
  • 형식: sk_live_... 또는 sk_test_...
// ✅ 서버에서만 사용
const client = createServerClient({
  clientKey: process.env.NEXT_PUBLIC_SOFTWARE_CLIENT_KEY,
  secretKey: process.env.SOFTWARE_SECRET_KEY, // 서버 전용
})

토큰 생명주기

토큰 만료

기본 만료 시간: 7일 (604800초)

// 환경 변수 설정
TOKEN_EXPIRATION = 604800 // 7일 (초 단위)

토큰 갱신

curl -X POST "https://api.01.software/api/users/refresh-token" \
  -H "Authorization: Bearer current_token"

응답:

{
  "token": "new_token",
  "refreshedAt": "2026-01-07T10:00:00Z",
  "exp": 1736856000
}

자동 갱신 (SDK)

const client = createBrowserClient({
  clientKey: process.env.NEXT_PUBLIC_SOFTWARE_CLIENT_KEY,
  onTokenRefresh: (newToken) => {
    // 새 토큰 저장
    localStorage.setItem('auth_token', newToken)
  },
})

세션 관리

로그인 상태 확인

curl "https://api.01.software/api/users/me" \
  -H "Authorization: Bearer $TOKEN"

응답:

{
  "user": {
    "id": "user_id",
    "email": "user@example.com",
    "role": "tenant-admin",
    "tenants": ["tenant_id"]
  }
}

로그아웃

curl -X POST "https://api.01.software/api/users/logout" \
  -H "Authorization: Bearer $TOKEN"

보안 모범 사례

1. 환경 변수 사용

# .env.local
NEXT_PUBLIC_SOFTWARE_CLIENT_KEY=pk_live_...
SOFTWARE_SECRET_KEY=sk_live_...

2. HTTPS 사용

프로덕션 환경에서는 반드시 HTTPS를 사용하세요.
// ✅ HTTPS
const baseUrl = 'https://api.01.software'

// ❌ HTTP (개발 환경 제외)
const baseUrl = 'http://api.01.software'

3. 토큰 저장

// ✅ HttpOnly Cookie (권장)
response.cookies.set('auth_token', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  maxAge: 604800,
})

// ⚠️ LocalStorage (XSS 취약)
localStorage.setItem('auth_token', token)

4. CORS 설정

// next.config.mjs
const nextConfig = {
  async headers() {
    return [
      {
        source: '/api/:path*',
        headers: [
          {
            key: 'Access-Control-Allow-Origin',
            value: 'https://yourdomain.com',
          },
          { key: 'Access-Control-Allow-Methods', value: 'GET,POST,PUT,DELETE' },
          {
            key: 'Access-Control-Allow-Headers',
            value: 'Authorization, Content-Type',
          },
        ],
      },
    ]
  },
}

에러 처리

인증 에러 코드

Status Code설명해결 방법
401Unauthorized로그인 필요
403Forbidden권한 부족
419Token Expired토큰 갱신 필요

에러 응답 예제

{
  "errors": [
    {
      "message": "You are not authorized to perform this action",
      "name": "Forbidden",
      "extensions": {
        "code": "FORBIDDEN"
      }
    }
  ]
}

SDK 통합

브라우저 클라이언트

import { createBrowserClient } from '@01.software/sdk'

const client = createBrowserClient({
  clientKey: process.env.NEXT_PUBLIC_SOFTWARE_CLIENT_KEY,
})

// 로그인
await client.collections.users.login({
  email: 'user@example.com',
  password: 'password',
})

// 인증된 요청 자동 처리
const { data } = await client.from('products').find()

서버 클라이언트

import { createServerClient } from '@01.software/sdk'

const client = createServerClient({
  clientKey: process.env.NEXT_PUBLIC_SOFTWARE_CLIENT_KEY,
  secretKey: process.env.SOFTWARE_SECRET_KEY
})

// API 키로 자동 인증
const { data } = await client.api.createOrder({...})

다음 단계

On this page