종합설계에서 퍼블리싱을 마치고 내가 구현해야 될 부분을 보다가, OAuth를 활용한 소셜 로그인 구현이 있었다. 무작정 코드만 갖다 쓰자니 내가 얻을 것도 없고, 이해도 안될 것 같으므로 우선 OAuth의 기초가 되는 인증 방식부터 공부해보기로 했다.
세션/쿠키(Session/Cookie) 방식
세션: 서버에서 갖고 있는 정보
쿠키: 사용자에게 발급된 세션을 얻기 위한 열쇠(SESSION ID)
- 쿠키만으로 인증을 사용한다는 말은 서버의 자원은 사용하지 않는다는 것, 즉 클라이언트가 인증 정보를 책임지게 됨 -> HTTP 요청 탈취가 가능. 보안 취약.
- 그래서 로그인과는 상관없는, 장바구니 및 자동 로그인 등에 사용된다.
세션/쿠키 방식 순서
1. 사용자 로그인
2. 서버에서 계정 정보를 읽어 사용자를 확인한 후, 사용자의 고유한 ID값을 부여하여 세션 저장소에 저장. 그 후 이와 연결되는 세션 ID(쿠키) 발급
3. 사용자는 서버에서 2. 의 세션ID를 받아 쿠키에 저장한 후, 인증이 필요한 요청마다 쿠키를 헤더에 실어 보냄
4. 서버에서 쿠키를 받아 세션 저장소의 그것과 대조한 후 대응되는 정보를 가져옴
5. 인증이 완료되고 서버는 사용자에 맞는 데이터를 보내줌
장점
1. 중간에 탈취 우려가 있는 HTTP보다 안전
2. 사용자당 고유 ID를 발급받게 되므로 그 ID값에 따라 회원 정보를 확인할 수 있다. 일일이 확인할 필요가 없어서 서버 자원 접근이 용이하다.
단점
1. 세션 하이재킹의 가능성
- 해커가 탈취한 HTTP 요청 안에 쿠키가 있는 경우, 그 훔친 쿠키를 이용해 HTTP 요청을 하게됐을 때 세션 저장소에서 해커를 사용자로 오인해 정보를 잘못 주는 것
- HTTPS를 사용하거나, 세션 유효시간을 지정하여 문제 해결
2. 서버에서 세션 저장소를 사용하므로 추가공간 필요 -> 서버 과부하 가능성 존재
토큰 기반 인증 방식 (JWT)
JWT는 Json Web Token의 약자로, 인증에 필요한 정보들을 암호화시킨 토큰을 뜻함. 세션/쿠키 방식과 마찬가지로 사용자가 Access Token (JWT 토큰)을 HTTP 헤더에 실어 서버로 보내는 방식
JWT를 만들기 위해 필요한 세 가지: Header, Payload, Verify Signature
- Header: Header, Payload, Verify Signature를 암호화할 방식(alg), 타입(typ) 등이 들어감
- Payload: 서버에서 보낼 데이터가 들어감. 일반적으로 유저 별 고유 ID값, 유효기간이 들어감
- Verify Signature: Base64 방식으로 인코딩한 Header, Payload 그리고 SECRET KEY를 더한 후 서명됨
최종적인 결과로 Encoded Header + "." + Encoded Payload + "." + Verify Signature의 형태가 된다. (위 그림)
Header와 Payload는 따로 암호화되지 않고 인코딩만 되기 때문에, 누구나 디코딩을 할 수 있다. 이는 즉 데이터가 들어가는 Payload에 비밀번호와 같은 중요 정보가 들어갈 경우 쉽게 노출될 수 있다는 뜻과 같다.
그러나 Verify Signature은 SECRET KEY를 알지 못하면 복호화할 수 없다.
ex) 만약 A 사용자의 데이터에 대해 B가 이 토큰을 조작해서 정보를 캐낸다고 해 보자. 이 때에 조작을 한 B는 A의 Payload에서 ID를 자신의(B) ID로 바꾼 후 토큰을 서버로 보낸다. 이를 받은 서버는 Verify Signature 검사를 하게 되는데, 이 때 Verify Signature은 A 사용자의 Payload를 기반으로 암호화되었기 때문에, SECRET KEY를 알지 못하는 이상 토큰을 조작할 수 없게 된다. 이러한 방식으로 토큰의 조작을 방지할 수 있다.
JWT가 인증에 사용되는 방식
1. 사용자가 로그인을 한다.
2. 서버에서 계정정보를 읽어 사용자를 확인한 후, 사용자의 고유한 ID값을 부여. 이후 기타 정보와 함께 Payload에 넣음
3. JWT 토큰의 유효기간을 설정
4. 암호화할 SECRET KEY를 이용해 ACCESS TOKEN을 발급
5. 사용자는 Access Token을 받아 저장한 후, 인증이 필요한 요청마다 토큰을 헤더에 실어서 보냄
6. 서버에서는 해당 토큰의 Verify Signature를 SECRET KEY로 복호화한 후 조작 여부 및 유효기간을 확인
7. 검증이 완료된다면 Payload를 디코딩하여 사용자의 ID에 맞는 데이터를 가져옴
세션/쿠키 방식과의 차이점
세션/쿠키 는 세션 저장소에 유저의 정보를 넣는 반면, JWT는 토큰 안에 유저의 정보들이 들어간다는 점이 가장 큰 차이점이다.
클라이언트 입장에서는 헤더에 넣어준다는 점은 동일하나, 서버 단에서 인증을 위해 암호화를 하는지, 또는 별도의 저장소를 이용하는지의 차이점이 존재한다.
장점
1. 별도의 세션 저장소 관리를 필요로 하는 세션/쿠키 방식에 비해 간편하다. JWT는 발급 후 Verify Signature로 검증만 하면 되기 때문에 추가 저장소가 필요가 없다. 추가 저장소가 필요하지 않기 때문에, 유지 보수 및 서버 확장에 훨씬 유리하다. (상태를 따로 저장하지 않으므로)
2. 확장성이 뛰어나다. 토큰을 기반으로 인증을 하는 Google 로그인, Facebook 로그인 등 다른 인증 시스템에 접근이 가능하다. 이에 선택적으로 이름이나 이메일 등을 받을 수 있는 권한도 받을 수 있다.
단점
1. 이미 발급된 JWT에 대해서는 돌이킬 수 없다. 세션/쿠키의 경우 악의적으로 활용될 경우 그냥 그 세션을 지워버리면 된다. 하지만, JWT의 경우 한 번 발급되면, 유효기간이 다 될 때까지 사용할 수 있다. 따라서, 악의적으로 활용될 경우 유효기간이 지나기 전까지 정보를 전부 제약 없이 가져갈 수 있는 것이다.
- 이는, 기존 Access Token의 유효기간을 짧게 하고, Refresh Token이라는 새로운 토큰을 발급함으로써 해결할 수 있다. 이렇게 될 경우 Access Token을 탈취당하더라도 상대적으로 피해를 줄일 수 있다. 이는 OAuth와 깊은 관련이 있다.
2. Payload의 정보가 제한적이다. Payload는 따로 암호화되지 않으므로 디코딩이 자유롭고, 디코딩을 할 경우 누구나 정보를 확인할 수 있다. 이는 유저의 정보가 전부 서버 저장소에 안전하게 보관되는 세션/쿠키 방식과 비교했을 때 크나큰 단점이다. 그래서, Payload에는 중요한 정보들을 넣을 수 없다.
3. JWT의 길이가 세션/쿠키 방식에 비해 길다. 그래서, 인증에 필요한 요청이 많아질수록 서버의 자원낭비가 발생한다.
출처 및 참조
'FE' 카테고리의 다른 글
[인증] OAuth 2.0을 활용한 SNS 로그인 (0) | 2021.05.14 |
---|---|
[인증] Access Token, Refresh Token (2) | 2021.05.14 |
자바스크립트 코딩테스트 참고글 (0) | 2021.01.20 |