클라이언트에서 인증 정보를 보관하는 방법
Json Wep Token의 약자로 웹에서 쓰이는 json토큰이다. 종류는 access token, refresh token 두가지다
보호된 정보에 접근할 수 있는 권한부여에 사용됨
클라이언트가 처음 인증을 받게 될때(로그인), access token, refresh token 둘다 받게 되지만 실제로 권한을 얻는데 사용되는 토큰은 access token이다.
권한을 부여받는 데엔 access token만 있으면 된다. 하지만 토큰이 탈취된다면, 로그인을 해서 여러 나쁜 행위를 할 수 있다. 그래서 access token이 만료기간을 짧게 주고 오랫동안 사용할 수 없도록 한다.
access token이 만료될 때마다 refresh token을 통해 말 그대로 access token을 refresh 한다.
access token은 로그인에 접근할 수 있는 카드키, refresh token은 카드키 재발급 이라고 생각하면 편하다.
3~4. 로그인이 완료되면 Access Token, Refresh Token을 발급. 이때 일반적으로 회원DB에 Refresh Token을 저장해둔다.
6~7. Access Token을 검증하여 이에 맞는 데이터를 보낸다.
10~11. 서버는 Access Token이 만료됨을 확인하고 권한없음을 신호로 보낸다.
** Access Token 만료가 될 때마다 계속 과정 9~11을 거칠 필요는 없다
사용자(프론트엔드)에서 Access Token의 Payload를 통해 유효기간을 알 수 있다. 따라서 프론트엔드 단에서 API 요청 전에 토큰이 만료됐다면 바로 재발급 요청을 할 수도 있다
기존의 Access Token만 있을 때보다 안전하다.
XSS 공격
공격자가 클라이언트 브라우저에 JavaScript를 삽입해 실행하는 공격이다. 공격자가 input 태그를 사용해 JavaScript를 서버로 전송해 서버에서 스크립트를 실행하거나, url에 javascript를 적어 클라이언트에서 스크립트 실행이 가능하다면 공격자가 사이트에 스크립트를 삽입해 XSS 공격을 할 수 있다. 이때 공격자는 javascript를 통해 사이트의 글로벌 변숫값을 가져오거나 그 값을 이용해 사이트인 척 API 콜을 요청할 수도 있다. 공격자의 코드가 내 사이트의 로직인 척 행동할 수 있다는 것
CSRF 공격
공격자가 다른 사이트에서 우리 사이트의 API 콜을 요청해 실행하는 공격이다. API 콜을 요청할 수 있는 클라이언트 도메인이 누구인지 서버에서 통제하고 있지 않다면 CSRF가 가능한데, 이때 공격자가 클라이언트에 저장된 유저 인증정보를 서버에 보낼 수 있다면, 제대로 로그인한 것처럼 유저의 정보를 변경하거나 유저만 가능한 액션들을 수행할 수 있다. 예를 들어 CSRF에 취약한 은행 사이트가 있다면 로그인한 척 계좌 비밀번호를 바꾸거나 송금을 보낼 수 있는 것이다.
1. localStorage 저장 방식
브라우저 저장소에 저장하는 방식, JavaScript 내 글로벌 변수로 읽기/쓰기 접근 가능
👿 : LocalStorage 안에 세션 id, refreshToken 또는 accessToken을 저장해두면 XSS 취약점을 통해 그 안에 담긴 값을 불러오거나, 불러온 값을 이용해 API 콜을 위조할 수 있다.
2. 쿠키 저장 방식
브라우저에 쿠키로 저장되는데, 클라이언트가 HTTP 요청을 보낼 때마다 자동으로 쿠키가 서버에 전송된다. Javascript 내 글로벌 변수로 읽기/쓰기 접근 가능
👿 : 세션 id, refreshToken, accessToken을 저장해두면 XSS 취약점이 있을 때 담긴 값들을 불러오거나, API 콜을 보내면 쿠키에 담긴 값들이 함께 전송되어 로그인한 척 공격을 수행할 수 있다.
👿 : 쿠키에 세션 id나 accessToken을 저장해 인증에 이용하는 구조에 CSRF 취약점이 있다면 인증 정보가 쿠키에 담겨 서버로 보내진다. 공격자는 유저 권한으로 정보를 가져오거나 액션을 수행할 수 있다
😇 : 쿠키에 refreshToken만 저장하고 새로운 accessToken을 받아와 인증에 이용하는 구조에서는 CSRF 취약점 공격을 방어할 수 있다. refreshToken으로 accessToken을 받아도 accessToken을 스크립트에 삽입할 수 없다면 accessToken을 사용해 유저 정보를 가져올 수 없기 때문이다.
3. secure httpOnly 쿠키 저장 방식
브라우저에 쿠키로 저장되는 것 같지만, Javascript 내에서 접근이 불가능하다. secure을 적용하면 https 접속에서만 동작한다.
😇 : httpOnly 쿠기 방식으로 저장된 정보는 XSS 취약점 공격으로 담긴 값을 불러올 수 없다.
😇 : 쿠키에 refreshToken만 저장하고 accessToken을 받아와 인증에 이용하는 구조로 CSRF 공격 방어가 가능하다
👿 : 쿠키 저장 방식과 같은 이우로 세션 id, accessToken은 저장하면 안 된다.
👿 : httpOnly 쿠키에 담긴 값에 접근할 수는 없지만 XSS 취약점을 노려 API 콜을 요청하면 httpOnly
쿠키에 담긴 값들도 함께 보내져 유저인 척 정보를 빼오거나 액션을 수행할 수 있다
👿 : LocalStorage 안에 세션 id, refreshToken 또는 accessToken을 저장해두면 XSS 취약점을 통해 그 안에 담긴 값을 불러오거나, 불러온 값을 이용해 API 콜을 위조할 수 있다.
어떤 저장 방식을 택해도 XSS 취약점이 있다면 보안 이슈가 발생한다.(XSS로 API 콜을 보내는 방식으로 다 뚫린다) 그러므로 유저 정보 저장 방식을 바꾸는 것만으로는 방어할 수 없고, 클라이언트와 서버에서 추가적으로 XSS 방어 처리가 필수다.
Access Token과 Refresh Token을 어디에 저장해야 하는지는 아래의 포스팅을 참고하면 좋을 것 같다.
https://velog.io/@ohzzi/Access-Token과-Refresh-Token을-어디에-저장해야-할까
좋은 정보 감사합니다 ❗️