원티드 프리온보딩 - 로그인 기능 구현하기 2 (내용)
원티드 프리온보딩 - 로그인 기능 구현하기 2강 복습
토큰(Token)이란?
사용자 신원을 알 수 있는 인증키,
a piece of data that is used to represent and replace another one, in order to prevent private information being seen by someone who is not allowed to do so :
로그인에 토큰을 사용해야하는 이유
서버는 무상태성(stateless)기 때문에 상태 저장을 하지 않기 때문에, 토큰을 사용해 사용자의 정보를 저장하기 위해
- 토큰을 사용하지 않는다면 물건을 장바구니에 추가할 때도, 장바구니로 이동할 때도 로그인을 계속해줘야함
로그인의 흐름
클라이언트에서 서버로 로그인 요청
서버에서 클라이언트에 토큰 발급 및 전달
클라이언트에서 토큰 보관
클라이언트에서 토큰을 사용해 서버에 요청
실제 서비스에서의 구조
유저 진입 후 토큰을 가지고 있는 여부에 따라 다음 단계 결정
1
2
3
4
5
6
1-1. 토큰이 있는 경우 서버에 token의 유효성을 확인
- 토큰이 유효하다면 로그인 성공!
- 토큰이 유효하지 않다면 로그인 진행
1-2. 토큰이 없다면 로그인 진행
- 사용자의 id와 비밀번호를 받아 서버에 인증 정보를 확인하고, 서버에서 새로운 token을 발급받아서 로그인 성공!
JWT (Json Web Token)
내부에 들어 있는 내용
1. Header
- 암호화 규칙 (alg) : 암호화 알고리즘_어떻게 암호화 할 것인지에 대한 내용
- 토큰 타입 (typ)
1
2
3
4
{
"alg": "HS256",
"typ": "JWT"
}
2. PAYLOAD
- 데이터 (클레임)
- sub: 토큰 제목
- iat: 언제 발급되었는지
1
2
3
4
5
{
"sub": "1234567",
"name": "John Doe",
"iat": 1516239022
}
3. SIGNATURE
- 암호화를 위한 데이터
- MY_SECRET_KEY : 서버만 알고 있고, 서버와 비교하여 유효성 검사할 데이터
1
2
3
4
5
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
MY_SECRET_KEY_1234!@#
) secret base64 encoded
해싱이란?
- 단방향 암호화 기법
- 평문(암호화 되지 않은 정보)를 해시함수(해시 알고리즘)을 이용해 고정된 길이의 암호화된 문자열로 바꾸는 것
실제로 JWT 관련 동작이 일어나는 곳
- 토큰이 유효한지 확인할 때
- 클라이언트가 저장된 token을 서버에 보내고, 서버는 유효성 검증을 한 결과를 클라이언트에게 반환
- 로그인 진행할 때
- 사용자가 입력한 id와 비밀번호를 서버에 보내면, 서버는 인증 정보를 확인하고 새로운 token을 생성해서 클라이언트에 보내줌
Access Token만 사용하면 보안이 완벽할까?
- XSS, CSRF 등을 통해 토큰을 탈취할 수 있음
XSS (Cross Site Scripting)
- 관리자가 아닌 권한이 없는 사용자가 웹 사이트에 스크립트를 삽입하는 공격 기법
- 악의적인 사용자가 C&C 서버로 리다이렉션 하기 위해 리다이렉션 스크립트를 주입하여 중간 경유지로 활용
- 사용자의 쿠키를 탈취하여 세션 하이재킹(Session Hijacking) 공격을 수행
CSRF (Cross-site Request Forgery)
- 사이트 간 요청 위조
- 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 특정 웹사이트에 요청하게 하는 공격
- 악성 메일이나, 스팸 문자의 링크를 클릭하면 사용자의 정보를 탈취하는 공격
JWT 보관 방식과 보안
Access Token : 재접근할 수 없는 런타임 메모리에 저장
Refresh Token: HttpOnly Cookie로 발급
Refresh Token
- 새로운 토큰을 생성하는 용도로만 사용되는 token (일회용 토큰)
HttpOnly Cookie
https
로만 접근이 가능하고, javascript로는 접근이 불가능- GET,POST (읽고 쓰기)가 모두 불가능
- API에 넣어서 사용해도 RESPONSE가 오지 않음
- XSS 공격 방어
- HTTPS 요청으로만 사용 가능하기 때문에 (자바스크립트 사용 불가) XSS 공격으로 토큰을 탈취할 수 없음
- 다른 방법으로 탈취하더라도 Token에 접근하기 위해서는 추가 인증이 필요함
- CSRF 공격 방어
1. CSRF 공격으로 Refresh Token 재사용 시도
2. 악성사이트에서 서버로 Access Token 재발급 요청
결과
- 만료되지 않은 Access Token 확인, 모든 토큰 무효화
- 일회용 Refresh Token으로 토큰 재발급 요청했기 때문에 요청을 무시 (Refresh Token Rotation)
참고사이트
This post is licensed under CC BY 4.0 by the author.