일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 프론트엔드
- React Query
- 알고리즘
- typescript
- wil
- 항해플러스
- 분기 회고
- frontend
- 리뷰
- 성장일지
- 보안
- 개발 공부
- GPU
- 자바스크립트
- FE
- 개발공부
- javascript
- 테스트 코드
- naver
- 성능최적화
- 항해 플러스
- rust
- webGPU
- 개발자
- 백준
- React
- 항해
- 회고
- 항해 플러스 프론트엔드
- 항해99
- Today
- Total
느릿늘있
브라우저 웹 스토리지와 인증 본문
인증은 웹 개발의 기본이 되면서도 종류의 다양성과 보안의 정도에 따라 꽤 많은 케이스가 존재하기에 정답이 없다. 최근 회사에서의 신규 프로젝트와 몇 가지 토이 프로젝트들을 개발하면서 브라우저의 웹 스토리지와 인증을 하나로 엮어서 글로 정리해두면 기억하기 좋을 것 같다는 생각이 들어 이 주제로 글을 쓰게되었다.
브라우저 웹 스토리지(+ 쿠키)와 인증
브라우저의 웹 스토리지 각각의 세부 내용과 사용법은 이 글의 목적이 아니다. 비교해서 기억하기 쉬운 형태로 각각의 주요 특징만 짚고 넘어가겠다.
[ 로컬 스토리지 ]
1. 브라우저를 종료해도 데이터가 유지된다. (로컬 - 유지)
2. 서로 다른 도메인 간 데이터를 공유하지 않는다. (동일 도메인은 공유)
3. 개발자 도구의 Application 탭에서 조회할 수 있다.
[ 세션 스토리지 ]
1. 세션(또는 탭)이 종료되면 데이터가 사라진다. (세션 - 삭제)
2. 서로 다른 세션 간 데이터를 공유하지 않는다.
3. 개발자 도구의 Application 탭에서 조회할 수 있다.
[ 쿠키 ]
1. Expires(만료일) 또는 Max-Age(최대 유지 기간)을 설정하지 않은 쿠키는 세션이 종료되면 데이터가 사라진다. (쿠키 - 유지/삭제 설정)
2. 서로 다른 도메인 간 데이터를 공유하지 않는다. (동일 도메인은 공유)
3. 개발자 도구의 Application 탭에서 조회할 수 있다.
1. 데이터의 유지 : 인증의 관점에서 브라우저의 종료와 함께 데이터가 사라진다는 것은 로그아웃을 의미한다. 따라서 보안적인 측면에서 로그아웃이 자동으로 동작하도록 인증 데이터를 세션 스토리지 또는 쿠키에 저장하는 것이 적절하다.
2. 도메인 간 데이터 공유 : 세션 스토리지는 세션 간 데이터를 공유하지 않는다. 즉, 새 탭으로 동일한 사이트에 접근하면 인증되지 않은 접근으로 인식된다. 탭마다 인증을 요구할 것이 아니라면 보통의 경우 동일 도메인 간 인증 정보가 공유되도록 로컬 스토리지 또는 쿠키를 사용하는 것이 적절하다.
위 두 가지 이유로 인해 인증 정보는 쿠키를 활용하여 HTTP(S) 통신을 하는 것이 정석이다. (쿠키는 이를 위해 생긴 것이기도 하다.) 다만 쿠키의 여러가지 속성 설정은 백엔드에서 Set-Cookie 헤더에 적용해주는 것이기 때문에 이 부분이 잘 협조가 안된다면 프론트엔드적 관점에서 임시 처리로서 웹 스토리지의 활용도 고려해볼만 하다. (단, 위에서 서술한 특징들을 잘 고려해서 판단해야 한다.)
JWT와 보안
각각의 저장소의 특징을 보면 공통점이 하나 있다.
" 개발자 도구의 Application 탭에서 조회할 수 있다. "
즉, 브라우저에 인증 정보를 저장하는 것은 인증 정보의 보안과 밀접한 관계가 있지만 어떤 저장소를 선택하느냐는 사실 상관이 없다. 암호화 작업 없이 인증 데이터를 브라우저에 저장하는 순간 너무나 쉽게 해당 정보는 탈취될 수 있고 이는 심각한 보안 취약점이라고 볼 수 있다.
이에 대한 해결책의 첫 단추는 JWT 적용이다. JWT는 원본 데이터와 signature를 대조하여 데이터의 위/변조를 판단한다. 여기서 중요한 부분은 인증 데이터의 위/변조를 판단한다는 점이다. 바꿔 말하면 JWT가 인증 데이터를 완벽하게 보호하는 것은 아니라는 점이다. JWT는 기본적으로 base64로 디코딩하면 body에 들어있는 인증 정보를 조회할 수 있다. 앞서 브라우저 저장소에서 살펴봤듯이 JWT를 어디에 저장하든 Application 탭에서 쉽게 가져다 볼 수 있기 때문에 데이터의 위/변조는 불가능할 지언정 인증 정보를 조회하거나 JWT 자체를 가져다 쓰는 것은 막을 수 없다.
이를 해결할 두 번째 단추는 인증 데이터를 감추는 것이다. 감추기의 첫 번째 단계는 JWT body에 불필요하게 인증 정보를 담지 않는 것다. 두 번째는 인증 정보를 꼭 담아야 한다면 반드시 자체적인 암/복호화를 해서 담는 것이다. AES와 같은 비공개 key를 사용하는 알고리즘을 적용해서 JWT 자체를 암호화하거나 특정 데이터만 암호화해서 보안을 강화할 수 있다. 감추기의 마지막 단계는 JWT 자체를 외부에 드러나는 브라우저 저장소에 저장하는 것이 아니라 소스 코드 내에서 변수에 할당함으로서 메모리에 감추는 것이다. 하지만 이 경우 새로고침만해도 데이터가 소실되기 때문에 Access/Refresh Token 방식을 도입하여 Access 토큰은 메모리에 감추고 Refresh 토큰을 저장소에 보관하여 Access 토큰 소실 시 재발급하는 방안을 고려해야 한다.
마지막 세 번째 단추는 저장소를 쿠키로 선택한 경우에 적용 가능한 쿠키 속성 설정을 통한 보안 강화이다. 우선, 쿠키에 secure 속성을 적용하여 안전한 https 통신에서만 인증이 동작하도록 제한한다. 그리고 필요한 경우, SameSite 속성을 strict로 강화하여 오직 동일한 사이트(도메인)에서의 요청에 대해서만 쿠키를 전송하도록 제한할 수 있다. 마지막 단계인 쿠키 속성 설정은 사실 백엔드에서 설정해주는 것이기 때문에 커뮤니케이션을 위한 지식 정도로 알아두면 좋겠다.
마치며
브라우저 웹 스토리지와 JWT를 가지고 주관적으로 중요하다고 생각되는 구성으로 정리해보았다. 완벽하지 않은 내용이지만 누군가에는 참고할만한 자료였기를 바란다. 추가로 위에서 상세하게 다루지 않은 JWT의 구조와 인증 방식, RTR(Refresh Token Rotation), 여러가지 쿠키 속성 그리고 언급하지 않은 또 하나의 브라우저 웹 스토리지인 Indexed DB 정도를 추가적인 학습 목표로 제안하며 여기서 마치도록 하겠다.
'개발공부' 카테고리의 다른 글
[React Hooks] useContext 이해하기 (0) | 2024.10.13 |
---|---|
참조값의 깊이에 대한 고찰 (feat. 복사와 비교) (3) | 2024.10.12 |
우당탕탕 RUST 도전기 (2) (0) | 2024.09.18 |
우당탕탕 RUST 도전기 (1) (0) | 2024.06.23 |
[TIL] Naver FE News 2024-02 (0) | 2024.02.17 |