인증/보안
Cookie
쿠키는 서버에서 클라이언트에 영속성 있는 데이터를 저장하는 방법입니다. 서버는 클라이언트의 쿠키를 이용하여 데이터를 가져올 수 있습니다. 그러므로 쿠키를 이용하는 것은 단순히 서버에서 클라이언트에 쿠키를 전송하는 것만 의미하지 않고, 클라이언트에서 서버로 쿠키를 다시 전송하는 것도 포함입니다.
서버가 클라이언트에 특정한 데이터를 저장할 수 있습니다.
서버는쿠키를 이용하여 데이터를 저장하고 이 데이터를 다시 불러와 사용할 수 있지만, 데이터를 저장한 이후 아무 때나 데이터를 가져올 수는 없습니다. 데이터를 저장한 이후 특정 조건들이 만족되어야 다시 가져올 수 있기 때문입니다.
요청하는 서버의 도메인, 경로, sameSite 등의 조건이 맞아떨어질 경우 같이 전송됩니다
쿠키 옵션 종류
- Domain
- www.google.com 과 같은 서버에 접속할 수 있는 이름을 의미합니다.
- 쿠키 옵션에 도메인 정보가 존재한다면 클라이언트에서는 쿠키의 도메인 옵션과 서버의 도메인이 일치해야만 쿠키를 전송할 수 있습니다. 이를 통해 잘못 전송하는 일을 막을 수 있습니다.
- Path
- 세부 경로로써 서버가 라우팅할 때 사용하는 경로를 의미합니다.
- 요청하는 URL이 http://www.localhost.com:3000/users/login 인 경우라면 Path는 /user/login이 되고, 이를 명시하지 않으면 / 으로 설정되어 있씁니다.
- MaxAge or Expires
- 쿠키가 유효한 기간을 정하는 옵션입니다(설정하지 않을 경우 쿠키가 세션 쿠기가 되어, 클라이언트가 종료되면 세션이 종료되고 그 후에 세션 쿠키가 제거됩니다)
- 쿠키가 영원히 남아있으면 그만큼 탈취되기도 쉬워지기 때문에 이러한 유효기간을 설정하는 것이 보안 측면에서 유리합니다.
- MaxAge 는 쿠키가 유효한 시간을 초단위로 설정하는 옵션입니다.
- Expires는 클라이언트의 시간을 기준으로 언제까지 쿠키가 유효한지 심판의 날을 지정할 수 있습니다.
- 쿠키는 위 옵션의 여부에 따라 세션 쿠키와 영속성 쿠키로 나눠집니다.
- 세션쿠키 : MaxAge 또는 Expires 옵션이 없는 쿠키로, 브라우저를 종료하면 사라지는 임시 쿠키입니다.
- 영속성 쿠키 : 브라우저의 종료 여부와 상관없이 MaxAge 또는 Expires 에 지정된 유효시간만큼 사용가능한 쿠키입니다.
- Secure
- 사용하는 프로토콜에 따른 쿠키의 전송 여부를 결정하는 옵션입니다(true 설정 시 HTTPS를 이용하는 경우에만 쿠키를 전송할 수 있습니다.)
- Secure 옵션이 없다면 프로토콜에 상관없이 http / https 에 모두 쿠키를 전송할 수 있습니다.
- HttpOnly
- 자바스크립트로 브라우저의 쿠키에 접근이 가능한지 여부를 결정합니다.(true 설정 시 자바스크립트로 쿠키 접근이 불가능합니다.)
- SameSite
- Cross-Site 요청을 받은 경우, 요청에서 사용한 메서드(GET,POST,...) 와 해당 옵션의 조합을 기준으로 서버의 쿠키 전송 여부를 결정하게 됩니다.
- Cross-Origin : 서버의 도메인, 프로토콜, 포트 중 하나라도 다른 경우 Cross-Origin 입니다.
- Cross-Site : eTLD+1 이 다른 경우 Cross-Site로 구분됩니다. eTLD+1 이란 .com .org 와 같이 도메인의 가장 마지막 부분을 TLD(최상위 도메인, Top Level Domain)라고 하는데 이 최상위 도메인의 바로 왼쪽의 하위레벨 도메인을 합한 것을 의미합니다.
- Cross-Site 요청을 받은 경우, 요청에서 사용한 메서드(GET,POST,...) 와 해당 옵션의 조합을 기준으로 서버의 쿠키 전송 여부를 결정하게 됩니다.
// http 헤더를 사용한 쿠키 옵션
'Set-Cookie':[
'cookie=yummy',
'Secure=Secure; Secure',
'HttpOnly=HttpOnly; HttpOnly',
'Path=Path; Path=/cookie',
'Doamin=Domain; Domain=codestates.com'
]
쿠키를 이용한 상태 유지
이러한 쿠키의 특성을 이용하여 서버는 클아이언트에 인증정보를 담은 쿠키를 전송하고, 클라이언트는 전달받은 쿠키를 서버에 요청과 함께 전송하여 Stateless한 인터넷 연결을 Stateful 하게 유지할 수 있습니다.
하지만 기본적으로 쿠키는 오랜 시간 동안 유지될 수 있고, HttpOnly 옵션을 사용하지 않았다면 자바스크립트를 이용해서 쿠키에 접근할 수 있기 때문에 쿠키에 민감한 정보를 담는 것은 위험합니다.
Session
접속 상태를 서버가 가지고(stateful), 접속 상태와 권한 부여를 위해 세션아이디를 쿠키로 전송합니다. 로그인을 예로 설명하면 웹사이트에서 로그인을 유지하기 위한 수단으로 쿠키를 사용하고, 쿠키에는 서버에서 발급한 세션 아이디를 저정합니다.
- 서버에 접속 상태가 저장됩니다.
- 보통 하나의 서버에만 접속 상태를 저장합니다(여러 개의 서버에서 같은 세션 데이터에 접근하는 것을 고려하면 session clustering / 공통 session store를 사용해야 해서 번거롭기 때문에 유리하지 않습니다)
- 신뢰할 수 있는 유저인지 확인 가능합니다.
- Cookie에 세션 아이디가 저장됩니다.
Cookie vs Session
| 설명 | 접속 상태 저장 경로 | 장점 | 단점 | |
| Cookie | 쿠키는 그저 http의 statless한 것을 보완해주는 도구 | 클라이언트 | 서버의 부담을 덜어줌 | 쿠키 그 자체는 인증이 아님 |
| Session | 접속 상태를 서버가 가짐(stateful), 접속 상태와 권한 부여를 위해 세션 아이디를 쿠키로 전송 | 서버 | 신뢰할 수 있는 유저인지 서버에서 추가로 확인 가능 | 하나의 서버에서만 접속 상태를 가지므로 분산에 분리 |
해싱(hashing)
가장 많이 쓰이는 암호화 방식으로 암호화만 가능합니다.
- 항상 같은 길이의 문자열을 리턴합니다.
- 서로 다른 문자열에 동일한 해시 함수를 사용하면 반드시 다른 결과값이 나옵니다.
- 동일한 문자열에 동일한 해시 함수를 사용하면 항상 같은 결과값이 나옵니다.
솔트(Salt)
해싱 이전 값에 임의의 값을 더해 데이터가 유출되더라도 해싱 이전의 값을 알아내기 더욱 어렵게 만드는 방법입니다. 솔트를 사용하게 되면 해싱 값이 유출되더라도, 솔트가 함께 유출된 것이 아니라면 암호화 이전의 값을 알아내는 것은 불가능에 가깝습니다.
토큰(token)
사용자 인증 정보(Authentication)와 권한 정보(Authorization)를 포함한 정보를 담은 암호화된 문자열입니다.
토큰 기반 인증은 기존의 세션 기반 인증이 가지고 있던 한계를 극복하고자 고안되었습니다. 세션 기반 인증은 서버에서 유저의 상태를 관리하기 때문에 서버에 부담이 커지게 되었고, 이를 극복하기 위해 서버가 사용자의 인증 상태를 저장하는 것이 아닌 클라이언트에 이를 저장하는 방법인 토큰 인증 방식이 등장하였습니다.
토근 진행 방식
- 사용자가 인증 정보를 담아 서버에 로그인 요청을 보냅니다.
- 서버는 데이터베이스에 저장된 사용자의 인증 정보를 확인합니다.
- 인증에 성공했다면 해당 사용자의 인증 및 권한 정보를 서버의 비밀 키와 함께 토큰으로 암호화합니다.
- 생성된 토큰을 클라이언트로 전달합니다
- HTTP 상에서 인증 토큰을 보내기 위해 사용하는 헤더인 Authorization 헤더를 사용하거나, 쿠키로 전달하는 등의 방법을 사용합니다.
- 클라이언트는 전달받은 토큰을 저장합니다.
- 저장하는 위치는 Local Storage, Session Storage, Cookie 등 다양합니다.
- 클라이언트가 서버로 리소스를 요청할 때 토큰을 함께 전달합니다.
- 토큰을 보낼 때에도 Authorization 헤더를 사용하거나 쿠키로 전달할 수 있습니다.
- 서버는 전달받은 토큰을 서버의 비밀 키를 통해 검증합니다.
- 이를 통해 토큰이 위조되었는지 혹은 토큰의 유효 기간이 지나지 않았는지 등을 확인할 수 있습니다.
- 토큰이 유효하다면 클라이언트의 요청에 대한 응답 데이터를 전송합니다.
토큰 인증 방식의 장점
- 무상태성
- 서버가 유저의 인증 상태를 관리하지 않습니다.
- 확장성
- 다수의 서버가 공통된 세션 데이터를 가질 필요가 없기 때문에 서버를 확장하기 더 용이합니다.
- 어디서나 토큰 생성 가능
- 토큰의 생성과 검증이 하나의 서버에서 이루어지지 않아도 되기 때문에 토큰 생성만을 담당하는 서버를 구축할 수 있습니다.
- 권한 부여에 용이
- 토큰은 인증상태, 접근권한 등 다양한 정보를 담을 수 있기 때문에 사용자 권한 부여에 용이합니다.
JWT(JSON Web Token)
토큰 기반 인증 구현 시 대표적으로 사용되는 기술로, JSON 객체에 정보를 담고 이를 토큰으로 암호화하여 전송하는 기술입니다.
JWT의 구성
JWT는 . 으로 나누어진 세 부분이 존재하며 각각을 차례대로 Header, Payload, Signature 라고 부릅니다.
- Header
- 해당 토큰 자체를 설명하는 데이터가 담겨 있습니다. 토큰의 종류와 시그니철르 만들 때 사용할 알고리즘을 JSON 형태로 저장합니다. 이 JSON 객체를 base64 방식으로 인코딩해서 만들어집니다.
- Payload
- 전달하려는 내용물을 담고 있는 부분입니다. 접근 권한, 개인정보, 토큰의 발급 시간 및 만료 시간등의 정보들을 JSON 형태로 담고, 이를 base64로 인코딩해서 만들어집니다.
- Signature
- 토큰의 무결성을 확인할 수 있는 부분입니다. Header와 Payload가 완성되었다면, Signature는 이를 서버의 비밀키와 Header에서 지정한 알고리즘을 사용하여 해싱합니다.
토큰 인증 방식의 한계
- 무상태성
- 인증 상태를 관리하는 주체가 서버가 아니므로, 토큰이 탈취되어도 해당 토큰을 강제로 만료시킬 수 없습니다.
- 유효 기간
- 토큰이 탈취되는 상황을 대비해서 유효 기간을 짧게 설정하면, 사용자는 토큰이 만료될 때마다 다시 로그인을 진행해야 하기 때문에 좋지 않은 사용자 경험을 제공합니다. 그렇다고 길게 설정하면 토큰이 탈취될 경우 더 치명적으로 작용할 수 있습니다.
- 토큰의 크기
- 토큰에 여러 정보를 담을 수 있는 만큼, 많은 데이터를 담으면 그만큼 암호화하는 과정도 길어지고 토큰의 크기도 커지기 때문에 네트워크 비용 문제가 생길 수 있습니다.
액세스 토큰(Access Token)과 리프레시 토큰(Refresh Token)
액세스 토큰
서버에 접근하기 위한 토큰으로 보안을 위해 보통 24시간 정도의 짧은 유효기간이 설정되어 있습니다.
리프레시 토큰
액세스 토큰이 만료되었을 때 새로운 액세스 토큰을 발급받기 위해 사용되는 토큰입니다. 따라서 리프레시 토큰은 액세스 토큰보다 긴 유효기간을 설정합니다.
OAuth
전통적으로 직접 작성한 서버에서 인증을 처리해 주는 것과는 달리, OAuth는 인증을 중개해 주는 매커니즘입니다. 보안된 리소스에 액세스하기 위해 클라이언트에게 권한을 제공하는 프로세스를 단순화하는 프로토콜입니다. 즉 이미 사용자 정보를 가지고 있는 웹 서비스에서 사용자의 인증을 대신해 주고, 접근 권한에 대한 토큰을 발급한 후, 이를 이용해 내 서버에서 인증이 가능해집니다.
OAuth를 활용한다면 자주 사용하는 중요한 서비스들(google, naver, github 등)의 로그인 정보를 기억해 놓고, 해당 서비스들을 통해서 외부 서비스로 소셜 로그인을 할 수 있습니다. 또한 OAuth을 사용해서 로그인한다면, 유저의 민감한 정보가 직접 APP에 노출될 일이 없고, 인증 권한에 대한 허가를 미리 유저에게 구해야 하기 때문에 더 안전하게 사용할 수 있다는 장점이 있습니다.
OAuth의 주체
- Resource Owner
- OAuth 인증을 사용하는 사용자를 의미합니다.
- Resource Server & Authorization Server
- 소셜 로그인을 하기 위해 사용하는, 사용자의 정보를 저장하고 있는 서버를 의미합니다.
- Application(Client, Server)
- 사용자가 소셜 로그인을 활용해 이용하고자 하는 새로운 서비스는 환경에 따라 조금씩 다르게 불립니다.
- 경우에 따라서 Applicaiton을 Client와 Server로 세분화해서 지칭하기도 합니다.
OAuth 인증 방식의 종류와 흐름
1. Implicit Grand Type
- 사용자가 Application에 접속합니다.
- Application에서 Authorization Server로 인증 요청을 보냅니다.
- Authorizaiton Server는 유효한 인증 요청인지 확인한 후 액세스 토큰을 발급합니다.
- Authorization Server에서 Application으로 액세스 토큰을 전달합니다.
- Application은 발급받은 액세스 토큰을 담아 Resource Server로 사용자의 정보를 요청합니다.
- Resource Server는 Application에게서 전달받은 액세스 토큰이 유효한 토큰인지 확인합니다.
- 유효한 토큰이라면, Application이 요청한 사용자의 정보를 전달합니다.
2. Authorization Code Grand Type
Authorization Code를 사용한 인증 단계가 추가로 있기 때문에 Implicit Grand Type보다 비교적 더 안전합니다.
- 사용자가 Application에 접속합니다.
- Application에서 Authorization Server로 인증 요청을 보냅니다.
- Authorizaiton Server는 유효한 인증 요청인지 확인한 후 Authorization Code를 발급합니다.
- Authorization Server에서 Application으로 Authorization Code를 전달합니다.
- Application이 Authorization Code로 발급받은 Authorization Code를 전달합니다.
- Authorizaiton Server는 유효한 Authorization Code인지 확인한 후 액세스 토큰을 발급합니다.
- Authorization Server에서 Application으로 액세스 토큰을 전달합니다.
- Application은 발급받은 액세스 토큰을 담아 Resource Server로 사용자의 정보를 요청합니다.
- Resource Server는 Application에게서 전달받은 액세스 토큰이 유효한 토큰인지 확인합니다.
- 유효한 토큰이라면, Application이 요청한 사용자의 정보를 전달합니다.
3. Refresh Token Grant Type
- 사용자가 Application에 접속합니다.
- Application에서 Authorization Server로 Refresh Token을 전달합니다.
- Authorization Server는 Refresh Token을 확인합니다.
- Authorization Server에서 Application으로 Access Token을 전달합니다.
- Application에서 Authorization Server로 Access Token을 전달합니다.
- Authorization Server는 Access Token을 확인합니다.
- Authorization Server에서 Application로 사용자 정보를 전달합니다.
'프론트엔드 > Section3' 카테고리의 다른 글
| 네트워크 (2) | 2023.05.01 |
|---|---|
| 웹 표준 & 접근성 (3) | 2023.04.25 |
| React 상태관리 Redux (0) | 2023.04.24 |
| React Custom Component (1) | 2023.04.18 |
| 와이어프레임 & 프로토타입 (1) | 2023.04.13 |