- Token = Session을 보완한 인증방식
- 세션기반 인증 : 서버나 DB에 유저정보 저장하는 인증방식.
- 민감한 정보 요청하면 클라이언트가 보낸 세션id와 세션객체를 비교하고,
매 요청마다 DB를 봐야하는 부담이 있었음.
= 유저 증가하면 DB 리소스가 더 필요해짐
이 부담을 클라이언트에 넘기는 방법이 바로
토큰기반 인증의 대표적인 JWT 다 ! !
Token
서버 => 클라이언트에 인증된 토큰을 보관하는 방법
Q, 클라이언트에 민감한 정보를 저장하면 안된다며?
= 유저정보를 암호화한 상태로 담기때문에 무리가 없다
- 대표적으로 JWT(JSON Web Token)가 있음
JWT(JSON Web Token)
클라이언트단 JS의 LocalStorage, Cookie나 리액트의 State 등 다양한 공간에 저장.
장점
1. Statelessness & Scalability 무상태성 & 확장성
- 서버는 클라이언트에 대한 정보 저장안해도 됨
토큰 해독 여부만 판단.
- 클라이언트는 토큰을 헤더에 추가함으로 인증절차 완료
2. 안정성
- 암호화 한 토큰 사용하고, 암호화 키를 노출할 필요없음
2. 어디서나 생성 가능
- 토큰 확인하는 서버가 토큰 안만들어도 됨
- 토큰 생성용 서버만들거나, 다른 회사에 토큰 작업을 맡기는 등 다양하게 활용 가능
4. 권한 부여에 용이
- 토큰의 payload(내용물) 안에 어떤 정보에 접근 가능한지 정의
- ex) 사진과 연락처 사용권한 부여, 사진권한만 부여, 연락처 권한만 부여
종류
- 클라이언트가 처음 로그인 시(인증받을 때)
액세스, 리프레시 토큰 두개를 다 받는다.
1. Access Token
보호된 정보(유저 이메일, 연락처, 사진 등)에 접근 가능한 권한을 부여할 때 사용
- 만약 해커가 액세스 토큰 얻었을 경우를 대비하여,
짧은 유효기간을 줘서 오랫동안 사용못하도록 한다
2. Refresh Token
유효기간이 긴 토큰
- 만약 해커가 리프레시토큰 얻을 경우, 문제가 커진다.
- 그래서 보안에 중요한 웹사이트는 리프레시 토큰을 사용하지 않는 곳도 많다
구조
- typ : 어떤 종류의 토큰(JWT)인지,
- alg : 어떤 알고리즘으로 시그니처를 암호화(sign)할 지 JSON형태로 정보가 담겨있다.
밑의 JSON 객체를 base64로 인코딩하면 JWT 첫번째 부분인 Header가 완성된다
{
"alg": "HS256",
"typ": "JWT"
}
2. Payload
유저의 정보가 담겨 있다
- 권한 부여 여부, 기타 정보 담을 수 있다
- 민감한 정보는 담지 않아야 한다. 왜냐하면 디코딩이 쉬운 base64방식으로 인코딩되기 때문이다.
밑의 JSON 객체를 base64로 인코딩하면 JWT 두번째 부분인 Payload가 완성된다
{
"sub": "someInfo",
"name": "Niki",
"iat": 192829434
}
3. Signature
Header, Payload를 base64로 인코딩한 값 + Salt 와 알고리즘을 사용하여 암호화된 값
- base64 인코딩 값은 쉽게 디코딩하여 Header, Payload를 확인할 수 있지만
Salt 비밀키로 암호화된 값은 비밀키가 없다면 해독하는데 많은 시간이 걸릴 것이다.
만약 HMAC SHA256알고리즘을 사용하면 아래방식으로 생성된다
HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret);
누군가 권한을 속이려고 Payload 변조하여 base64로 인코딩해도 원본 Payload로 암호화한 시그니처 값과 다르므로
서버가 토큰이 변조됐음을 확인할 수 있다.
사용예시
- Gmail 인증서버에 로그인정보 제공
- 성공적으로 인증하면 JWT 발급받기
- 앱은 JWT로 해당 유저의 Gmail 이메일 읽거나 사용 가능함
토큰기반 인증절차
- 클라이언트 => 서버 아이디/비밀번호 담아 로그인 요청
- 아이디/비밀번호 일치여부 확인 후, 클라이언트에게 보낼 암호화된 토큰 생성
- Access/Refresh 토큰 모두 생성
- 토큰에 담길 정보(payload)는 유저를 식별할 정보, 권한 부여된 목록(사진, 연락처 등)이 될 수 있음
- 두 종류의 토큰이 같은 정보를 담을 필요 없음
- 서버 => 클라이언트 토큰 전송하면, 클라이언트는 토큰 저장.
- 저장 위치 - Local Storage, Session Storage, Cookie 등 다양함
- 클라이언트가 HTTP헤더(Authorization 헤더)나 쿠키에 토큰 담아 전송.
쿠키에는 Refresh 토큰 / 헤더나 바디에 Access 토큰을 담는 다양한 방법 구현 가능
- 서버가 토큰 해독해서 발급해준 토큰이 확인되면
클라이언트 요청 처리 후 응답.