역할

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/tokenPIW
  • 수신 전용 서버임. 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)
DBPostgreSQL smahdb, Spring Data JPA
세션Redis(Spring Session, Sentinel). 세션 600초
JWTjjwt, 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를 부름. 홈넷사 입장의 연동 절차는 공개노트/기능/홈넷 서버 연동.

  1. Basic 인증 또는 폼 파라미터로 client_id·client_secret, 본문에 grant_type=client_credentials(둘 다 허용)
  2. 요청을 alog.tb_oauth_ctf_l에 먼저 기록함
  3. 클라이언트를 조회해 인증함
  4. 기존 토큰 행을 지우고 새 토큰을 cmn.tb_hnsvr_lnkg_tkn_d에 넣음. 즉 클라이언트당 유효 토큰은 1개이고 재발급하면 이전 토큰은 즉시 무효가 됨
  5. 표준 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_idclient_secret
내부 리소스 서버(APW)client_id가 내부 상수 ID와 같음cmn.tb_cstt_mcstt_idcstt_vl
층간소음알리미 기기client_id가 fns-로 시작cmn.tb_nsba_dvc_mfns- + MAC기기 ID
홈넷사 홈넷서버그 외 전부cmn.tb_hnsvr_mhnsvr_idhnsvr_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_dAPW 호출
client_credentials RefreshToken발급 안 함
가전사 AccessToken삼성 sse, LG lgeJWT1시간저장 안 함(무상태 검증)PIW 호출
가전사 RefreshToken삼성 sse, LG lgeJWT2주cmn.tb_oauth_m/api/uma/token 재발급
ApiKey내부 WAS ↔ APW·OAW문자열만료 없음cmn.tb_cstt_m헤더 인증
앱 Access/Refresh입주민 앱JWT15일 / 30일Refresh만 cmn.tb_refsh_tkn_mMAW 호출. 공개노트/개발/모듈/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
20104client_secret 불일치
20107code를 찾을 수 없음(이미 사용했거나 만료)
20111지원하지 않는 grant_type
20114등록된 redirect_uri와 불일치
20117code가 아닌 response_type
20123저장된 refresh_token과 불일치
20124 / 20125refresh_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인증 요청·응답 로그

알려진 이슈

  1. 비활성 코드가 많음. 토큰 엔드포인트 관련 클래스 3개가 파일 전체 주석 처리됨
  2. 비활성화한 잔재 설정 파일에 평문 DB 계정과 jasypt 키가 남아 있음
  3. 테스트용 엔드포인트(/api/uma/test)가 살아 있고 하드코딩된 개발 주소로 리다이렉트함. 운영에서 제거 권고
  4. 로그인 화면을 오래 열어둔 뒤 제출하면 세션 만료로 서버 오류(500)가 날 수 있음(세션 600초)
  5. 토큰 응답의 expires_in3600으로 하드코딩되어 있어 설정값을 바꿔도 응답은 그대로 나감
  6. 인증 로깅 필터가 로그 행 번호를 인스턴스 필드로 들고 있어 동시 요청 시 응답 로그가 엉뚱한 행에 기록될 수 있음
  7. client_secret 평문 비교·평문 저장
  8. 파트너 사용여부(us_yn)를 검사하지 않음
  9. 리프레시 토큰이 회전하지 않음
  10. API 버전 관리가 없어 재배포 시 기존 연동 시스템이 깨질 위험이 있음(인수인계 지적)
  11. 기기 이벤트 구독 해지 기능은 제거됨(토큰이 만료되면 해지 요청이 올 수 없다는 이유). 대신 공개노트/개발/모듈/SCW 스케줄러 서버의 구독 해지 스케줄러가 처리함

확인 필요

확인 필요

  • 홈넷사 AccessToken 유효기간이 연동규격서 값과 같은지(위 “토큰 종류” 콜아웃 참고)
  • 개발 프로필 리프레시 토큰 유효기간이 오타인지
  • 인증 로깅 필터의 동시성 문제가 실제 운영에서 로그 꼬임을 일으킨 적이 있는지
  • /api/ccg/tokencheck가 Apache에서 외부로 노출되지 않는지(웹서버 설정 파일이 저장소에 없음)
  • 층간소음알리미(fns-) 연동이 실제 운영에 올라갔는지. 인수인계(2024-06)에는 “추가 예상”으로만 적혀 있음
  • 삼성 installedAppId를 실제로 소비하는 곳. OAW 안에서는 저장만 하고 읽지 않음

관련

공개노트/개발/시스템 구성 공개노트/개발/모듈/APW 연계 서버 공개노트/개발/모듈/MAW 앱 API 서버 공개노트/개발/모듈/SCW 스케줄러 서버 공개노트/기능/홈넷 서버 연동 공개노트/기능/로그인과 세대 승인 공개노트/기능/우리집제어 기본매뉴얼/운영/홈넷 서버 연동 (인증서 발급)