인증 이야기

저는 시스템 디자인을 좋아합니다. 사용자를 위해 소프트웨어를 훌륭하게 만드는 작은 결정들에 대해 고민하는 것을 좋아합니다.

엔지니어로서 저는 보안을 중요하게 생각합니다. 소프트웨어가 안전하지 않거나 공격으로 인해 금전적 손실이 발생한다면 아무런 쓸모가 없습니다. 저는 언제나 제대로 작동하는 제품을 만들고 싶습니다.

최근에 한 AI 스타트업의 인증 작업을 진행했습니다. 프론트엔드에는 Next.js를 사용했습니다. Next.js는 프론트엔드와 백엔드를 하나의 코드베이스로 통합하기 때문에 소규모 팀에 매우 적합합니다.

이번 프로젝트에서 저는 브라우저에 인증 토큰을 어떻게 저장하고 보호할지에 집중했습니다. 그 해결책은 쿠키, 그중에서도 특히 HttpOnly 쿠키였습니다.

왜 Local Storage 대신 쿠키를 사용할까요?

Local Storage는 사용하기 쉽지만 위험 요소가 있습니다. JavaScript가 이를 읽을 수 있기 때문입니다. 이로 인해 교차 사이트 스크립팅(XSS) 공격에 취약해집니다. 악성 스크립트가 사이트에서 실행되면 사용자의 토큰을 훔칠 수 있습니다.

쿠키는 이 문제를 해결합니다. 쿠키에 HttpOnly 플래그를 추가할 수 있는데, 이는 브라우저에 "이 쿠키는 HTTP 요청을 통해서만 전송하세요. JavaScript가 접근하지 못하게 하세요"라고 지시하는 것과 같습니다.

공격자가 JavaScript를 사용하여 쿠키를 읽으려 해도 아무것도 볼 수 없습니다. 쿠키는 공격자에게 보이지 않지만, 브라우저는 여전히 서버로 쿠키를 자동으로 전송합니다.

쿠키를 더욱 안전하게 만들기 위해 저는 두 가지 플래그를 더 사용합니다:

• Secure: 쿠키가 HTTPS를 통해서만 전송되도록 보장합니다. • SameSite=Lax: 교차 사이트 요청 위조(CSRF) 공격을 방지하는 데 도움이 됩니다.

Next.js로 이를 구현한 방법:

백엔드(FastAPI)를 브라우저로부터 숨기고 싶었습니다. 그래서 Next.js를 프록시로 사용하여 서버 간(server-to-server) 설정을 구축했습니다.

  1. 사용자가 Next.js Server Action을 통해 로그인합니다.
  2. Server Action이 FastAPI로 인증 정보를 보냅니다.
  3. FastAPI가 Next.js 서버로 토큰을 반환합니다.
  4. Next.js 서버가 해당 토큰을 HttpOnly 쿠키에 기록합니다.
  5. 브라우저는 쿠키를 저장하지만 읽을 수는 없습니다.

사용자가 데이터가 필요할 때, Next.js 서버가 쿠키를 읽어 백엔드와 통신합니다. 민감한 토큰은 브라우저의 JavaScript 환경에 절대 노출되지 않습니다.

이 설정을 통해 백엔드를 격리하고 사용자를 더 안전하게 보호할 수 있습니다.

여러분은 Next.js 프로젝트에서 인증을 어떻게 처리하시나요? 여러분의 방식이 궁금합니다.

출처: https://dev.to/zikthemaker/an-auth-story-42hf