Skip to content

feat: 클라이언트별 커스텀 로그인 스킨 지원 - #28

Merged
mack-erel merged 18 commits into
mainfrom
feat/login-skin
Apr 21, 2026
Merged

feat: 클라이언트별 커스텀 로그인 스킨 지원#28
mack-erel merged 18 commits into
mainfrom
feat/login-skin

Conversation

@mack-erel

Copy link
Copy Markdown
Owner

Summary

  • OIDC/SAML 클라이언트마다 로그인 스킨 URL을 설정할 수 있는 client_skins 테이블 추가
  • R2 Private 버킷(SKIN_CACHE)을 TTL 캐시로 사용, fetch 실패/비HTML 응답 시 기본 스킨 fallback
  • X-IDP-Token 헤더로 스킨 URL에 인증 적용 (없으면 기본 스킨 노출)
  • 스킨 HTML 내 치환자 지원: {{IDP_FORM_ACTION}}, {{IDP_REDIRECT_TO}}, {{IDP_SKIN_HINT}}
  • 관리자 UI: 스킨 추가/삭제/활성화토글/캐시삭제

적용 필요 사항 (사용자 직접 실행)

# R2 버킷 생성
wrangler r2 bucket create idp-skin-cache

# wrangler.jsonc에 r2_buckets 바인딩 추가 (SKIN_CACHE / idp-skin-cache)
# DB 마이그레이션 적용
bun run db:migrate

스킨 HTML 예시

<form method="POST" action="{{IDP_FORM_ACTION}}">
  <input type="hidden" name="redirectTo" value="{{IDP_REDIRECT_TO}}">
  <input name="username" type="text">
  <input name="password" type="password">
  <button type="submit">로그인</button>
</form>

Test plan

  • OIDC 클라이언트에 스킨 URL 설정 후 로그인 페이지 접근 시 커스텀 스킨 노출 확인
  • 스킨 URL 다운 시 기본 스킨 fallback 확인
  • X-IDP-Token 없으면 fetch 실패 → 기본 스킨 노출 확인
  • R2 TTL 캐시 동작 확인
  • 관리자 스킨 페이지 CRUD 확인

🤖 Generated with Claude Code

mack-erel and others added 18 commits April 20, 2026 16:49
- client_skins 테이블 추가 (OIDC/SAML 클라이언트별, 스킨 타입별)
- R2 Private 기반 TTL 캐시 + fetch 실패 시 기본 스킨 fallback
- X-IDP-Token 헤더로 스킨 URL 보호, Content-Type HTML 검증
- 치환자: {{IDP_FORM_ACTION}}, {{IDP_REDIRECT_TO}}, {{IDP_SKIN_HINT}}
- OIDC/SAML 로그인 리다이렉트에 skinHint 파라미터 추가
- 관리자 스킨 관리 페이지 (생성/삭제/활성화/캐시삭제)
- wrangler.jsonc R2 바인딩(SKIN_CACHE) 추가 (gitignore로 별도 적용 필요)

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- client_skins.skinType enum에 signup, find_id, find_password 추가
- /signup, /find-id, /find-password 라우트 생성
- 커스텀 스킨 있으면 렌더, 없으면 기본 준비중 UI 표시
- 관리자 스킨 페이지에서 스킨 타입 선택 가능

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- /admin/skins/guide 가이드 페이지 생성 (개요, 동작흐름, 치환자, 인증헤더, HTML 예시, 캐시, 등록방법)
- 스킨 목록 페이지에 '가이드 보기' 링크 추가
- ko.json에 guide_* i18n 키 추가

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- step4b_r2Setup: wrangler r2 bucket create 실행 후 wrangler.jsonc bucket_name 업데이트
- --r2-bucket-name, --no-r2 CLI 옵션 추가
- 버킷 이미 존재할 경우 경고 후 계속 진행

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
클라이언트 선택 시 OIDC/SAML optgroup에서 자동 판별하여 hidden input으로 전송

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
deprecated API 경고 제거

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- 자유 회원가입: username/email/password 폼, 중복 검사, argon2id 해싱
- 아이디 찾기: 이메일로 조회 → 마스킹 표시 + 전체 아이디 이메일 발송
- 비밀번호 찾기: 이메일+아이디 확인 후 재설정 링크 이메일 발송 (1시간 유효)
- 비밀번호 재설정: 토큰 검증 후 새 비밀번호 설정
- passwordResetTokens 테이블 및 마이그레이션(0009) 추가
- nodemailer 기반 SMTP 이메일 모듈(src/lib/server/email.ts) 추가
- 로그인 페이지에 회원가입/아이디찾기/비밀번호찾기 링크 추가

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- oidcClients 스키마에 FC/BC 로그아웃 URI 컬럼 추가 (마이그레이션 0010)
- OIDC 백채널 로그아웃: logout_token JWT 생성 후 waitUntil로 비동기 POST
- OIDC 프론트채널 로그아웃: end-session 시 iframe 렌더링 후 자동 리다이렉트
- SAML SP-initiated SLO: LogoutRequest 파싱, 서명 검증, LogoutResponse 반환
- IDP-initiated 로그아웃 시 OIDC BC 및 SAML SLO 트리거
- OpenID 메타데이터에 FC/BC 로그아웃 지원 여부 추가
- 관리자 UI에 FC/BC 로그아웃 URI 설정 필드 추가

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- samlSloStates 테이블 추가로 체인 상태 DB 추적 (마이그레이션 0011)
- SP-initiated SLO: 다른 SP들을 순서대로 방문 후 최종 LogoutResponse 반환
- IDP-initiated SLO: /logout에서 체인 시작, 모든 SP 순회 후 세션 폐기
- SAMLResponse+RelayState로 체인 이어가기 (팝-퍼스트로 중복 처리 방지)
- 체인 완료 시 OIDC BC 로그아웃 + IDP 세션 폐기 + 쿠키 삭제

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@mack-erel
mack-erel merged commit 16329fd into main Apr 21, 2026
6 checks passed
@mack-erel
mack-erel deleted the feat/login-skin branch April 21, 2026 01:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant