Access Token과 Refresh Token을 어떻게 전달하고 클라이언트는 어디에 저장할까?
서버와 클라이언트 각각의 입장에서 적어보겠습니다!
[서버] 각 토큰을 어떻게 전달해야 할까?
Response Body
{
"accessToken": "access_token_here",
"refreshToken": "refresh_token_here"
}
장점 :
- 간단하고 구현이 쉬움
- 클라이언트 측에서 유연하게 처리 가능
단점 :
- 토큰이 노출될 가능성이 높음 (ex. 웹 콘솔 로그에 토큰이 남을 수 있음)
- CSRF 공격에 취약
Header
HTTP/1.1 200 OK
Content-Type: application/json
Authorization: Bearer access_token_here
Refresh-Token: refresh_token_here
장점 :
- response body를 깨끗하게 유지 가능
- 보안 헤더를 통해 전송 가능, 보안이 향상됨
단점 :
- 일부 브라우저/클라이언트에서 헤더 크기 제한이 있을 수 있음
- 클라이언트 측에서 헤더 처리가 필요함
Cookie
Set-Cookie: accessToken=access_token_here; HttpOnly; Secure; SameSite=Strict
Set-Cookie: refreshToken=refresh_token_here; HttpOnly; Secure; SameSite=Strict
장점 :
- 쿠키의 HttpOnly, Secure, SameSite 속성을 사용해 보안을 강화할 수 있음
- 브라우저가 자동으로 쿠키를 관리, 전송함
단점 :
- 쿠키 사용 시, XSS 공격에 주의해야 함
- CSRF 공격에 취약할 수 있음 (SameSite 속성으로 완화 가능)
결론
액세스 토큰은 HTTP 헤더에 포함 : 요청 시마다 Authorization 헤더에 Bearer 토큰을 포함하여 전송. 보안이 강화되고 쿠키와의 충돌을 피할 수 있다.
리프레시 토큰은 HttpOnly 쿠키에 포함 : HttpOnly, Secure, SameStie 속성을 사용하여 리프레시 토큰을 쿠키에 저장. 자바스크립트에서 토큰에 접근할 수 없게 되어 XSS 공격을 완화할 수 있다.
[클라이언트] 토큰을 어디에 저장해야 할까?
Access Token의 저장위치
access token은 5분에서 30분으로 탈취의 위험을 고려하여 매우 짧게 설정한다. 그럼에도 불구하고 탈취의 위험이 존재하므로 저장 위치에 대한 고려가 필요하다.
Local Storage
장점 : 만료날짜 없이 데이터를 저장할 수 있어 브라우저를 닫거나 다시 열어도 데이터를 사용할 수 있다.
단점 : js를 통해 localStorage에 접근하면 바로 토큰에 접근할 수 있다. 따라서, 공격자가 악의적인 js코드를 피해자 웹 브라우저에서 실행시키는 XSS 공격을 통해 해커의 악성 스크립트에 노출되어 토크느 탈취가 가능하다.
XSS(Cross Site Scripting) 이란 게시판이나 웹 메일 등에 자바 스크립트와 같은 스크립트 코드를 삽입 해 개발자가 고려하지 않은 기능이 작동하게 하는 공격. URL 에 스크립트를 포함할 수 있으며, 게시물에 삽입할 수도 있다. 이를 통해 XSS 공격 용도의 해당 페이지를 이용하는 사용자의 브라우저에 저장된 파일들을 탈취할 수 있다. 또한 시스템 권한이나 악성코드 다운로드 등의 공격도 가능하다. 거짓 페이지를 노출하여 개인정보 유출문제도 가능
XSS 공격은 IPS, IDS, 방화벽 등으로 방지가 안돼 문자 필터링 방식으로 공격을 막는다. script 문자 필터링(사용자의 모든 입력값에 대해 서버측에서 필터링)을 하여 검증한다. 주로 스크립트를 실행하기 위한 특수문자 필터링(<,>,",')을 한다.
Cookie
장점 :
- 쿠키 설정 시 httpOnly 값을 활성화 하면 네트워크 통신 상에서만 토큰 정보가 들어있는 쿠키가 붙게 되어 자바스크립트로 토큰 값에 접근하는 것이 불가능해져 XSS 문제를 해결할 수 있다.
- Secure 옵션을 통해 쿠키가 HTTPS로만 전송되게 하여 보안 수준을 높일 수 있다.
단점 :
- CSRF 공격의 위험이 있다.
- 유저도 모르게 계정 탈퇴, 댓글 포스트 자동 작성, 회원정보 변경
- 해결방법 : Same Origin 정책으로 자바스크립트에서 타 도메인의 쿠키 값을 확인, 수정하지 못한다. 이를 활용한다. 즉 Cookie 설정에 SameSite 설정을한다.(단 SameSite 속성을 쓰기 위해서 Secure 설정이 적용되어야 한다)
- 쿠키는 한정된 도메인에서만 사용된다. (모바일 불가)
- 해결방법 : 토큰이 필요할 시 현재 쿠키에 있는 토큰을 사용하여 새 토큰을 문자열로 받아오는 API 구현
CSRF(Cross-Site Request Forgery) 공격은 사용자가 자신의 의지와 무관하게 공격자가 의도한 행위(수정,삭제,등록등)을 특정 웹사이트에 요청하게 하는 공격을 말한다. 즉 자신도 모르게 서버를 공격하는 경우이다.(계정 정보를 탈취하는 것이 아니라 스크립트를 통해 사이트 외부에서 사이트의 API 를 사용하는 것처럼 모방 혹은 사이트 내부에서 스크립트가 실행되어 원하지 않는 작업 수행)
즉 서버에서 쿠키 설정을 http only, samesite, secure 을 모두 설정하고 CORS 설정으로 해당 특정 도메인만 허용하여 보안적으로 안정화시킨다면 프론트서버에서 따로 토큰 관리할 필요없이 서버에서만의 토큰 관리를 통해 인증인가를 처리할 수 있게된다.
Refresh Token의 저장위치
refresh token은 보통 긴 시간을 설정하기 때문에 보안적으로 매우 중요하다. 따라서 서버에서 관리해야 한다.
DataBase (MySQL, H2, ..)
Redis
장점 : 빠르다. 레디스는 주기억장치(ex. RAM)에 데이터를 저장하므로 db보다 성능이 좋다.
단점 : 전원이 꺼지면 데이터가 날아간다.
따라서 자주쓰고 날아가도 괜찮은 정보를 redis에 저장하면 성능적으로 좋다.
참고