HTTP 인증은 '요청을 보낸 주체가 누구인지'를 증명하는 절차입니다. HTTP는 상태가 없는(stateless) 프로토콜이라, 매 요청이 스스로 자신을 증명해야 합니다. 서버가 보호된 리소스에 인증을 요구할 때는 401 Unauthorized와 함께 WWW-Authenticate 헤더로 어떤 인증 방식을 기대하는지 알려 줍니다.
GET /v1/me HTTP/1.1
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api", error="invalid_token"
Basic vs Bearer
가장 기본적인 두 가지 Authorization 방식은 Basic과 Bearer입니다. Basic은 사용자명:비밀번호를 Base64로 인코딩해 보냅니다. 주의할 점은 Base64는 암호화가 아니라 인코딩이라, 누구나 되돌릴 수 있다는 것입니다. 따라서 Basic은 반드시 HTTPS 위에서만 써야 합니다.
GET /v1/me HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==
GET /v1/me HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Bearer는 '이 토큰을 지닌(bearer) 자에게 접근을 허용한다'는 뜻으로, 미리 발급받은 토큰(대개 OAuth 2.0 액세스 토큰이나 JWT)을 그대로 실어 보냅니다. 토큰만 있으면 인증되므로, 토큰이 유출되면 그대로 악용됩니다. 그래서 Bearer 역시 HTTPS가 필수이고, 토큰에는 짧은 만료 시간을 두는 것이 안전합니다.
401 vs 403
실무에서 가장 자주 헷갈리는 구분입니다. 401 Unauthorized는 이름과 달리 '인증(authentication) 실패'를 뜻합니다 — '당신이 누구인지 모르겠으니 자격 증명을 제시하라'. 403 Forbidden은 '인증은 됐고 당신이 누구인지 알지만, 이 작업을 할 권한(authorization)이 없다'는 뜻입니다. 로그인은 됐는데 관리자 전용 페이지에 접근하면 403, 로그인 자체를 안 했거나 토큰이 만료됐으면 401입니다.
토큰/JWT vs 세션/쿠키
인증 상태를 유지하는 방식은 크게 두 계열입니다.
- 세션 + 쿠키(상태 유지형): 서버가 세션을 만들어 저장하고, 클라이언트에는 세션 ID를 쿠키로 내려줍니다. 서버가 상태를 쥐고 있어 즉시 로그아웃·무효화가 쉽지만, 여러 서버로 확장할 때 세션 공유가 필요합니다.
- JWT 등 토큰(무상태형): 사용자 정보(claims)와 서명을 토큰 자체에 담아, 서버는 서명만 검증하면 됩니다. 확장성이 좋고 서버가 세션을 저장할 필요가 없지만, 발급된 토큰을 만료 전에 강제로 무효화하기가 어렵습니다(블랙리스트 등 추가 장치 필요).
쿠키를 쓸 때는 보안 속성이 중요합니다. HttpOnly로 자바스크립트 접근을 막아 XSS로부터 토큰을 보호하고, Secure로 HTTPS에서만 전송하며, SameSite로 CSRF를 완화합니다. Bearer 토큰을 브라우저 localStorage에 두면 XSS에 취약하므로, HttpOnly 쿠키가 더 안전한 선택인 경우가 많습니다.
HTTPS가 필수인 이유
Basic이든 Bearer든, 자격 증명과 토큰은 요청 헤더에 사실상 평문으로 실립니다. HTTPS 없이 보내면 같은 네트워크의 공격자가 이를 그대로 가로채(스니핑) 계정을 탈취할 수 있습니다. 그래서 모든 인증은 예외 없이 TLS(HTTPS) 위에서 이뤄져야 하며, 이것은 선택이 아니라 최소 요건입니다.