6.3 KiB
6.3 KiB
WordPress SSO 플러그인: 구현 및 동작 원리
이 문서는 Baron SSO와 WordPress를 연동하는 플러그인의 상세한 구현 과정과 핵심 동작 로직을 설명합니다.
1. 프로젝트 목표 및 결과물
목표: 외부 SSO 인증을 통해 WordPress 사이트에 별도의 회원가입이나 로그인 절차 없이 자동으로 사용자를 인증하고, 실제 제품 데모처럼 보이는 세련된 UI/UX를 제공하는 WordPress 플러그인을 개발합니다.
핵심 결과물:
- 팝업창을 이용한 비동기 방식의 SSO 로그인 연동
- JWT
sub클레임을 이용한 안정적인 사용자 식별 및 자동 회원가입 - WordPress Hook을 활용하여 최소한의 코드로 핵심 기능 및 UI 구현
2. 핵심 로그인 플로우 (Sequence Diagram)
sequenceDiagram
actor User
participant WP Frontend (JS)
participant SSO Service (Popup)
participant WP Backend (PHP)
User->>WP Frontend (JS): "Baron SSO 로그인" 버튼 클릭
WP Frontend (JS)->>SSO Service (Popup): window.open() 팝업 실행
SSO Service (Popup)-->>User: 로그인 UI 표시
User->>SSO Service (Popup): 아이디/패스워드 입력 및 로그인
SSO Service (Popup)->>SSO Service (Popup): 인증 처리 및 JWT 생성
SSO Service (Popup)->>WP Frontend (JS): postMessage로 JWT 전송
Note right of SSO Service (Popup): 팝업창 닫힘
WP Frontend (JS)->>WP Frontend (JS): JWT 수신 후, `?token=[JWT]` 파라미터와 함께 페이지 새로고침
WP Frontend (JS)->>WP Backend (PHP): 페이지 요청 (GET /?token=...)
WP Backend (PHP)->>WP Backend (PHP): `init` hook에서 `token` 파라미터 감지
WP Backend (PHP)->>WP Backend (PHP): JWT 디코딩하여 `sub` 추출
WP Backend (PHP)->>WP Backend (PHP): `sub` 값으로 사용자 조회 (usermeta)
alt 사용자 없음
WP Backend (PHP)->>WP Backend (PHP): 신규 사용자 생성 (wp_create_user)
WP Backend (PHP)->>WP Backend (PHP): `sso_subject_id` 메타 정보 저장
end
WP Backend (PHP)->>WP Frontend (JS): 로그인 쿠키 생성 후 `token` 제거된 URL로 리다이렉트
WP Frontend (JS)->>WP Backend (PHP): 최종 페이지 요청 (GET /)
WP Backend (PHP)-->>WP Frontend (JS): 로그인된 페이지 렌더링
WP Frontend (JS)-->>User: 로그인 완료된 화면 표시
3. 상세 구현 내용
A. 프론트엔드 (JavaScript)
sso_add_popup_script함수 (wp_footerhook)- 팝업 실행:
openSsoPopup함수는window.open을 사용해 정해진 크기의 팝업창을 화면 중앙에 띄웁니다. - 토큰 수신:
window.addEventListener('message', ...)를 통해 다른 창으로부터 메시지를 안전하게 수신합니다. SSO 팝업창에서postMessage로 보낸 데이터가type: 'LOGIN_SUCCESS'이고token이 포함된 객체인지 검증합니다. - 페이지 리로드: 수신한 토큰을 쿼리 파라미터로 추가하여 현재 페이지를 다시 로드합니다. 이 리로드 과정이 백엔드 로직을 트리거하는 핵심 열쇠입니다.
- 팝업 실행:
B. 백엔드 (PHP)
sso_handle_jwt_login함수 (inithook)- WordPress가 초기화되는 시점에 실행되어,
$_GET['token']파라미터의 존재 여부를 가장 먼저 확인합니다. 이 방식을 통해 다른 어떤 콘텐츠보다 먼저 로그인 로직이 실행되도록 보장합니다.
- WordPress가 초기화되는 시점에 실행되어,
sso_process_jwt_and_login함수- JWT 파싱: 전달받은 JWT를
.기준으로 분리하고, 두 번째 부분(Payload)을 Base64 디코딩하여 사용자 정보를 담은 객체를 얻습니다. - 사용자 식별: 기존의 이메일 방식 대신,
sub클레임을sanitize_text_field로 안전하게 처리한 후get_users함수와meta_query를 사용해sso_subject_id와 일치하는 사용자를 찾습니다. 이 방식은 이메일이 없거나 변경되어도 동일 사용자를 식별할 수 있게 해줍니다. - 자동 회원가입: 일치하는 사용자가 없으면
wp_create_user를 호출합니다. 이때 WordPress의 필수 필드인 이메일은사용자명@sso.local과 같이 고유한 가상 주소로 채워줍니다. - 메타 데이터 저장: 신규 생성된 사용자의 경우,
update_user_meta를 통해sso_subject_id를 저장해두어 다음 로그인 시 동일 사용자로 인식할 수 있게 합니다. - 로그인 실행:
wp_set_current_user와wp_set_auth_cookie를 통해 WordPress의 표준 로그인 상태를 만듭니다.
- JWT 파싱: 전달받은 JWT를
C. UI/UX 개선
sso_custom_styles함수 (wp_headhook)- 하나의 함수에서 모든 CSS를
<style>태그로 감싸wp_head시점에 주입합니다. 이를 통해 별도의 CSS 파일 없이 플러그인 파일 하나만으로 UI 커스터마이징을 완료했습니다. - 히어로 헤더:
.entry-header클래스에calc(50% - 50vw)트릭을 사용한 음수 마진을 적용하여 부모 컨테이너의 너비 제약을 벗어나 화면 전체 너비의 배경을 갖도록 구현했습니다. - 카드형 목록:
.post,.article클래스에background-color,border,box-shadow,border-radius속성을 부여하여 각 글이 입체적인 카드처럼 보이도록 스타일링했습니다. - 기타 요소: 로그인 배지, CTA 배너, 버튼 인터랙션 등 모든 시각적 요소는 이 함수 내에 CSS 클래스로 정의되어 관리됩니다.
- 하나의 함수에서 모든 CSS를
sso_inject_header_button함수 (wp_body_openhook)is_user_logged_in()조건문을 통해 로그인 상태를 분기 처리합니다.- 로그인 시:
wp_get_current_user()로 현재 사용자 정보를 가져와 이메일을 상태 배지에 표시하고, 로그아웃 버튼을 출력합니다. - 로그아웃 시: 설정 페이지에서 저장한 SSO 프론트엔드 URL을 기반으로 로그인 팝업을 띄우는 버튼을 출력합니다.
sso_add_cta_banner함수 (loop_starthook)is_home() && !is_user_logged_in()조건문을 통해 블로그 메인 페이지에 로그아웃 상태인 경우에만 CTA 배너가 표시되도록 제어합니다.loop_start훅을 사용하여 게시물 루프가 시작되기 직전에 배너가 나타나도록 했습니다.