- 세션 기반의 인증은 요청을 받을 때마다
클라이언트가 보낸 세션 아이디
와 서버(혹은 DB)의 저장소에 있는 세션 객체 안의 세션 아이디
를 비교.
- 매번 서버의 데이터를 살펴보는 것이 불편하다면?
토큰 기반 인증 (Token-based Authentication)
- 클라이언트에서 인증 정보를 보관
- 유저 정보를 암호화하기 때문에 민감한 인증 정보도 클라이언트에 담을 수 있다.
유저 식별 정보, 토큰 권한으로 어떤 데이터에 접근할 수 있는지(ex: 사진, 연락처에만 접근 가능) 등이 담긴 암호화된 토큰이 쿠키 등에 담겨 클라이언트에 전달돼서 저장됨....
JWT
- JSON Web Token
- 가장 대표적인 토큰 기반 인증
JWT이 이용하는 토큰
1. 엑세스 토큰 (Access Token) : 인증 증명에 사용
- 보호된 정보들(유저의 이메일, 연락처, 사진 등)에 접근할 수 있는 권한 부여에 사용
- 클라이언트가 처음 인증을 받으면(= 로그인 시) 엑세스 토큰, 리프레시 토큰 두 가지를 다 발급 받지만, 이후 실제로 권한을 얻는 데 사용되는 토큰은 엑세스 토큰.
- 엑세스 토큰을 탈취당하더라도 오랫동안 사용할 수 없도록 비교적 짧은 유효기간을 주는 것이 좋다.
2. 리프레시 토큰 (Refresh Token) : 새 엑세스 토큰 발급에 사용
- 엑세스 토큰의 유효기간이 만료되면 리프레시 토큰을 사용해 새로운 엑세스 토큰을 발급받는다. (유저가 다시 로그인 할 필요 X)
- 만약 리프레시 토큰도 탈취당한다면 상당히 오랜 기간동안 유저에게 피해를 입힐 수 있다. (이 때문에 보안이 중요한 웹사이트 중에는 리프레시 토큰을 사용하지 않는 곳이 많음)
JWT의 구조
- 어떤 종류의 토큰인지
- 어떤 알고리즘으로 시그니처를 암호화(sign) 할 지 적혀있다.
- 아래 형식의 JSON 객체를 base64 방식으로 인코딩한 것
{
"alg": "HS256",
"typ": "JWT"
}
2. Payload
- 서버에서 활용할 수 있는 유저의 정보
- 어떤 정보에 접근 가능한지에 대한 권한, 또는 유저 이름 같은 개인정보 등을 담을 수 있다.
- 아래 형식의 JSON 객체를 base64 방식으로 인코딩한 것
3. Signature
Header
와 Payload
를 서버의 비밀 키(솔트)와 Header에서 지정한 알고리즘을 사용해 해싱해서 생성
- Header와 Payload를 알아내서 토큰을 위조하더라도 서버의 비밀 키를 모르면 전혀 다른 Signature가 만들어짐.
HMAC SHA256 알고리즘을 사용
HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret);
JWT 사용 예시
- JWT은 권한 부여에 굉장히 유용.
- 어떤 정보에 접근 가능하고 접근 불가능한지 Payload에서 설정할 수 있음
- 서로 다른 어플리케이션에도 권한을 부여할 수 있다.
Ex) A
라는 앱을 Gmail과 연동시켜 이메일 정보를 가져오려고 할 때
1) A
앱의 클라이언트에서 Gmail 인증 서버에 로그인 정보(아이디, 비밀번호)를 제공해서 인증(로그인) 요청을 보낸다.
2) 성공적으로 인증 시 JWT를 발급받는다.
3) A
앱에서 JWT를 사용해 해당 유저의 Gmail 이메일을 읽거나 사용할 수 있다.
토큰 기반 인증 절차 (JWT 절차)
1. 클라이언트가 서버에 로그인 요청
- 클라이언트가 아이디/비밀번호를 요청에 담아 서버에 보낸다. (로그인 요청)
2. 로그인 성공 시 서버가 암호화된 토큰(JWT) 생성해서 클라이언트에 전송
- 로그인 성공 시, 엑세스 토큰과 리프레시 토큰을 모두 생성한다.
- 토큰에 담길 정보(payload) : 유저 식별 정보, 토큰 권한으로 어떤 데이터에 접근할 수 있는지(ex: 사진, 연락처에만 접근 가능) 등
- 두 토큰이 같은 정보를 담을 필요는 없다.
3. 클라이언트가 전송받은 토큰 저장
- 저장하는 위치 : Local Storage, Session Storage, Cookie 등 다양
4. 클라이언트 요청 시 토큰 함께 전송
- 클라이언트가 요청 보낼 때
HTTP 헤더
또는 쿠키
에 토큰 담아 보냄.
(엑세스 토큰은 HTTP 헤더
또는 바디
에, 리프레시 토큰은 쿠키
에 담는 등...다양한 방법으로 구현할 수 있다)
- HTTP 헤더로 Authorization 헤더를 사용한다면 Bearer Authentication을 이용한다. (참고: 링크1(요약), 링크2(상세))
5. 서버는 토큰 해독 후 요청 해결/응답 보냄
토큰 기반 인증의 장점
1. 무상태성 & 확장성 (Statelessness & Scalability)
무상태성
- 서버는 클라이언트에 대한 정보를 저장할 필요 X (토큰이 해독 되는지만 판단)
- 클라이언트는 새로운 요청 보낼 때마다 토큰을 헤더에 포함시키면 된다.
확장성
- 같은 토큰으로 여러 서버에서 인증 가능하기 때문에, 서버가 여러 개인 서비스일 때 더욱 편리.
(서버에 세션 객체(인증 상태) 저장하는 세션 방식이라면 모든 서버가 해당 유저의 정보를 공유하고 있어야 함)
2. 안전하다
- 암호화한 토큰을 사용하고, 암호화 키를 노출할 필요가 없기 때문에 안전.
3. 어디서나 생성 가능
- 토큰을 확인하는 서버가 토큰을 만들지 않아도 된다.
- 토큰 생성용 서버를 따로 만들거나, 다른 회사(서버)에 토큰 관련 작업을 맡길 수도 있다.
4. 권한 부여에 용이하다.
- 토큰의 Payload 안에 어떤 정보에 접근 가능하고 접근 불가능한지 정할 수 있다.
(ex: 서비스의 사진과 연락처 사용 권한만 부여)