역할
OAW(OAuth2.0 WAS)는 스마트홈 플랫폼의 인증 서버임. 성격이 다른 두 인증 체계를 한 서버가 제공함. 전체 그림은 공개노트/개발/시스템 구성.
| 체계 | 누가 쓰나 | 진입점 | 받은 토큰으로 부르는 곳 |
|---|---|---|---|
| client_credentials | 홈넷사 홈넷서버, 내부 APW, 층간소음알리미 기기 | POST /api/ccg/authcheck(발급), /api/ccg/tokencheck(검증) | APW |
| authorization_code + refresh_token (JWT) | 가전사 파트너(삼성 sse, LG lge) | /api/uma/login, /api/uma/authorize, /api/uma/token | PIW |
- 수신 전용 서버임. OAW가 밖으로 부르는 것은 APW의 기기 이벤트 구독 요청 1건뿐임
- 외부 진입은
homez-api.lh.or.kr:8094로 들어온 요청 중/api/ccg/authcheck만 Apache가 OAW로 넘김. 나머지는 APW로 감. 공개노트/개발/모듈/APW 연계 서버 - 2024-06 인수인계 문서에는 “client_credential 1가지만 사용”으로 적혀 있으나, 이후 가전사 연동용 JWT 흐름이 추가됨
기술 스택
| 항목 | 값 |
|---|---|
| 프레임워크 | Spring Boot 2.5.3, Java 8, Spring Security OAuth2 2.3.8, Gradle, war 패키징(oaw.war) |
| DB | PostgreSQL smahdb, Spring Data JPA |
| 세션 | Redis(Spring Session, Sentinel). 세션 600초 |
| JWT | jjwt, HS256. access/refresh 서명키가 서로 다름(교차 검증 안 됨) |
| 설정 암호화 | jasypt |
| HTTP 클라이언트 | unirest(APW 호출용) |
| 포트 | 8082 (모든 프로필 공통) |
| 톰캣 | /usr/local/tomcat-oaw/. 기동은 startup.sh(수신 전용이라 프록시 버전이 아님) |
| 로그 | /app/logs/was/tomcat-oaw/ |
| Jenkins 잡 | (DEV/PROD)-lh-smah-server-oaw |
토큰 유효기간은 아래 “토큰 종류” 표 참고.
확인 필요
src/main/resources/에 확장자를 일부러 깨뜨려 비활성화한 잔재 파일 3개가 남아 있고 평문 DB 계정과 jasypt 키가 들어 있음. 소스 유출 시 위험하므로 삭제 권고- 개발 프로필의 리프레시 토큰 유효기간이 2주의 자릿수 오타로 추정됨(그대로면 약 140일). 커밋 이력상 토큰 유효기간을 여러 번 임시로 바꾼 흔적이 있어 현재 값이 의도한 값인지 확인 필요
- 개발 프로필은 로그 레벨이 DEBUG·TRACE라 로그량이 매우 큼. 디스크 부족으로 로그 경로를 옮긴 이력이 있음
홈넷사·내부 서버 토큰 (client_credentials)
발급 (POST /api/ccg/authcheck)
홈넷사 홈넷서버가 자기 client_id·client_secret으로 AccessToken을 받아 감. 이 토큰으로 APW의 홈넷 연동 API를 부름. 홈넷사 입장의 연동 절차는 공개노트/기능/홈넷 서버 연동.
- Basic 인증 또는 폼 파라미터로
client_id·client_secret, 본문에grant_type=client_credentials(둘 다 허용) - 요청을
alog.tb_oauth_ctf_l에 먼저 기록함 - 클라이언트를 조회해 인증함
- 기존 토큰 행을 지우고 새 토큰을
cmn.tb_hnsvr_lnkg_tkn_d에 넣음. 즉 클라이언트당 유효 토큰은 1개이고 재발급하면 이전 토큰은 즉시 무효가 됨 - 표준 OAuth2 JSON(
access_token,token_type,expires_in,scope)으로 응답하고, 응답 본문도 같은 로그 행에 기록함
핵심 규칙
- RefreshToken은 발급하지 않음. 만료되면 다시 발급받아야 함
- scope은
read write고정. 권한은 홈넷서버ROLE_HNSVR/ 내부·층간소음ROLE_INTSVR고정 - 홈넷서버 조회 조건에 삭제여부
N+ 연동상태코드ON이 붙음. 연동상태가ON이 아니면 토큰 저장 단계에서 실패함 trace_id,sbd_id파라미터는 연동규격 V1.1에서 추가된 항목이고, 없는 요청(V1.0)도 동작함
운영 시 알아둘 점
- 홈넷사가 “토큰 발급이 안 된다”고 하면 먼저
cmn.tb_hnsvr_m의 해당 행에서 삭제여부와 연동상태코드를 봄. 관리자 시스템에서 연동 시험 시작을 안 눌렀으면 발급되지 않음 - 로그 검색어:
Could not find hnsver_sn,Client not found:,result_code:4011(client_id 오류),result_code:4012(client_secret 오류),result_code:4013(정보 부족),result_code:4019(내부 오류) - 같은 client_id로 두 서버가 동시에 토큰을 받아 쓰면 나중 발급이 앞 토큰을 지워 앞 서버가 401을 맞음
검증 (/api/ccg/tokencheck)
APW가 홈넷서버에게 받은 AccessToken이 유효한지 OAW에 물어봄. 내부 연계 전용이고 인증된 클라이언트만 호출할 수 있음. Apache가 외부에서 이 경로를 넘기지 않음. 로그 검색어 Failed to find access token for token.
OAW가 죽으면 APW의 /api/hn2lh/** 전체가 4013(인증 서버 장애)으로 401 응답함.
클라이언트(연동 대상) 등록 방식
client_id 모양을 보고 세 저장소 중 하나를 고름. OAuth 표준의 oauth_client_details 테이블은 쓰지 않음.
| 구분 | 판별 조건 | 테이블 | client_id | client_secret |
|---|---|---|---|---|
| 내부 리소스 서버(APW) | client_id가 내부 상수 ID와 같음 | cmn.tb_cstt_m | cstt_id | cstt_vl |
| 층간소음알리미 기기 | client_id가 fns-로 시작 | cmn.tb_nsba_dvc_m | fns- + MAC | 기기 ID |
| 홈넷사 홈넷서버 | 그 외 전부 | cmn.tb_hnsvr_m | hnsvr_id | hnsvr_scrtkey |
- 신규 홈넷사 연동은 별도 등록 화면 없이
cmn.tb_hnsvr_m에 행을 넣고 ID·시크릿을 알려주는 것이 전부임. 연동상태코드를ON으로 올리는 것을 잊으면 발급이 안 됨 - scope·grant type·권한은 DB 컬럼이 아니라 코드에 고정되어 있음
- client_secret을 평문으로 비교함(DB에도 평문 저장). 해시 적용 코드는 주석으로만 남아 있음
- 에너지플랫폼(이음)은 API 키 방식이라 OAW 대상이 아님
가전사 연동 (삼성·LG)
삼성 SmartThings·LG 앱에서 LH 계정을 연결할 때 쓰는 흐름임. 입주민이 보는 화면과 동작은 공개노트/기능/우리집제어 “파트너 가전”.
1. 입주민 로그인 (POST /api/uma/login)
가전사 앱 웹뷰에 뜨는 LH 로그인 화면의 제출 처리임.
- 단지 ID가 넘어오면
아이디 + 단지로 사용자를 찾고, 없으면 아이디만으로 찾음(삼성 요청사항). 같은 아이디가 단지별로 존재할 수 있다는 뜻임 - 비밀번호는 MAW와 같은 방식(아이디를 salt로 쓰는 SHA-512)으로 비교함
- 불일치 시 실패 횟수를 올리고 응답에 남은 정보를 담음. 성공하면 실패 횟수를 초기화함
“삼성 앱에서 LH 로그인이 안 된다”는 문의는 사용자 상태(usr_ss_cd)로 갈림.
| 상태 | 뜻 | 로그인 결과 |
|---|---|---|
USE | 사용 | 정상 |
INI | 초기화 | 정상 처리하되 비밀번호 변경 유도 |
RDY | 승인대기 | 미승인 사용자 |
DEN | 승인거부 | 승인거부 사용자 |
LCK | 잠김 | 계정 잠김 |
STP | 중지 | 계정 중지 |
아이디가 아예 없으면 존재 여부를 숨기려고 비밀번호 불일치와 같은 메시지를 내려줌. MAW 쪽 상태 코드 체계와는 값이 일부 다름에 주의. 공개노트/기능/로그인과 세대 승인
2. Authorization Code 발급 (GET /api/uma/authorize)
- 파트너 테이블에서 client_id로 파트너를 찾고
redirect_uri가 등록값과 완전히 일치해야 함 - 미인증 상태면 로그인 화면으로 보내고, 인증되어 있으면 임의의 code를 만들어 저장한 뒤
redirect_uri로 돌려보냄 - 파트너별로 (사용자, 파트너) 조합 1행만 유지하고 code만 갱신함
- 삼성일 때는
state가 Base64 JSON이고 그 안의installedAppId를 저장함. 파싱에 실패해도 code 발급은 진행됨(로그만 남김)
운영 시 알아둘 점
- 가전사에서 “연결이 안 된다”고 하면 파트너 테이블의
redir_uri가 가전사가 보내는 값과 글자 하나까지 같은지 봄. 다르면20114 - 로그 검색어
samsung OAuth state parsing error - 파트너 사용여부(
us_yn) 컬럼은 있으나 코드에서 검사하지 않음.N으로 막으려 해도 막히지 않음
3. JWT 토큰 발급·재발급 (POST /api/uma/token)
grant_type=authorization_code: code·redirect_uri·client_secret을 확인하고 access·refresh JWT를 발급함. code는 1회용이라 발급 후 지움- 토큰 발급 직후 APW에 기기 이벤트 구독을 비동기로 요청함(응답을 확인하지 않음). 실패해도 토큰 발급은 정상 진행됨
grant_type=refresh_token: 서명·만료를 검증하고 DB의 저장값과 대조한 뒤 새 access 토큰만 발급함. 리프레시 토큰은 회전하지 않음
운영 시 알아둘 점
- access는 1시간, refresh는 2주임. 2주 넘게 앱을 안 쓰면 재연동이 필요함
- 사용자가 다시 연동(authorize)을 타면 리프레시 토큰이 새 값으로 덮여, 기존에 들고 있던 토큰은
20123(불일치)로 깨짐 - 삼성 커넥터는 오류
error값이invalid_grant인 것을 보고 재인증을 트리거함 - 삼성·LG 앱에서 기기 상태가 실시간으로 안 바뀌면 구독 요청이 실패했을 수 있음. 로그 검색어
Failed to call subscribeDeviceEvent.cmn.tb_cstt_m의 APW 주소·API 키가 비어 있으면 조용히 아무것도 하지 않음
토큰 종류 — 어느 서버가 어떤 토큰을 쓰나
| 토큰 | 발급 대상 | 형식 | 유효기간 | 저장소 | 사용처 |
|---|---|---|---|---|---|
| client_credentials AccessToken | 홈넷서버, APW, 층간소음 기기 | 불투명 문자열 | 24시간 | cmn.tb_hnsvr_lnkg_tkn_d | APW 호출 |
| client_credentials RefreshToken | — | 발급 안 함 | — | — | — |
| 가전사 AccessToken | 삼성 sse, LG lge | JWT | 1시간 | 저장 안 함(무상태 검증) | PIW 호출 |
| 가전사 RefreshToken | 삼성 sse, LG lge | JWT | 2주 | cmn.tb_oauth_m | /api/uma/token 재발급 |
| ApiKey | 내부 WAS ↔ APW·OAW | 문자열 | 만료 없음 | cmn.tb_cstt_m | 헤더 인증 |
| 앱 Access/Refresh | 입주민 앱 | JWT | 15일 / 30일 | Refresh만 cmn.tb_refsh_tkn_m | MAW 호출. 공개노트/개발/모듈/MAW 앱 API 서버 |
| LH → 홈넷 방향 토큰 | APW가 홈넷서버에서 받아옴 | 홈넷사 발급 | 홈넷사 정책 | cmn.tb_hnsvr_lnkg_tkn_d | 홈넷서버 호출. 공개노트/기능/홈넷 서버 연동 |
확인 필요
코드상 홈넷사 AccessToken 유효기간은 24시간인데, 운영 정리본과 공개노트/기능/홈넷 서버 연동에는 “1시간마다 바뀜”으로 적혀 있음. 어느 쪽이 맞는지, 홈넷사 연동규격서에 명시된 값이 무엇인지 담당자 확인 필요(규격서 원문은 저장소에 없음).
이 유효기간을 MAW는 쓰지 않음 — MAW는 홈넷 토큰을 캐시하지 않고 홈넷서버를 부를 때마다 APW에서 새로 받아 씀(2026-09-18 코드 확인). 따라서 유효기간이 얼마든 MAW 쪽에 고칠 코드는 없음. 공개노트/개발/모듈/MAW 앱 API 서버
인증 로깅과 실패 응답
OAW로 들어오는 모든 요청·응답을 alog.tb_oauth_ctf_l에 남김. 홈넷사 연동 문제 추적의 1차 근거임. 요청 시 행을 만들고 응답 본문으로 같은 행을 갱신함.
인증 실패는 홈넷 연동규격 형식의 JSON({trace_id, result_code})을 HTTP 401로 내려줌. result_message는 규격에서 삭제되어 담지 않음.
| result_code | 뜻 |
|---|---|
4010 | 인증 필요(접근 거부) |
4011 | 인증 실패 — client_id 오류 |
4012 | 인증 실패 — client_secret 오류 |
4013 | 인증을 위한 정보가 부족함 |
4019 | 인증 실패 — 내부 오류 |
5001 | 서버 오류 |
가전사 OAuth 오류 코드는 201xx 체계임. 자주 보는 것만 정리함.
| 코드 | 뜻 |
|---|---|
20102 | 등록되지 않은 client_id |
20104 | client_secret 불일치 |
20107 | code를 찾을 수 없음(이미 사용했거나 만료) |
20111 | 지원하지 않는 grant_type |
20114 | 등록된 redirect_uri와 불일치 |
20117 | code가 아닌 response_type |
20123 | 저장된 refresh_token과 불일치 |
20124 / 20125 | refresh_token 만료 / 서명·형식 오류 |
데이터
| 테이블 | 용도 |
|---|---|
cmn.tb_hnsvr_m | 홈넷서버 마스터. 홈넷사 client_id·secret, 단지, 연동상태, 삭제여부, 홈넷서버 주소 |
cmn.tb_hnsvr_lnkg_tkn_d | 발급된 AccessToken |
cmn.tb_cstt_m | 공통 상수. 내부 서버 인증정보와 APW 주소를 겸함 |
cmn.tb_nsba_dvc_m | 층간소음알리미 기기(MAC = client_id) |
cmn.tb_usr_m / cmn.tb_hsh_m | 입주민 사용자 / 세대 |
cmn.tb_ptnr_m | 가전사 파트너. client_id, 시크릿, redir_uri, 사용여부 |
cmn.tb_oauth_m | 가전사 연동 상태. 리프레시 토큰, code, 삼성 installedAppId |
alog.tb_oauth_ctf_l | 인증 요청·응답 로그 |
알려진 이슈
- 비활성 코드가 많음. 토큰 엔드포인트 관련 클래스 3개가 파일 전체 주석 처리됨
- 비활성화한 잔재 설정 파일에 평문 DB 계정과 jasypt 키가 남아 있음
- 테스트용 엔드포인트(
/api/uma/test)가 살아 있고 하드코딩된 개발 주소로 리다이렉트함. 운영에서 제거 권고 - 로그인 화면을 오래 열어둔 뒤 제출하면 세션 만료로 서버 오류(500)가 날 수 있음(세션 600초)
- 토큰 응답의
expires_in이 3600으로 하드코딩되어 있어 설정값을 바꿔도 응답은 그대로 나감 - 인증 로깅 필터가 로그 행 번호를 인스턴스 필드로 들고 있어 동시 요청 시 응답 로그가 엉뚱한 행에 기록될 수 있음
- client_secret 평문 비교·평문 저장
- 파트너 사용여부(
us_yn)를 검사하지 않음 - 리프레시 토큰이 회전하지 않음
- API 버전 관리가 없어 재배포 시 기존 연동 시스템이 깨질 위험이 있음(인수인계 지적)
- 기기 이벤트 구독 해지 기능은 제거됨(토큰이 만료되면 해지 요청이 올 수 없다는 이유). 대신 공개노트/개발/모듈/SCW 스케줄러 서버의 구독 해지 스케줄러가 처리함
확인 필요
확인 필요
- 홈넷사 AccessToken 유효기간이 연동규격서 값과 같은지(위 “토큰 종류” 콜아웃 참고)
- 개발 프로필 리프레시 토큰 유효기간이 오타인지
- 인증 로깅 필터의 동시성 문제가 실제 운영에서 로그 꼬임을 일으킨 적이 있는지
/api/ccg/tokencheck가 Apache에서 외부로 노출되지 않는지(웹서버 설정 파일이 저장소에 없음)- 층간소음알리미(
fns-) 연동이 실제 운영에 올라갔는지. 인수인계(2024-06)에는 “추가 예상”으로만 적혀 있음- 삼성
installedAppId를 실제로 소비하는 곳. OAW 안에서는 저장만 하고 읽지 않음
관련
공개노트/개발/시스템 구성 공개노트/개발/모듈/APW 연계 서버 공개노트/개발/모듈/MAW 앱 API 서버 공개노트/개발/모듈/SCW 스케줄러 서버 공개노트/기능/홈넷 서버 연동 공개노트/기능/로그인과 세대 승인 공개노트/기능/우리집제어 기본매뉴얼/운영/홈넷 서버 연동 (인증서 발급)