1. 인증과 인가의 분리
두 개념을 서로 다른 계층에서 처리해, 애플리케이션 코드가 토큰 검증 로직을 갖지 않도록 설계했습니다.
Authentication
인증 — 너는 누구인가
Cognito User Pool이 담당합니다. 이메일·비밀번호를 검증하고 서명된 JWT를 발급합니다. 비밀번호는 Cognito가 관리하므로 앱과 서버는 비밀번호를 저장하지 않습니다.
Authorization
인가 — 무엇을 할 수 있는가
API Gateway가 토큰 서명·만료를 검증하고, Lambda가 클레임의 sub(userId)로 본인 데이터만 접근하도록 범위를 제한합니다.
2. 전체 흐름 다이어그램
- 로그인 요청 — 앱이 이메일·비밀번호로
POST /auth/login을 호출하고, Lambda가 Cognito의USER_PASSWORD_AUTH플로우를 실행합니다. - 토큰 발급 — Cognito가 ID / Access / Refresh 토큰을 반환합니다. 앱은 이를 안전한 저장소에 보관합니다.
- 인증된 호출 — 이후 모든 보호 API 호출에
Authorization: Bearer <AccessToken>헤더를 자동 첨부합니다(OkHttp Interceptor). - 토큰 검증 — API Gateway JWT Authorizer가 Cognito JWKS 공개키로 서명과 만료를 검증합니다. 실패하면 Lambda까지 도달하지 않고
401을 반환합니다. - 클레임 전달 — 검증을 통과하면 디코딩된 클레임이 이벤트 컨텍스트로 Lambda에 전달됩니다.
- 범위 제한 — Lambda는
sub를 파티션 키에 사용해 타인의 데이터를 조회할 수 없도록 원천 차단합니다.
3. 공개 라우트와 보호 라우트
회원가입·로그인은 토큰을 받기 전에 호출해야 하므로 공개로 두고, 그 외 전체를 $default 라우트에서 JWT로 보호합니다.
| 구분 | 라우트 | 인증 | 이유 |
|---|---|---|---|
| 공개 | POST /auth/signup | 없음 | 가입 시점에는 토큰이 없음 |
POST /auth/login | 없음 | 토큰을 발급받는 진입점 | |
POST /auth/confirm | 없음 | 이메일 인증코드 확인 | |
GET /health | 없음 | 모니터링용 헬스체크 | |
| 보호 | $default (그 외 전체) | JWT 필수 | 기본 차단(default-deny) 정책 |
기본 차단 설계
새 API를 추가하면 별도 설정 없이 자동으로 인증 보호를 받습니다. 공개로 열려면 명시적으로 공개 라우트 목록에 추가해야 하므로, 실수로 인증 없는 엔드포인트가 노출될 위험이 낮습니다.
4. 토큰 종류와 수명
| 토큰 | 수명 | 용도 | 비고 |
|---|---|---|---|
| Access Token | 1시간 | API 호출 인가 | API Gateway가 검증하는 대상 |
| ID Token | 1시간 | 사용자 프로필 정보(email, name) | 클라이언트 화면 표시용 |
| Refresh Token | 30일 | Access/ID 토큰 재발급 | 만료 시 재로그인 필요 |
- 서명 알고리즘은 RS256(비대칭) — 검증 측은 공개키만 필요하므로 비밀키 공유가 없습니다.
- 모바일 앱은 퍼블릭 클라이언트로 구성해 클라이언트 시크릿을 사용하지 않습니다(앱 디컴파일 시 유출 방지).
- 토큰 수명을 짧게 두고 Refresh로 갱신 → 토큰 유출 시 피해 시간을 제한합니다.
5. 계정 정책
| 항목 | 설정 |
|---|---|
| 로그인 식별자 | 이메일 (자동 검증) |
| 비밀번호 최소 길이 | 8자 |
| 비밀번호 구성 | 영소문자 + 숫자 필수 |
| 계정 복구 | 검증된 이메일로 재설정 |
| 허용 인증 플로우 | USER_PASSWORD_AUTH, USER_SRP_AUTH, REFRESH_TOKEN_AUTH |