JWT(Json Web Token)

혜진 조·2022년 6월 28일
0

JWT

목록 보기
1/2

(토큰 방식: 사용자 정보를 웹 브라우저에 저장 <-> 세션 방식: 사용자 정보를 서버에 저장)

👀 오늘의 주제

4번 단계에서 발급받은 토큰을 브라우저 어딘가에 저장을 해두어야하는데,
어디에 저장할 것인가?

1)local storage 
  =>XSS에 취약 (Javascript를 입력하여 공격하는 방식)
  
  "React DOM은 JSX에 삽입된 모든 값을 렌더링 하기 전에 이스케이프(escape)한다"
     *escape: 특정 문자를 원래의 기능에서 벗어나게 변환하는 행위
   

2)cookie
  요청 request에 cookie에 저장된 access token을 보내는 방식
  cookie는 httpOnly옵션과 secure 옵션을 통해서 XSS공격을 방어할 수 있다.
  =>하지만, CSRF 공격에 취약하다. ex.옥션 사건

다 장단점이 있어서, 개발자에 판단에 달려있다.

jwt를 이용한 로그인 흐름

사용자가 로그인을 하면, 서버에서 해당 계정 정보를 확인해서 유효시간이 있는 JWT 토큰을 발급한다. 해당 사용자는 유효시간이 끝날 때 까지, 인증이 필요한 요청마다 해당 JWT 토큰을 http 헤더에 넣어 서버에 요청을 한다. 서버에서는 해당 JWT 토큰이 유효한지 확인하고 사용자 정보를 전달한다.

  1. 사용자가 username, password 로 로그인을 한다.
  2. 서버는 해당 계정 정보를 읽어 사용자가 있는지 확인을 하고, JWT 토큰을 발급한다. 이때, JWT 토큰에 사용자의 고유한 ID값을 부여한 후, 기타 정보와 함께 Payload에 넣고 토큰의 유효 기간을 설정한다.
  3. 서버는 secret_key를 이용해 Access Token을 발급하고, 해당 JWT 토큰을 브라우저에게 전달한다.
  4. 사용자는 Access Token을 받아 저장한 후, 인증이 필요한 요청마다 Authorization 헤더에 토큰을 실어 보낸다.
  5. 서버는 secret_key를 이용해 해당 토큰의 Verify Signature를 복호화한 후, 조작 여부와 유효기간을 확인한다.
  6. 검증이 완료되면 Payload를 디코딩하여 사용자 데이터를 전달한다.

보안을 위한 refresh token 도입

사용자가 로그인을 하면 서버에서 토큰을 발급할 때, access token과 refresh token을 동시에 발급해준다. refresh token은 access token을 재발급받을 수 있는 token이다.
(refresh token은 사용자 인증이 아닌 새로운 액세스 토큰을 생성하는 용도로만 사용된다. 요청 헤더에는 access token을 넣는다.)
access token은 보안적으로 취약하므로 expire를 2시간 정도로 짧게 가져가고, refresh token은 2주 정도로 길게 가져가는 방식을 주로 사용한다.(refresh token은 DB에 저장된다.)
사용자는 Access Token과 Refresh Token을 둘 다 서버에 전송하여 전자로 인증하고 만료됐을 시 후자로 새로운 Access Token을 발급받는다.
공격자는 Access Token을 탈취하더라도 짧은 유효 기간이 지나면 사용할 수 없다.
정상적인 클라이언트는 유효 기간이 지나더라도 Refresh Token을 사용하여 새로운 Access Token을 생성, 사용할 수 있다.

여러 블로그를 검색한 결과 보통 access token은 로컬 스토리지 또는 로컬 변수에 저장,
refresh token은 httpOnly, secure cookie에 저장하는 것 같다.

로그인 했을 때 각각 setCookie() or localStorage.setItem()
로그아웃 했을 때 각각 removeCookie() or localStoreafe.removeItem()

access token을 로컬 변수에 저장 한 예시
(velog.io/@yaytomato/프론트에서-안전하게-로그인-처리하기 에서 참고한 코드)

onLogin = (email, password) => {
	const data = {
		email,
		password,
	};
	axios.post('/login', data).then(response => {
		const { accessToken } = response.data; //access token이라는 변수에 저장

		// API 요청하는 콜마다 헤더에 accessToken 담아 보내도록 설정
		axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;

		// accessToken을 localStorage, cookie 등에 저장하지 않는다!

	}).catch(error => {
		// ... 에러 처리
	});
}

함께 고민해야할 거리들
서버 개발자와 상의하여 accessToken 과 refreshToken의 key 명칭 정하기
로그인 만료, 로그인 연장 어떻게 처리할 것인지

참조사이트
https://velog.io/@khy226

https://tecoble.techcourse.co.kr/post/2021-10-20-refresh-token/

https://velog.io/@daybreak

https://velog.io/@0307kwon

구현 코드 참고할 수 있는 사이트
https://velog.io/@yaytomato

https://kimtruth.github.io/2021/05/30/JWT-Security/

profile
나를 믿고 한 걸음 한 걸음 내딛기! 🍏

0개의 댓글