-
[Web] 세션/쿠키 인증과 토큰 인증(Access Token, Refresh Token)프론트엔드 2022. 2. 10. 17:38
인증
- Reference : https://tansfil.tistory.com/58?category=475681
인증이란 / 인증이 필요한 이유
인증이란
- 프론트엔드 관점에서 봤을 때 : 사용자의 로그인, 회원가입과 같이 사용자 입장에서 서비스의 도입 부분을 가리킴.
- 서버사이드에서 봤을 때 : 모든 API 요청에 대해 사용자를 확인하는 작업.
인증이 필요한 이유
- 서버에서는 요청을 받았을 때, 누구의 요청인지를 정확히 알아야 한다. 그렇지 않으면 자신의 정보가 타인에게 유출될 수 있다. 따라서 프론트엔드(앱)에서는 누가 요청하고 있는지에 대한 단서를 서버에 보내야 하며, 서버에서는 그 단서를 정확히 파악해 맞는 데이터를 뿌려줘야 한다.
HTTP 요청에 대해
- 모바일, 웹 서비스에서 가장 많이 쓰이는 통신 방식.
- 응답 후 연결이 끊기며(비연결성), 서버가 클라이언트가 누구인지 기억하지 못한다(무상태). 즉 지금 보낼 HTTP 요청은 이전에 보냈던 HTTP 요청과는 전혀 관계가 없다. 따라서 각각의 HTTP 요청에는 주체가 누구인지에 대한 정보가 필수적이다. (인증이 필요 없다면 필요없을 수도 있지만, 대부분의 경우 인증이 필수적)
- 서버에 요청을 보내는 작업 = HTTP 메세지를 보내는 것.
- HTTP 메세지 : 헤더, 바디 두 가지로 구성됨. 한 줄의 공백이 헤더와 바디를 구분짓는 역할을 함. 헤더에는 요청에 관한 기본적인 정보들이 들어가고, 바디에는 서버로 보내야 할 데이터가 담긴다. 보통 모바일/웹 서비스의 인증은, HTTP 메세지의 헤더에 인증 수단을 넣어 요청을 보냄으로써 이루어진다.
인증 방식
1. 계정 정보를 HTTP 요청 헤더에 넣는 방식
- HTTP 요청 메세지 헤더의 인증 수단에 비밀번호를 넣는 방식이다.
- 보통 앱에서 서버로 HTTP 요청을 할 때는, 따로 암호화를 하지 않는다.따라서 데이터를 요청할 때마다 사용자의 프라이빗한 정보를 계속해서 보내게 되고, 이러한 HTTP 요청을 가로채면 사용자의 계정정보를 쉽게 알 수 있다.
- HTTP 요청을 암호화해서 보안을 높이는 방식의 HTTPS가 있지만, HTTPS로도 이러한 방식은 잘 쓰이지 않는다.
- 보안에 매우 취약하며, 서버에서 신호가 올 때마다 ID, PW를 통해 유저가 맞는지 인증해야하므로 비효율적이기도 하다. 최악의 인증방식이라고 볼 수 있다. 실제 서비스에서는 쓰지이 않고, 개발 단계에서 인증 절차를 빠르게 테스트해볼 때 사용해볼 수는 있다.
2. 세션/쿠키 방식
- 첫 번째 방식의 단점을 보완하기 위해 나온 것이 세션/쿠키 방식의 인증이다.
- 과정 : 사용자 로그인 -> 서버에서 사용자 확인 후 세션 ID 발행 -> 사용자는 서버에서 받은 세션 ID를 쿠키에 저장 하고, 데이터를 요청할 때마다 쿠키를 헤더에 실어 보낸다 -> 서버는 쿠키를 받아 세션저장소에서 대조한 뒤(인증완료) -> 사용자에 맞는 데이터를 보내준다.
- 세션 : 서버에서 가지고 있는 정보 / 쿠키 : 사용자에게 발급된 세션 ID (세션을 열기 위한 열쇠)
- 쿠키만으로 인증을 하는 경우 -> 서버의 자원은 사용하지 않고 클라이언트가 인증 정보를 책임지게 됨.이 경우 첫 번째 방식처럼 HTTP 요청을 탈취당하면 정보를 다 털리게 됨. 보안과는 상관없는 단순한 장바구니나 자동로그인 설정 같은 경우에는 유용하게 쓰인다.
- 세션을 사용해 인증을 하는 경우 -> 사용자는 쿠키를 이용하고, 서버에서는 쿠키를 받아 세션의 정보에 접근하는 방식으로 인증을 한다. 인증의 책임을 서버가 지기 때문에 보안성이 높아짐(사용자가 해킹당하는 것보다 서버가 해킹당하는 것이 훨씬 어렵기 때문).
- 장점 :
- HTTP 요청에 사용자 정보를 직접 담는 대신 쿠키를 담는다. 쿠키(세션 ID) 자체는 유의미한 값을 가지고 있지 않기 때문에, HTTP 요청이 도중에 노출되더라도 첫 번째 방식보다 상대적으로 안전하다.
- 서버에서 쿠키 값을 받으면, 회원정보를 일일히 대조해볼 필요 없이 바로 어떤 회원인지 알 수 있어서 서버의 자원에 보다 효율적으로 접근할 수 있다.
- 단점 :
- 사용자 A의 쿠키가 들어있는 HTTP 요청을 해커가 가로챘다면, 훔친 쿠키를 이용해 HTTP 요청을 보낼 수 있다. 그러면 서버의 세션 저장소에서는 사용자 A로 오인해 정보를 잘못 뿌려주게 된다. (세션 하이재킹 공격)=> 해결책: HTTPS를 사용해 요청을 탈취해도 안의 정보를 읽기 힘들게 하거나, 세션에 유효시간을 설정해준다.
- 서버에서 세션 저장소를 사용하기 위해 추가적인 저장공간을 필요로 하게 되고, 자연스럽게 부하도 높아지게 된다.
3. 토큰 기반 인증 방식 (JWT, JSON Web Token) : Access Token을 사용하는 인증 방식
- 인증에 필요한 정보들을 암호화시킨 토큰을 사용해 인증하는 방식.
- 사용자가 Access Token을 HTTP 헤더에 실어 서버로 보낸다.
- 토큰의 구성 요소 :
- Header : 토큰의 암호화 방식, 타입 등
- Payload : 서버에서 보낼 데이터. 유저의 고유 ID 값, 유효기간 등
- Verify Signature : 인코딩한 Header + Payload + SECRET KEY + 서명
- 최종적인 토큰의 모습 : Encoded Header + “.” + Encoded Payload + “.” + Verify Signature
- Header, Payload는 인코딩되어 16진수로 변경되지만, 따로 암호화되지는 않는다. 따라서 Header, Payload는 디코딩만으로 누구나 쉽게 확인할 수 있다.
- Verify Signature는 SECRET KEY를 알지 못하면 복호화할 수 없다.
- 인증 과정 :
- 사용자 로그인
- 서버에서 사용자 확인 -> 사용자에게 고유한 ID 값 부여 -> 기타 정보와 함께 Payload에 담음 -> 토큰의 유효기간 설정
- SECRET KEY를 이용해 Access Token 발급 -> Access Token과 함께 사용자에게 응답
- 사용자는 Access Token을 받아 저장 -> 데이터 요청 시 토큰을 헤더에 실어 보냄
- 서버에서 해당 토큰의 Verify Signature를 SECRET KEY로 복호화한 후 조작 여부, 유효기간 확인
- 검증이 완료되면 Payload를 디코딩하여 사용자의 ID에 맞는 데이터 가져와 응답
- https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F995EC2345B53368912
- 세션/쿠키 인증 방식과의 차이점 :
- 세션/쿠키는 세션 저장소에 유저 정보를 넣기 때문에, 서버 측에 별도의 세션 저장소가 필요함.
- 토큰 인증 방식은 토큰 안에 유저의 정보들을 넣기 때문에 별도의 저장소는 필요하지 않음. (별도의 저장소가 필요하지 않은 대신, 암호화가 필요함. )
- 장점 :
- 추가 저장소가 필요하지 않아 간편하다. Stateless(어떠한 별도의 저장소도 사용하지 않는, 즉 상태를 저장하지 않는)한 서버를 만드는 데 큰 강점. 서버를 확장하거나 유지, 보수하는 데 유리함.
- 확장성이 뛰어나다. 토큰 기반으로 하는 다른 인증 시스템(Facebook 로그인, Google 로그인 등)에 접근이 가능하다.
- 단점 :
- 악의적으로 이용되는 경우 해당하는 세션을 지워버리면 되는 세션/쿠키 인증방식과는 달리, 한 번 발급되면 유효기간이 완료될 때까지는 계속 사용이 가능하다. -> Refresh Token을 통해 어느 정도 해결할 수 있다.
- Payload 정보가 제한적이다. Payload는 암호화되지 않기 때문에 디코딩하면 누구나 정보를 확인할 수 있다. 따라서 유저의 중요한 정보들은 Payload에 넣을 수 없다. (세션/쿠키 방식에서는 유저의 정보가 전부 서버의 저장소에 안전하게 저장된다. )
- 세션/쿠키 방식에 비해 길이가 길다. 따라서 인증이 필요한 요청이 많아질수록 서버의 자원낭비가 발생하게 된다.
4. Refresh Token
- Access Token (JWT)를 이용한 인증 방식의 문제점 : 제3자에게 토큰을 탈취당할 경우 보안에 취약할 수 있다. 이 점을 해결하기 위해 유효기간을 짧게 하면, 그만큼 사용자가 로그인을 자주 해야 하는 불편함이 생긴다.
- Access Token의 유효기간을 짧게 하면서도, 사용자의 불편함을 줄일 수 있는 방법으로 나온 것이 Refresh Token이다.
- Refresh Token은 Access Token과 똑같은 형태의 JWT이다. Refresh Token은, 처음에 로그인을 완료했을 때 Access Token과 동시에 발급된다. Refresh Token은 긴 유효기간을 가지면서, Access Token이 만료되었을 때 Access Token을 새로 발급해주는 열쇠로 사용된다.
- Refresh Token의 유효기간이 만료되었을 경우에만 사용자가 새로 로그인을 하면 된다. 단, Refresh Token도 탈취될 가능성이 있기 때문에 적절한 유효기간 설정이 필요하다. (주로 2주 정도)
Refresh Token + Access Token을 활용한 인증 과정
- 사용자 로그인 -> 서버에서 사용자 확인(회원 DB에서 ID, PW 값 비교) -> 로그인 완료
- 서버에서 Access Token, Refresh Token 발급, 응답에 담아 보냄 (이 때 일반적으로 회원DB에 Refresh Token을 저장해 둠)
- 사용자는 Refresh Token을 안전한 저장소에 저장한 후, Access Token만 헤더에 실어 요청을 보냄.
- 서버에서 Access Token을 검증한 후 응답함.
- Access Token이 만료된 경우, 사용자는 Refresh Token과 Access Token을 같이 서버로 보냄.
- 서버는 받은 Access Token과 (조작 여부 확인) Refresh Token (회원 DB에 저장해둔 Refresh Token과 대조)을 확인한 후, 새로운 Access Token을 발급해 준다.
- 사용자는 새로 발급받은 Access Token을 헤더에 실어 다시 API 요청을 진행한다.
- 장점 : Access Token만 사용할 때보다 안전하다.
- 단점 : 검증 프로세스가 길어 구현이 복잡해졌다. Access Token이 만료될 때마다 재발급하는 과정에서 생기는 HTTP 요청횟수가 많아 서버의 자원 낭비가 발생한다.
(Velog(https://velog.io/@seomoon/Web-%EC%84%B8%EC%85%98%EC%BF%A0%ED%82%A4-%EC%9D%B8%EC%A6%9D%EA%B3%BC-%ED%86%A0%ED%81%B0-%EC%9D%B8%EC%A6%9DAccess-Token-Refresh-Token)에서 이동해 온 글입니다!)
'프론트엔드' 카테고리의 다른 글
[Web] 브라우저 프로토콜의 종류, HTTP 프로토콜 (0) 2022.02.10 [Web] 브라우저의 기능과 기본 구조 (0) 2022.02.10 [React] React에서 input 이벤트 사용하기 (onChange, onInput, onBlur) (0) 2022.02.10 [반응형 웹] 어떤 해상도의 기기가 가장 많을까? 해상도 점유율 확인하기 (0) 2022.02.10 [React] API 주소 환경변수로 분리하기 (개발서버/실서버) (feat.CRA, github-actions) (0) 2022.01.09