인증
모든 API 요청은 Authorization 헤더에 Bearer 토큰을 포함해야 합니다. (OPTIONS 요청 제외)
토큰 형식
토큰은 JSON 페이로드를 Base64URL(RFC 4648)로 인코딩한 문자열입니다.
토큰 페이로드 구조
{
"v": 1,
"alg": "HS256",
"sig": "hex_signature",
"key": "companies/comp_123/files/document.pdf",
"exp": 1705996800,
"method": "PUT",
"originalFilename": "document.pdf",
"target_date": "2024-01-01",
"meta": {
"mime": "application/pdf",
"size": 5242880,
"company_id": "comp_123",
"related_doc_id": "doc_456",
"site_id": "site_789",
"doc_type": "contract",
"doc_page": "1",
"tags": {},
"UID": "user_id"
}
}
필드 설명
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
v |
number | O | 프로토콜 버전 (현재 1) |
alg |
string | O | 알고리즘 (HS256) |
sig |
string | O | HMAC-SHA256 서명 (16진수) |
key |
string | O | R2 객체 경로 (companies/로 시작해야 함) |
exp |
number | O | 만료 시간 (Unix 타임스탬프) |
method |
string | - | 허용할 HTTP 메서드 |
originalFilename |
string | - | 업로드 시 파일명 검증용 |
target_date |
string | - | 대상 날짜 |
meta |
object | - | 파일 메타데이터 |
meta 필드 설명
| 필드 | 타입 | 설명 |
|---|---|---|
mime |
string | 예상 MIME 타입 (업로드 시 검증) |
size |
number | 예상 파일 크기 (바이트, 업로드 시 검증) |
company_id |
string | 회사 ID |
related_doc_id |
string | 관련 문서 ID |
site_id |
string | 사이트 ID |
doc_type |
string | 문서 타입 |
doc_page |
string | 문서 페이지 |
tags |
object | 추가 태그 |
UID |
string | 사용자 ID |
서명 생성
- 페이로드에서
sig를 제외한 필드로 서명 대상 문자열을 구성합니다. - HMAC-SHA256 알고리즘으로 서명을 생성합니다.
- 서명을 16진수 문자열로 변환하여
sig필드에 포함합니다.
검증 흐름
1. Authorization 헤더에서 Bearer 토큰 추출
└─ 없으면: 401 "Missing token"
2. Base64URL 디코딩 → JSON 파싱
└─ 실패: 400 "Invalid token format"
3. 필수 필드(sig, key, exp) 존재 확인
└─ 누락: 400 "Malformed token payload"
4. HMAC-SHA256 서명 검증 (상수 시간 비교)
└─ 불일치: 403 "Invalid signature"
5. 만료 시간 검증
└─ 만료: 403 "Token expired"
6. 검증 통과 → 페이로드 반환
보안: 타이밍 어택 방어
서명 검증 시 constantTimeEqual() 함수를 사용하여 상수 시간 비교를 수행합니다. 문자열의 모든 문자를 XOR 비교하여, 서명 일치 여부와 무관하게 항상 같은 실행 시간을 보장합니다.
인증 에러 코드
| HTTP 상태 | 메시지 | 원인 |
|---|---|---|
| 401 | Missing token | Authorization 헤더 없음 |
| 400 | Invalid token format | Base64URL 디코딩 또는 JSON 파싱 실패 |
| 400 | Malformed token payload | sig, key, exp 필드 누락 |
| 403 | Invalid signature | HMAC 서명 불일치 |
| 403 | Token expired | 토큰 만료 |