TIL

Socket.IO에서 JWT 만료 시 아예 연결을 차단하는 방법

하얀잔디 2025. 9. 5. 20:03

 

 

실시간 웹 애플리케이션을 개발하다 보면, Socket.IO 연결에서 JWT 토큰 관리가 까다로운 경우가 많습니다.

 

특히 토큰이 만료되었을 때 기존 연결을 어떻게 처리할지, 새로운 연결 시도를 어떻게 막을지 고민이 되죠.

 

핸드셰이크 단계에서부터 JWT를 검증해서 유효하지 않은 토큰으로는 아예 연결 자체가 성립되지 않도록 하는 방법을 공유합니다.

 

운영과 개발 서버에 이 방식을 적용한 경험을 바탕으로 작성했습니다.

 

 

해결책: io.use()로 핸드셰이크 단계에서 차단

Socket.IO의 io.use()는 네임스페이스 미들웨어로, 모든 소켓 연결 시도마다 가장 먼저 실행됩니다. 여기서 토큰 검증을 하고, 실패하면 next(new Error(...))로 연결 자체를 거부하는 것이 핵심입니다.

이렇게 하면:

  • 연결이 성립하기도 전에 컷!!
  • connection 리스너가 아예 실행되지 않음
  • 서버 리소스 점유, 채널 조인, 방 진입 등의 후속 로직이 전혀 실행되지 않음
  • 실패 사유는 클라이언트의 connect_error 이벤트로 전달

 

import axios from 'axios';
import { Server } from 'socket.io';

const io = new Server(httpServer, {
  // CORS, path 등 환경에 맞게 설정
});

io.use(async (socket, next) => {
  // ⚠️ 토큰은 query가 아닌 auth로 받는 것이 안전하고 표준적입니다
  const { user_id, tenant_code, token } = socket.handshake.auth || {};

  // 디버깅용 메타데이터 저장
  socket.data.meta = { user_id, tenant_code };

  if (!token || !user_id || !tenant_code) {
    return next(new Error('Missing credentials'));
  }

  try {
    const res = await axios.post(
      `${process.env.API_HOST}/v3/token/validation`,
      { user_id, tenant_code, token },
      { timeout: 3000 } // 타임아웃 필수!
    );

    if (res.status !== 200) {
      return next(new Error('Token validation failed'));
    }

    // 검증 통과
    return next();
  } catch (err) {
    // 외부 API 오류나 타임아웃도 "연결 거부"로 일관 처리
    return next(new Error('Auth service unreachable'));
  }
});

// 여기까지 도달했다면 "검증을 통과한 연결"만 들어옵니다
io.on('connection', (socket) => {
  const { user_id, tenant_code } = socket.data.meta || {};
  console.info('[Socket] Connected:', { user_id, tenant_code, id: socket.id });

  // 이후 비즈니스 로직...
});

 

중요한 포인트들

  • next(): 검증 통과, 연결 허용
  • next(new Error('...')): 즉시 거부, connection 이벤트 실행 안됨
  • throw하지 말고 return next(err)로 명확히 종료
  • 인증 실패와 검증 서비스 장애를 같은 인터페이스로 클라이언트에 전달하면, 클라이언트에서 재시도/로그인 갱신 로직을 일관되게 처리할 수 있습니다

'TIL' 카테고리의 다른 글

Nginx 설정 팁  (0) 2025.09.11
Socket Admin UI 페이지 보는법  (0) 2025.09.11
Docker 로그와 PM2, Logger, 색상 출력 – 실무에서 겪은 이야기  (3) 2025.08.15
postgres DB 이원화  (3) 2025.08.10
Ingress Controller rewrite 안될때  (2) 2025.07.30