목차
보안 프로세스인 인증과 인가에 대해서 설명해보려고 한다. 로그인 기능을 구현할 때 인가코드, 인증 이러한 용어들을 듣게 되는데 정확히 뭔지 궁금해져 공부해보게 되었다.
인증(소셜 로그인)
인증은 식별 가능한 정보로 보호된 리소스에 접근하는 것을 허용하기 이전에 서비스에 등록된 유저의 신원을 입증하는 과정이다.
예를 들어 출국할 때 여권으로 신원을 입증하거나 회사에 들어올 때 출입증을 통해 신원을 입증할 수 있다. 웹의 경우에는 아이디와 패스워드를 입력하거나 휴대폰에 전달된 SMS에 적혀있는 코드를 입력하는 것이다.
인가(OAuth)
인가는 요청된 리소스에 접근할 수 있는 권한이 있는 인증된 유저인지 입증하는 과정이다.
예를 들어 회사가 14층에 위치하고 있다면 13층에 위치한 다른 회사에는 접근할 수 없다.
웹에서는 일반적으로 토큰을 통해서 인가를 다룬다. 사용자의 신원을 바탕으로 인가 세부사항을 가진 토큰을 생성하게 되고, 시스템은 인가 토큰을 이용해서 어떤 권한을 부여할지, 즉 리소스 접근 요청을 허용할지 거부할지를 결정하게 된다.
인증과 인가를 비교해보자면 위의 표와 같다. 인증은 사용자가 보고 직접 변경할 수 있지만, 인가는 볼 수도, 변경할 수도 없다. 그리고 인증은 데이터 전송 시 ID 토큰을 사용하고, 인가는 엑세스 토큰을 사용한다.
다시 말해, 인증과 인가는 자원을 유효한 사용자에게 전달, 공개하기 위한 방법이다.
HTTP의 stateless
웹 사이트는 HTTP 통신 위에서 동작하고, 모든 요청과 응답은 stateless한 특성을 가지게 된다. 즉, 서버에서 client의 이전 상태를 기억하고 있지 않다.
Request Header를 사용한 인증 과정은 아래와 같다.
1. url로 접근
2. url을 파싱하여 base64로 인코딩
3. 인코딩한 값을 request header에 담기
4. HTTP 통신
5. 서버는 DB에 값이 있는지 체크
이 특성과 인증을 함께 생각해보면 로그인을 통해 인증을 거쳐도 이후 요청에서는 이전의 인증된 상태를 유지하지 않게 된다. 이러한 상황에서 웹 사이트를 이용하게 된다면 인증/인가가 필요한 모든 상황에서 사용자는 반복적으로 아이디와 패스워드를 입력해야하는 불상사가 있을 것이다.
그럼, stateless한 HTTP 위에서 인증/인가를 어떠한 방식으로 해야할까?에 대한 의문이 생긴다.
해결책으로는 크게 3가지 방법이 있다. 쿠키, 세션, 토큰
1. 인증/인가 구현 방식 - 쿠키
HTTP 쿠키는 서버에서 사용자 브라우저로 전송하는 키-값 형태의 작은 데이터다. 브라우저는 서버에서 받은 쿠키를 저장해 놓았다가 동일한 서버로 재요청시 제공받았던 데이터를 함께 전송한다. 이를 통해 HTTP의 stateless를 보완해 HTTP 통신에서도 상태 정보를 보존할 수 있다.
사용자가 로그인할 때 서버는 ID/PW를 쿠키에 담아서 응답하고, 이후 요청부터는 브라우저가 ID/PW를 쿠키에 담아 함께 보내면, 사용자는 인증/인가를 위해 매번 ID/PW를 입력할 필요가 없다.
참고로 쿠키의 유효기간을 설정하고, response header에 쿠키를 설정할 수 있다. 또한 쿠키에는 HttpOnly라는 설정값이 있어 JS로 쿠키에 접근할 수 없도록 막아 XSS(Cross Site Scripting, 공격자가 상대방의 브라우저에 스크립트가 실행되도록 해 사용자의 세션을 가로채거나, 웹사이트를 변조하거나, 악의적 콘텐츠를 삽입하거나, 피싱 공격)와 같은 공격으로부터 보호해줄 수 있다.
정리하자면, 쿠키를 사용하면 첫 인증 때 기존 로그인 정보를 쿠키 형태로 브라우저에 심고, 매 요청마다 쿠키를 통해 로그인 정보를 함께 서버로 보내는 것이다. 즉, 매번 자동으로 로그인을 한다고 보면된다.
쿠키의 장점은 기존 로그인을 위한 정보를 사용하기 때문에 인증/인가를 위한 추가적인 데이터 저장이 필요없어 서버 대수를 늘려도 크게 이슈가 발생하지 않는다. 하지만 사용자의 주요 정보를 매번 요청에 담아야 하기 때문에 보안상의 위험이 있다.
2. 인증/인가 구현 방식 - 세션
쿠키의 보안상 문제를 보안하고자 나온 것이 세션이다. 세션은 고객의 주요 정보가 아닌, 고객을 식별할 수 있는 값(Session ID)을 생성해 쿠키로 주고 받는다. 따라서 사용자를 식별할 수 있는 값을 생성해야하고, 이를 서버에 저장하는 작업이 필요하다.
세션을 사용했을 때의 장점은 아래와 같다.
1. 만료기간을 지정할 수 있기 때문에 해커가 가져가더라도 만료 기간이 지나면 사용할 수 없다.
2. 클라이언트 쪽에서 데이터를 가지고 있지 않기 때문에 보안상 쿠키보다 안전하다.
3. 세션은 서버가 관리하고 있기 때문에 세션 자체를 서버에서 삭제하면 더 이상 사용할 수 없다.
하지만 단점으로는 다중 서버일 경우에는 매번 같은 서버로 요청이 간다고 보장할 수 없기 때문에 session ID가 저장되지 않은 곳으로 요청이 가면 사용자를 식별할 수 없다는 단점이 있다.
물론, 이를 보완하기 위한 방법으로 사용자를 식별해 이전에 통신한 서버로 요청이 가도록 경로를 지정하거나 다중 서버의 모든 session 저장소를 동일하게 유지하는 방법(Session Storage 사용)이 있다.
어찌됐든, session ID 또한 탈취 가능성이 있고, client 상태를 서버에서 관리한다는 점에 있어서 HTTP stateless 특성과는 거리가 멀고, client가 많아질 경우에는 session storage가 뻑이갈 수 있다는 문제점이 있다.
3. 인증/인가 구현 방식 - 토큰
그래서 나온 방식이 HTTP Stateless 특성을 사용하는(상태를 저장하지 않는) 토큰이다.
토큰은 기존 로그인 정보를 그대로 사용하지 않으면서도 서버에서 사용자 식별값을 저장 및 관리하지 않아도 된다.
토큰은 사용자를 인증할 수 있는 정보가 숨겨진 암호화된 access token을 발급하고, 인증이 필요할 때마다 서버에 토큰과 함께 요청을 보낸다. 서버는 저장된 데이터가 아닌 토큰 해독을 통해 사용자를 식별할 수 있는 정보를 알아내고 이를 바탕으로 인증/인가를 진행한다.
토큰에 다양한 유형과 종류가 있지만 우리팀에서는 JWT(JSON Web Token)을 사용했다. JWT는 웹 서비스에서 자주 사용되는 토큰으로 header, payload, signature와 같은 요소들로 구성되어 있다. "."을 구분자로 읽기 어려운 JWT로 생성이 된다.
- Header: Token 유형, 서명 알고리즘(HS256 or RSA 등)이 담긴다.
- Payload: Claim이 포함되는 영역으로 전송하고자 하는 여러 데이터가 담긴다.(Claim 유형: Registered / Public / Private)
- Signature: Base64로 인코딩 된 Header, Payload와 서버만이 가지고 있는 비밀 키를 설정한 알고리즘으로 암호화한 값이 담긴다.
요청과 함께 JWT가 서버에 도착했을 때 서버는 JWT가 시크릿키를 통해 자신이 발행한 것이 맞는지 확인하고, 시크릿키로 암호화를 진행해 signature 영역과 동일한지 확인한다.
토큰을 사용하면 서버가 여러대가 있어도 각자의 시크릿키로 해독 및 인증을 진행할 수 있고확장성 높음), 토큰으로 상태관리를 하기 때문에 따로 세션을 둘 필요가 없다는 장점이 있다.
하지만 여전히 해커에게 노출될 수 있다는 위험은 배제할 수 없기 때문에 시크릿키에 만료기간을 설정할 수 있다. 만료기간이 지나면 해커뿐만이 아니라 사용자도 사용할 수 없기 때문에 이러한 불편함을 감소하기 위해 refresh token이 나왔다.
1. HTTP 통신
2. 서버는 시크릿키를 사용해 access token과 refresh token 생성
3. 서버는 refresh token만 따로 저장소에 저장
4. 서버는 클라이언트에게 access token과 refresh token 전송
5. 클라이언트는 2개의 token을 저장
6. 클라이언트는 access token을 사용해서 요청 보냄
7. 만약 access token이 만료되었을 경우 클라이언트는 access token과 refresh token을 다시 서버로 전송
8. 서버는 refresh token을 참조하여 DB 체크
9. DB에 있는 정보와 일치한다면 새로 갱신된 access token을 클라이언트에게 전송
다른 서비스를 통해 인증을 받을 수도 있는데 예시로는 OAuth가 있다. 이는 다른 글에서 자세하게 작성하도록 하겠다.
참고자료
'CS > 그 외' 카테고리의 다른 글
HLS(HTTP 라이브 스트리밍)와 m3u8 (0) | 2024.06.23 |
---|---|
OAuth 인증 과정 (0) | 2024.01.24 |
프론트엔드 입장에서 바라본 Socket과 WebSocket (0) | 2024.01.12 |
[⭐️⭐️⭐️⭐️⭐️] 브라우저의 렌더링 원리 (0) | 2023.03.10 |
댓글