MQTT에 JWT로 사용자 인증 적용하기
브로커와 클라이언트 사이 인증에 JWT를 도입하는 개념부터 토큰 발행, 브로커 검증, 클라이언트 연동 예제와 보안 고려사항을 포함한 실무 자료
목차
개요
IoT 환경에서 MQTT는 경량 메시지 전송 프로토콜로 널리 사용된다. 기본 인증만으로는 확장성과 보안성에서 한계가 있으므로 JWT(JSON Web Token)를 이용한 토큰 기반 인증이 유용하다. 이 글은 JWT의 개념, MQTT에 적용하는 흐름, 서버·클라이언트 예제, 브로커 측 검증과 보안 고려사항을 설명한다.
JWT 기본 개념
JWT는 헤더(header), 페이로드(payload), 서명(signature)으로 구성된다. 페이로드에는 사용자 식별자(sub), 만료(exp) 등 클레임을 포함한다. 서명은 비밀키 또는 공개/비밀 키쌍으로 생성되어 위변조 방지와 발급자 검증에 사용된다.
토큰 구성
- 헤더: 알고리즘과 타입 정보
- 페이로드: 사용자 정보와 클레임
- 서명: 토큰 무결성 검증용
MQTT와 JWT 인증 흐름
일반적인 흐름은 다음과 같다.
- 클라이언트가 인증서버에 자격 증명으로 JWT 발급 요청
- 인증서버가 사용자 검증 후 JWT 발급
- 클라이언트가 MQTT 접속 시 토큰을 패스워드 또는 사용자 이름으로 전달
- 브로커가 토큰을 검증하고 허가 여부를 판단
전달 방식 예시
브로커 별로 권장 방식이 다르나, 일반적으로 MQTT CONNECT 패킷의 password 필드에 JWT를 넣는 방식이 많이 쓰인다. username 필드에는 클라이언트 아이디나 식별자를 전달할 수 있다.
서버에서 JWT 발급 예제 (Node.js)
간단한 발급 과정의 예시 코드는 아래와 같다. jsonwebtoken 패키지를 사용한 발급 예제이다.
const jwt = require('jsonwebtoken');
function issueToken(userId) {
const payload = { sub: userId };
const options = { expiresIn: '1h', issuer: 'auth.example.com' };
const secret = process.env.JWT_SECRET;
return jwt.sign(payload, secret, options);
}
// 사용 예
const token = issueToken('device123');
console.log(token);
클라이언트 연결 예제 (mqtt.js)
클라이언트는 발행된 토큰을 CONNECT 시 password에 전달한다. 아래 예제는 mqtt.js를 사용한 연결 코드이다.
const mqtt = require('mqtt');
const token = 'eyJhbGciOi...'; // 서버에서 발급된 JWT
const client = mqtt.connect('mqtts://broker.example.com:8883', {
clientId: 'device123',
username: 'device123',
password: token,
rejectUnauthorized: true
});
client.on('connect', () => {
console.log('connected');
client.subscribe('sensors/temperature');
});
브로커 측 검증
브로커는 CONNECT 수신 시 토큰을 추출하고 서명 및 클레임 유효성을 확인한다. EMQX, VerneMQ 등은 JWT 인증 플러그인을 제공하거나 커스텀 인증 플러그인으로 검증 로직을 추가할 수 있다.
검증 시점 체크 항목
- 서명 검증으로 토큰 무결성 확인
- exp 클레임으로 만료 여부 확인
- iss/aud 등 발급자와 대상 일치 여부 확인
- 토큰의 sub 또는 추가 클레임으로 권한 매핑
EMQX 예시 설정(개념)
EMQX는 JWT 인증 플러그인에서 비밀키를 설정하거나 외부 인증 API를 호출해 검증하는 방식이 가능하다. 아래는 인증 플러그인 구성 예시의 개념적 표현이다.
{
"auth": {
"jwt": {
"secret": "your_jwt_secret",
"issuer": "auth.example.com",
"audience": "mqtt"
}
}
}
권한 부여와 토픽 정책 연결
토큰의 클레임에 역할(role) 또는 허용 토픽 목록을 포함하면 브로커에서 연결 후 토픽 권한을 결정하는 데 유용하다. 예를 들어 role이 sensor이면 읽기/쓰기 권한을 일부 토픽으로 제한하는 방식이다.
보안 고려사항
- 비밀키 관리: 서명 비밀키는 안전한 비밀 관리 시스템에 보관
- 토큰 만료: 짧은 만료 시간을 설정해 탈취 위험 감소
- 재사용 방지: 필요 시 토큰 블랙리스트(로그아웃 또는 키 회전)를 운영
- TLS 사용: 토큰 전송 시 네트워크 도청 방지를 위한 TLS 필수
- 클레임 검증: iss, aud 등 추가 검증으로 올바른 발급자 확인
운영 시 체크리스트
- 토큰 발급 로그와 실패 로그 모니터링
- 토큰 만료 정책과 키 회전 주기 문서화
- 브로커 플러그인 테스트 및 부하 영향 검증
- 클라이언트 라이브러리의 토큰 갱신 전략 수립
마무리
JWT를 MQTT에 적용하면 중앙화된 인증과 확장 가능한 권한 모델을 구성하기 수월하다. 발급·전달·검증의 각 단계에서 보안과 운영성을 고려하면 안정적인 인증 체계를 만들 수 있다. 제공된 예제를 기반으로 환경에 맞춘 설정과 테스트를 권장한다.