로그아웃할 곳을 찾기 전에 세션을 지우면 안 된다

앱의 세션을 지워도 외부 SSO 세션은 남을 수 있다. LMS 카탈로그의 로그아웃을 거쳐야 하는 경로에서는 그 주소를 조회할 때 아직 로그인 세션이 필요하다. 로컬 로그아웃을 먼저 마치면 다음 이동에 필요한 정보를 잃는다.

AI Commons는 카탈로그를 경유하는 흐름을 도입한 뒤 주소 검증과 테스트를 보강했다. 클라이언트의 순서는 다음과 같다.

  1. 카탈로그 로그아웃 주소 조회

    현재 세션으로 조회한다. 조회 오류는 null로 바꿔 대체 경로를 선택한다.

  2. 앱 로그아웃 요청

    서버에 세션·쿠키 삭제를 요청한 뒤 다른 탭에 로그아웃을 알린다.

  3. 클라이언트 상태 정리와 이동

    인증 관련 저장 값과 조회 캐시를 지운다. 카탈로그 주소가 있으면 return_url을 붙여 이동하고, 없으면 설정한 LMS 주소로 이동한다. 이후 운영자 보기 값도 함께 정리하도록 보완했다.

동작을 추가한 비용은 세션이 살아 있는 동안 외부 주소 조회를 한 번 더 기다리는 것이다. 필요한 정보를 먼저 확보하는 순서는 지키지만, 이 훅에 별도의 제한 시간 타이머를 두지는 않는다.

HTTPS 검사와 목적지 허용 목록은 다르다

후속 변경에서는 카탈로그가 반환한 주소를 파싱하고 HTTPS 스킴인지 확인하도록 보강했다. 실제 조건은 작다.

const isSafeHttps = (url: string) => {
  try {
    return new URL(url).protocol === "https:";
  } catch {
    return false;
  }
};

누락된 주소, 파싱할 수 없는 문자열, http:나 javascript: 주소는 로그아웃 목적지로 반환하지 않는다. 이 검사는 호스트 허용 목록을 확인하지 않으므로 파싱 가능한 다른 HTTPS 호스트까지 차단하지는 않는다. 또한 원래 문자열 뒤에 /logout을 붙이는 구현이다. 모든 URL 경로와 쿼리를 일반적으로 정규화하는 로직으로 읽을 수는 없다.

화면에서 떠난 것만으로 로그아웃 성공을 판단하지 않는다

앱 로그아웃 POST가 실패해도 클라이언트 정리와 이동은 진행한다. 사용자가 이전 계정의 캐시와 운영자 보기 상태에 머물지 않도록 하는 정책이다. 하지만 요청 실패 뒤 이동했다는 사실은 앱 서버나 외부 SSO의 세션 삭제를 증명하지 않는다. 카탈로그 조회 실패로 LMS에 직접 이동하는 경로도 외부 세션 종료의 확인은 아니다.

초기 서버 테스트는 주소 조회와 null·오류 처리를 검사한다. 이후 비HTTPS·잘못된 주소의 거부와 클라이언트 훅 테스트를 보강했다. 훅 테스트는 카탈로그 경유와 조회 오류의 대체 이동, POST 실패 뒤 정리, 탭 알림과 진행 상태를 검사하며, 이동은 실제 LMS 브라우저 실행 대신 location 설정을 감시한다. 이 검사는 외부 SSO의 종료 결과까지 포함하지 않는다.