Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d2aeb4c
docs: OAuth 인증 기반 User 도메인 ADR (#34)
sevineleven Jul 29, 2026
c3cb973
feat: OAuth 인증 기반 User 도메인 (#34)
sevineleven Jul 29, 2026
fbef741
Merge remote-tracking branch 'origin/dev' into feat/34-oauth-user-auth
sevineleven Aug 13, 2026
7361050
feat: 소셜 로그인을 앱이 쓰는 계약으로 맞춘다 (kakao·apple·google)
sevineleven Aug 13, 2026
b019319
fix: 토큰이 로그에 그대로 남는 구멍을 막는다
sevineleven Aug 13, 2026
fff7daf
infra: 소셜 로그인 시크릿 주입 경로와 .p8 유출 차단
sevineleven Aug 13, 2026
02d1f0e
docs: ADR 0002 을 앱이 쓰는 실제 계약으로 개정한다
sevineleven Aug 13, 2026
67d0990
infra: 마이그레이션 검증 잡에 JWT 서명키 더미를 넣는다
sevineleven Aug 13, 2026
c2a0923
fix: 카카오 액세스 토큰이 우리 앱 것인지 검증한다
sevineleven Aug 13, 2026
0d59592
fix: 구글 ID 토큰의 iss 표기 두 가지를 모두 받는다
sevineleven Aug 13, 2026
ba9a4b4
Merge remote-tracking branch 'origin/dev' into feat/34-oauth-user-auth
sevineleven Aug 14, 2026
679696e
fix: OAuth 규격 이름의 토큰과 물결 섞인 Bearer 를 로그에서 가린다
sevineleven Aug 16, 2026
6ea2145
fix: Bearer scheme 을 대소문자 없이 읽는다
sevineleven Aug 16, 2026
5bef0cb
fix: 식별자 없는 로그아웃이 조용히 성공하던 것
sevineleven Aug 16, 2026
0b07f0a
perf: JWKS 조회 상한을 3초로 잡는다
sevineleven Aug 16, 2026
2395d59
fix: refresh 회전을 원자적으로 선점한다
sevineleven Aug 16, 2026
983f8b7
test: refresh 회전의 동시성과 유예 창을 잠근다
sevineleven Aug 16, 2026
eac0077
docs: ADR 의 코드 블록에 언어를 지정한다
sevineleven Aug 16, 2026
2bafbdb
fix: Basic 자격증명으로는 상태를 바꾸지 못하게 한다
sevineleven Aug 16, 2026
e6642b3
test: Basic 으로 쓰기가 막히는 것을 잠근다
sevineleven Aug 16, 2026
397dae2
fix: iss 클레임이 없는 토큰이 500 을 내던 것
sevineleven Aug 16, 2026
c6b46b2
test: ID 토큰 검증이 실제로 거절하는지 잠근다
sevineleven Aug 16, 2026
62f5f0e
feat: 로그인할 때 이 기기를 사용자에게 이어 둔다
sevineleven Aug 16, 2026
fe3fcc8
test: 기기 연결이 실제로 기록되는지 잠근다
sevineleven Aug 16, 2026
eb32b84
perf: 살아 있는 refresh 만 인덱스로 짚고 한 문장으로 폐기한다
sevineleven Aug 16, 2026
37f6d3f
perf: 위조 토큰이 JWKS 조회를 유발하지 못하게 한다
sevineleven Aug 16, 2026
c060d23
fix: JWKS 캐시를 넣으며 좁아진 호출 상한과 넓어진 알고리즘을 되돌린다
sevineleven Aug 16, 2026
de0f68e
fix: 기기 연결 실패가 로그인을 막던 것
sevineleven Aug 16, 2026
731a990
fix: JWKS 응답 크기 상한을 되돌리고 상수 실수를 부팅에서 끊는다
sevineleven Aug 16, 2026
0692c35
test: 기기 연결이 로그인을 막지 않는 것을 잠근다
sevineleven Aug 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,13 @@ jobs:
DB_URL: jdbc:mysql://127.0.0.1:3306/offway?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul
DB_USERNAME: root
DB_PASSWORD: ci-verify
# 이 둘은 비면 부팅이 실패한다(열린 채 뜨는 쪽이 더 위험해서 그렇게 만들어 두었다).
# 아래 셋은 비면 부팅이 실패한다(열린 채 뜨는 쪽이 더 위험해서 그렇게 만들어 두었다).
# 검증용 더미이고 이 잡 밖으로 나가지 않는다.
OFFWAY_BASIC_USERNAME: ci
OFFWAY_BASIC_PASSWORD: '{noop}ci'
# 자체 토큰 서명키(#34). 없으면 아무 토큰이나 위조 가능해져 TokenIssuer 가 부팅을 막는다.
# HS256 최소 32바이트라 길이를 채운 더미를 쓴다. 운영 값은 JWT_SECRET 시크릿에서 온다.
JWT_SECRET: ci-migration-verify-only-not-a-real-signing-key
run: |
set -uo pipefail
JAR=$(ls build/libs/*.jar | grep -v plain | head -1)
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ jobs:
DATA_GO_KR_SERVICE_KEY=${{ secrets.DATA_GO_KR_SERVICE_KEY }}
TMAP_APP_KEY=${{ secrets.TMAP_APP_KEY }}
DISCORD_WEBHOOK_URL=${{ secrets.DISCORD_WEBHOOK_URL }}
JWT_SECRET=${{ secrets.JWT_SECRET }}
KAKAO_REST_API_KEY=${{ secrets.KAKAO_REST_API_KEY }}
KAKAO_APP_ID=${{ secrets.KAKAO_APP_ID }}
GOOGLE_WEB_CLIENT_ID=${{ secrets.GOOGLE_WEB_CLIENT_ID }}
APPLE_SERVICE_ID=${{ secrets.APPLE_SERVICE_ID }}
APPLE_TEAM_ID=${{ secrets.APPLE_TEAM_ID }}
APPLE_KEY_ID=${{ secrets.APPLE_KEY_ID }}
APPLE_PRIVATE_KEY_BASE64=${{ secrets.APPLE_PRIVATE_KEY_BASE64 }}
ENVEOF
scp -i ~/.ssh/deploy_key env.prod \
"${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }}:~/offway/env.prod"
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ secret.properties
*.jks
*.keystore
*.key
# Apple 로그인 키 (AuthKey_XXXXXXXXXX.p8) — 레포가 public 이라 확장자로 먼저 막는다.
# 재발급이 안 되는 키라 한 번 새면 콘솔에서 폐기하고 새로 만드는 수밖에 없다.
*.p8
credentials.json
**/secrets/

Expand Down
46 changes: 46 additions & 0 deletions application-secret.properties.example
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,52 @@ TMAP_APP_KEY=
APIDOG_ACCESS_TOKEN=
APIDOG_PROJECT_ID=

# ── 소셜 로그인 (#34) ─────────────────────────────────────────
# 비어 있어도 부팅된다 — 해당 provider 로그인만 USER-002 로 실패한다(로컬 실행성 규칙).
# 로컬에서 실 provider 토큰 없이 API 를 부르려면 POST /api/v1/auth/dev-login 을 쓴다(local 전용).

# 자체 JWT 서명키 (HS256, 최소 32바이트)
# ⚠️ 이 값을 아는 사람은 아무 사용자의 토큰이나 위조할 수 있다.
# - local 은 application-local.properties 의 개발용 고정값이 쓰이므로 비워둬도 된다.
# - 운영은 반드시 주입한다. 없으면 부팅이 실패한다(조용히 약한 키로 뜨지 않게).
# - 생성: openssl rand -base64 48
JWT_SECRET=

# 카카오 REST API 키
# - 발급: https://developers.kakao.com > 내 애플리케이션 > 앱 키 > REST API 키
# - 서버는 이 키로 카카오를 부르지 않는다(프로필 조회는 사용자 액세스 토큰만 받는다).
# 앱이 등록됐는지 판별하는 용도라, 비면 카카오 로그인을 받지 않는다.
# - client secret 은 필요 없다. 그 값이 쓰이는 토큰 엔드포인트(POST /oauth/token)는 앱이 SDK 로 끝낸다.
KAKAO_REST_API_KEY=

# 카카오 앱 번호 (앱 ID) — Apple 의 APPLE_SERVICE_ID · 구글의 GOOGLE_WEB_CLIENT_ID 와 같은 역할이다
# ⚠️ 이 값이 비면 카카오 로그인을 아예 받지 않는다. 조용히 검증을 건너뛰지 않기 위해서다.
# 검증이 없으면 **다른 카카오 앱에서 발급된 액세스 토큰**을 그대로 우리 서버에 던져 그 사용자로
# 로그인할 수 있다 — 토큰 하나만 손에 넣으면 되는 계정 탈취다.
# - 확인: https://developers.kakao.com > 내 애플리케이션 > 앱 설정 > 요약 정보 > 앱 ID (숫자)
# - REST API 키가 아니다. 서버는 토큰 정보 조회(/v1/user/access_token_info)가 돌려주는 app_id 와 이 값을 대조한다.
KAKAO_APP_ID=

# 구글 '웹' 클라이언트 ID
# ⚠️ iOS/Android 클라이언트 ID 가 아니라 **웹** 클라이언트 ID 다. ID 토큰의 aud 검증에 쓴다 —
# 값이 어긋나면 앱이 보낸 토큰이 전부 401 이 된다.
# - 발급: https://console.cloud.google.com > API 및 서비스 > 사용자 인증 정보 > OAuth 2.0 클라이언트 ID (웹)
GOOGLE_WEB_CLIENT_ID=

# 애플 Service ID — identityToken 의 aud 검증에 쓴다
# - 발급: https://developer.apple.com > Certificates, Identifiers & Profiles > Identifiers > Services IDs
APPLE_SERVICE_ID=

# 애플 서버 인증용 (지금은 미사용 — 회원 탈퇴 시 Apple 연결 해제(revoke)에 필요해 미리 받아 둔다)
# ⚠️ APPLE_PRIVATE_KEY_BASE64 는 .p8 키 파일을 base64 로 인코딩한 값이다.
# env-file 이 여러 줄 값을 못 받아 한 줄로 만든 것이라, 쓸 때 디코딩한다.
# 원본 .p8 은 재발급이 안 된다 — 레포에 두지 말 것(.gitignore 가 *.p8 을 막는다).
# - 생성: base64 -i AuthKey_XXXXXXXXXX.p8 | tr -d '\n'
# - 발급: https://developer.apple.com > Keys > Sign in with Apple 활성화한 키
APPLE_TEAM_ID=
APPLE_KEY_ID=
APPLE_PRIVATE_KEY_BASE64=

# 디스코드 알림 웹훅 URL (외부 API 한도 알림 · 정책 만료 알림)
# ⚠️ URL 끝 token 조각을 아는 사람은 누구나 그 채널에 글을 쓸 수 있다 — 비밀로 다룬다.
# - 발급: 디스코드 채널 > 채널 편집 > 연동 > 웹훅 > 새 웹훅 > 웹훅 URL 복사
Expand Down
Loading