Error Handling

storage로 관리하던 token, cookie로 넘기자

KANG_G1 2024. 3. 27. 16:29

refresh는 해결되었지만 큰 문제가 하나 더 남았었습니다.

바로 token인데요.

token을 cookie에 싣는 방법으로 빠르게 개발을 진행하기 위해

제가 발표에 사용했던 자료를 포스팅하고자 합니다.

1. 문제점과 해결 방안 제시

그동안 서비스에서 로그인 시, 서버로부터 받아온 response의

token(= refresh, access)을 localstorage에 보관해왔습니다.

해당 방식의 문제점은 크래커가 localStorage에 접근하는 코드 한 줄로

token에 쉽게 접근이 가능하다는 점인데요.(XSS Attack)

 

token 조작으로 타 유저의 이미지 변경, 원치 않는 정보 변경 등이 이뤄질 수 있으므로

이에 대한 대응이 필요한데 여러 대응책 중 하나가 바로 Cookie를 활용하는 것입니다.

2. 왜 Cookie를 활용해야 하는가

장점)

XSS Attack으로부터 안전하다.

cookie의 HTTP ONLY 옵션을 사용하여 JS로 쿠키에 접근할 수 없도록 처리 가능합니다.

그렇기에 XSS Attack으로 쿠키에 담긴 token 정보를 탈취할 수 없습니다.

(HTTP ONLY 옵션은 서버에서 설정이 가능합니다.)

 

단점)

따로 설정하지 않아도 HTTP Request에 담아서 보내지는 것이 cookie이기에

크래커가 Request URL을 알고있다면 유저 Request를 조작하기 쉬운데요,

이를 방지할 수 있는 cookie의 속성이 존재합니다.

 

localStorage의 장점을 쿠키에서도 적용 가능하다는 의미인데요.

same-site 속성 설정과 JS의 fetch API 속성 기본값 등으로

Reequest에 쿠키를 싣지 않을 수 있게 되었습니다.

Cookie를 왜 사용해야 하는지에 대한 설명을 했으니

어떻게 적용해야 할 지에 대해서도 말해야겠죠?

아래에 이어서 말씀드리겠습니다.

3. 적용 방법

1) 서버 response 변경

: 로그인 요청에 대한 응답을 변경.

현재는 이들 토큰을 응답 본문에 포함시키고 있는데,

이를 HTTP-only 쿠키로 전달하도록 변경해야 합니다.

쿠키를 설정할 때 'httpOnly' 속성을 true로 설정하여 자바스크립트에서

쿠키에 접근하지 못하도록 해야 합니다.

 

클라이언트에서는 더 이상 응답 본문에서 token을 읽지 않아도 됩니다.

대신, 브라우저가 자동으로 요청에 쿠키를 포함시킬 것입니다.

따라서 클라이언트는 단순히 서버로부터 응답을 받고, 필요에 따라 새로운 요청을 보내면 됩니다.

 

2) Token 갱신 처리

: access token이 만료되면, 클라이언트는 refresh token을 사용하여 새로운 access token을 얻습니다.

이때 서버는 refresh token이 포함된 쿠키를 받게 됩니다.

서버는 이 refresh token을 확인하고, 유효하다면 새로운 access token을 생성하여

HTTP-only 쿠키로 클라이언트에게 전달합니다.

 

이 방식을 사용하면, 클라이언트와 서버 모두에서 Token을 안전하게 관리할 수 있습니다.

또한, 클라이언트는 Token의 상세 내용을 알 필요 없이, 단지 서버가 제공하는 Token을 사용하면 됩니다.

그리고 사용자는 재로그인 없이 계속해서 서비스를 이용할 수 있습니다.

4. 또 다른 적용 방법

Refresh Token 하나만 사용하는 건데요.

프론트에서 refresh token으로만 요청을 하고, 나머지를 백엔드에서 처리해주는 방식으로

이전 직장 동료분께 공유받은 방법이 있습니다.

프론트에서는 쿠키를 저장소에 두진 않고 서버에서 response로 전달될 때

set-cookie로 전달되어서 사용하는 방식이라고 하시네요!

 

해당 방법을 사용한다면 서버와 클라이언트 둘 다 작업이 필요하지만

보안과 코드 효율성을 따졌을 땐 좋아보이는 방법으로 보여집니다.


5. 선택

발표 이후 Refresh Token은 Cookie로, Access Token은 로그인의 response로 전달받아

localStorage에서 관리하기로 결정했습니다.

하지만 언제까지고 localStorage에 저장하진 않을거에요.

어딘가에 캐싱을 해둬야겠죠?