AI는 "되는" 로그인을 만든다, "안전한" 로그인이 아니라
AI 코딩 도구에게 "회원가입, 로그인 기능 만들어줘"라고 하면 동작하는 코드가 나온다. JWT 토큰도 발급하고, 미들웨어도 붙여준다. 하지만 보안 관점에서 보면 구멍이 뚫린 경우가 대부분이다.
보안 진단 실무에서 바이브코딩으로 만든 서비스 50개를 점검한 결과, JWT 관련 취약점이 없는 서비스는 단 3개였다. 나머지 47개에서 아래 5가지 실수가 반복적으로 발견됐다.
실수 1: 토큰 만료 시간 없음
# AI가 자주 생성하는 코드
token = jwt.encode({"user_id": user.id}, SECRET_KEY, algorithm="HS256")
# 문제: 만료 시간(exp)이 없다
# 이 토큰은 영원히 유효하다. 한 번 탈취되면 끝.
수정:
from datetime import datetime, timedelta
token = jwt.encode({
"user_id": user.id,
"exp": datetime.utcnow() + timedelta(hours=1), # 1시간 후 만료
"iat": datetime.utcnow(), # 발급 시각
}, SECRET_KEY, algorithm="HS256")
액세스 토큰은 15분~1시간, 리프레시 토큰은 7~14일이 적절하다.
실수 2: 시크릿 키가 "secret"
# AI가 예시용으로 넣은 키가 그대로 배포됨
SECRET_KEY = "secret"
# 또는
SECRET_KEY = "your-secret-key"
# 또는
SECRET_KEY = "mysecretkey123"
이런 키는 사전 공격으로 1초 만에 크랙된다. jwt.io에서 토큰을 붙여넣고 "secret"을 입력하면 서명이 통과되는지 바로 확인할 수 있다.
수정:
import secrets
SECRET_KEY = secrets.token_hex(32) # 64자 랜덤 문자열
# 이 값을 .env에 저장하고 환경변수로 읽는다
실수 3: 알고리즘 검증 안 함
# 위험 — 알고리즘을 지정하지 않고 디코딩
payload = jwt.decode(token, SECRET_KEY)
# 공격자가 토큰 헤더의 alg를 "none"으로 바꾸면
# 서명 없이 토큰이 통과된다 (일명 "alg: none" 공격)
수정:
# 안전 — 허용할 알고리즘을 명시
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
algorithms 파라미터를 반드시 지정한다. 이것 하나로 alg:none 공격과 RS256/HS256 혼동 공격을 막는다.
실수 4: 토큰을 localStorage에 저장
// AI가 자주 생성하는 프론트엔드 코드
localStorage.setItem('token', response.data.token);
// 문제: XSS 취약점이 하나라도 있으면 토큰이 탈취된다
// localStorage는 JavaScript로 접근 가능하기 때문
수정:
// 서버에서 HttpOnly 쿠키로 토큰 전달
res.cookie('token', token, {
httpOnly: true, // JavaScript 접근 차단
secure: true, // HTTPS에서만 전송
sameSite: 'strict', // CSRF 방지
maxAge: 3600000, // 1시간
});
HttpOnly 쿠키에 저장하면 XSS로 토큰을 가져갈 수 없다.
실수 5: 토큰 폐기(로그아웃) 미구현
AI가 만든 로그인에 로그아웃이 없거나, 프론트에서 토큰만 삭제하는 경우가 많다.
// AI의 로그아웃 — 클라이언트에서만 삭제
function logout() {
localStorage.removeItem('token');
// 하지만 토큰 자체는 여전히 유효하다
// 탈취된 토큰이 있다면 계속 쓸 수 있다
}
수정 방법:
- 짧은 만료 + 리프레시 토큰: 액세스 토큰 15분 만료, 리프레시 토큰으로 갱신. 로그아웃 시 리프레시 토큰을 DB에서 삭제.
- 토큰 블랙리스트: Redis에 로그아웃된 토큰 ID(jti)를 저장. 매 요청마다 블랙리스트 확인.
5가지 전부 해당되는지 궁금하다면
CodeScan은 배포된 웹사이트에서 인증 헤더 설정, 쿠키 보안 속성, 에러 응답 패턴까지 자동으로 점검한다. JWT 구현이 제대로 됐는지 외부에서 확인할 수 있는 가장 빠른 방법이다.