Skip to content

웹소켓 STOMP 쿠키 기반 인증 도입 및 SEND 커맨드 실시간 검증#231

Open
ckdals4600 wants to merge 3 commits into
mainfrom
feat/#223-websocket-auth-improvement
Open

웹소켓 STOMP 쿠키 기반 인증 도입 및 SEND 커맨드 실시간 검증#231
ckdals4600 wants to merge 3 commits into
mainfrom
feat/#223-websocket-auth-improvement

Conversation

@ckdals4600
Copy link
Copy Markdown
Contributor

@ckdals4600 ckdals4600 commented May 16, 2026

관련 이슈

PR 설명

  • 기존 웹소켓 통신은 연결(CONNECT) 시점에만 헤더를 통해 인증을 수행하여, 연결 이후 토큰이 만료되거나 비정상적인 SEND 요청이 들어올 때 이를 방어하지 못하는 보안 취약점이 있었습니다.
  • 이를 해결하기 위해 HTTP Handshake 과정에서 쿠키를 통해 토큰을 추출하는 로직을 추가하고, 메시지 발행(SEND) 시점마다 토큰의 유효성을 실시간으로 검증하도록 인증 아키텍처를 크게 개선했습니다.

작업 내용

1. 웹소켓 엔드포인트 보안 정책 강화 (SecurityConstants)

  • 기존 PERMIT_URLS에 포함되어 무조건 허용되던 웹소켓 경로(/ws/chat/**, /ws/link/**)를 제거하여, 기본적인 Spring Security 인증 정책의 보호를 받도록 변경했습니다.

2. 쿠키 기반 Handshake 인터셉터 추가 (WebSocketConfig)

  • 웹소켓 연결 최초 진입점인 HTTP Handshake 단계에서 동작하는 HandshakeInterceptor를 추가했습니다.
  • 클라이언트의 요청 쿠키에서 accessToken을 추출하여 STOMP 세션 정보(attributes)에 저장해 둠으로써, 이후 TCP 통신 단계에서도 토큰 정보에 접근할 수 있도록 하이브리드 인증 기반을 마련했습니다.

3. SEND 커맨드 JWT 실시간 검증 (StompHandler)

  • ChannelInterceptorpreSend 로직을 개선하여, CONNECT뿐만 아니라 SEND 커맨드 유입 시에도 인증을 수행하도록 분기를 확장했습니다.
  • 세션 속성에 저장된 쿠키 토큰(또는 헤더 토큰)을 가져와 만료 여부를 실시간으로 체크(validateAccessToken)하며, 만료되거나 유효하지 않은 토큰으로 메시지를 전송하려 할 경우 MessagingException을 발생시켜 원천 차단합니다.

@ckdals4600 ckdals4600 self-assigned this May 16, 2026
@ckdals4600 ckdals4600 linked an issue May 16, 2026 that may be closed by this pull request
@ckdals4600 ckdals4600 requested review from Goder-0 and minibr May 16, 2026 12:23
@ckdals4600 ckdals4600 force-pushed the feat/#223-websocket-auth-improvement branch from 7ebc66e to 33b06d1 Compare May 20, 2026 10:53
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 20, 2026

📊 코드 커버리지 리포트

Overall Project 94.21% 🍏

There is no coverage information present for the Files changed

Comment on lines +44 to +56
if (sessionAttributes != null && sessionAttributes.containsKey("accessToken")) {
token = (String)sessionAttributes.get("accessToken");
}

if (jwtTokenProvider.validateAccessToken(token)) {
Authentication authentication = jwtTokenProvider.getAuthentication(token);
accessor.setUser(authentication);
if (token == null && StompCommand.CONNECT.equals(command)) {
String authorizationHeader = accessor.getFirstNativeHeader(JwtKeys.Headers.AUTHORIZATION);

if (authorizationHeader != null && authorizationHeader.startsWith(JwtKeys.Headers.BEARER_PREFIX)) {
token = authorizationHeader.substring(JwtKeys.Headers.BEARER_PREFIX.length());

if (sessionAttributes != null) {
sessionAttributes.put("accessToken", token);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 의도를 한번 확인해보고 싶습니다.

이전 JWT 인증 쪽 논의에서는 Authorization 헤더를 우선 보고, 필요할 때 쿠키를 fallback으로 사용하는 흐름이 있었던 것으로 기억하는데요. 현재 WebSocket 쪽 구현은 세션/쿠키에 저장된 accessToken이 있으면 그 값을 먼저 사용하고, 없을 때만 CONNECT 헤더를 보는 구조라서 우선순위가 조금 달라 보였습니다.

그래서 브라우저에 남아 있는 쿠키 토큰이 오래된 상태이고, 클라이언트가 더 최신 토큰을 헤더로 보내는 경우에는 헤더 값이 반영되지 못할 수도 있을 것 같아서요.

혹시 쿠키 값을 항상 우선하도록 의도하신 걸까요? 만약 쿠키/헤더 하이브리드 지원을 생각하신 거라면, CONNECT 시점에는 헤더를 우선 적용하고 그 값을 세션에 갱신하는 쪽도 더 자연스러울 수 있을 것 같아 의견 여쭙습니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일반 API와 달리, 소켓 통신 인증에서는 쿠키에 저장된 토큰을 최우선으로 사용하기로 결정했기 때문에 세션/쿠키를 먼저 확인하도록 구현했습니다.
CONNECT 시점의 헤더 확인 로직은 정상적인 흐름이라기보다는, 쿠키 세팅이 불가피하게 누락되는 만약의 경우를 대비한 방어 로직으로 남겨둔 것입니다.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

설명 주신 의도는 이해했습니다. 웹소켓에서는 쿠키/세션을 우선하고, 헤더는 예외 상황 fallback으로 두신 거군요.

그 기준으로 보면 현재 통합 테스트는 Authorization 헤더만 사용해서 연결하고 있어서, 실제 주 경로인 쿠키 기반 handshake/auth 흐름을 직접 검증하고 있지는 않은 것 같습니다. 혹시 가능하다면 accessToken 쿠키를 실어서 연결하는 케이스도 하나 추가해두면, 이번 PR의 핵심 동작을 더 정확하게 보장할 수 있을 것 같은데 어떻게 생각하시나요?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 의견 감사합니다! 짚어주신 대로 현재 테스트가 Fallback 경로인 Authorization 헤더에만 맞춰져 있어서, 주 경로인 쿠키 기반의 인증 흐름에 대한 검증이 누락되어 있었네요. 핵심 동작을 더 확실히 보장할 수 있도록 accessToken 쿠키를 사용하는 테스트 케이스를 바로 추가하겠습니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Goder-0 쿠키 기반 인증 방식으로 테스트 코드 수정완료하였습니다. 확인부탁드립니다

@Goder-0
Copy link
Copy Markdown
Contributor

Goder-0 commented May 20, 2026

PR에 이슈 번호 연결해주세요.

@ckdals4600 ckdals4600 requested a review from Goder-0 May 22, 2026 14:37
- [WebSocketConfig] HTTP Handshake 시 accessToken 쿠키를 웹소켓 세션으로 복사하는 HandshakeInterceptor 추가
- [StompHandler] STOMP CONNECT 시 세션(쿠키) 토큰과 헤더 토큰을 모두 지원하도록 하이브리드 인증 로직 구현
Copy link
Copy Markdown
Contributor

@Goder-0 Goder-0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

작업이 완료되었다고 판단되어 승인합니다.
한편, 프론트 대응작업으로 Team-SoFa/linkiving#518 이슈를 생성하였습니다. 해당 이슈를 해결하는 PR이 올라온 이후 머지가 되는것이 좋을 것 같습니다.

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.

WebSocket 인증 방식 개선

2 participants