인증과 인가, JWT Token

Nak·2023년 1월 18일
0
post-thumbnail

인증과 인가

인가 Authorization

한번 인증을 받은 사용자가 서비스의 여러 기능들을 사용할 때
로그인 후 내 장바구니를 보거나 배송을 취소, 주문 하는 등
내 계정으로만 할 수 있는 활동을 시도할 때 로그인 되어있음을 알아보고 허가를 해주는거다.
쉽게 로그인이 유지되는 상태에서 일어나는 일이다.

인증 Authentication

인증 (Authentication)은 쉽게 로그인이라고 생각하면 된다.
웹에 가입된 회원임을, 특정 서비스에 일정 권한이 주어진 사용자임을 아이디랑 패스워드 등을 통해서
인증을 받는거다.

그럼 어떻게 로그인 한 상태를 서버가 알 수 있을까?

데이터베이스 저장된 사용자 계정이 해시값을 꺼내온 뒤, 사용자의 암호를 복잡한 알고리즘으로 계산한 값과 일치하는지 확인하는 과정을 걸쳐야 한다.

매 요청마다 아이디와 비밀번호를 주고 받으면 보안상 위험하다.

인가 : 그럼 어떻게 아이디와 패스워드를 지킬수 있을까?

전통적으로 많이 사용되어온 "세션" 방식과 세션 방식에서 고안된 "토큰" 방식이 있다.

세션 방식 stateful

일단 "세션"방식은 사용자가 로그인에 성공하면, 서버는 "세션 ID"을 출력한다.ex)놀이공원 티켓

반쪽은 사용자의 브라우저로 보내고 반쪽은 메모리(가장빠름)에 저장한다.

경우에 따라서 하드디스크(좀 느림)에 넣거나, 데이터베이스(느림)에 저장한다.

사용자가 사이트에 요청을 보낼때마다 세션 ID를 보내고,

서버에 맞는 짝이 있는지 찾아서 인가 해준다.

세션 방식은 모든 상태를 기억하고 있음.
ex)한 기기에만 로그인한 상태를 만들려는 경우 pc에서 로그인한 상태의 사용자가 핸드폰에서 또 로그인하면 pc에서는 로그아웃되도록 기존 세션을 종료할 수 있다.

허점 :
만약 에러가 나타나서 서버가 재부팅되어야 하는 상황이 오면 메모리에 있던 것들은 다 날아간다.
그렇다고 하드디스크에 저장하면 느려짐.

만약 서버를 여러대 두고 운영할 때 여러 서버들 사이에 분산을 해서 로드 바란싱을 해주는데

만약 로그인은 1번서버에 연결되서 하고 이메일은 3번 서버한테 가면 세션유지가 안된다.
그렇다고 사용자의 요청이 각자 할당된 서버로만 보내지게 하는것도 번거롭고 까다롭다.

다른 방법으로 데이터베이스 서버에 넣어두거나(속도가 엄청 느려짐) 레디스나 MemCached 같은 메모리형
데이터베이스 서버에 넣기도 한다. (설계하기 까다롭다)

JWT : JSON Web Token 방식 stateless

사용자가 로그인 하면 토큰을 출력해서 사용자에게 쿠키로 건네준다.(서버는 저장하지 않음)
토큰방식은 모든 상태를 기억하지 못함.
인코딩 또는 암호화된 3가지 데이터를 이어 붙인거다 (.으로 기준)
누가 누구에게 발급했는지, 유효기간, 역할 등 원하는 내용을 담을 수 있다.(클레임이라고 명칭)

JWT는 각각 1번:header, 2번:payload, 3번:verify signature로 구분된다.

payload를 Base64로 디코딩해보면 JSON형식으로 여러 정보들이 들어있다.

header는 두가지 정보가 들어있다.

  • type은 JWT (고정값)
  • alg : 알고리즘의 약자 verify signature 값을 만드는데 사용되는 알고리즘이 저장됨.(HS256등)
    서버가 요청에 토큰 값이 실려들어오면 1,2번의 값을 서버의 비밀키와 함께 돌려봐서 계산된 결과값이
    3번 과 일치하는 결과가 나오는지 확인.

약점 :
어디서 로그인한 토큰을 뺏을 수 없어서 서버가 기록하고 있지 않음.
토큰을 탈취 당한경우 무효화 할 방법이 없다.
때문에 실 서비스중에 JWT만으로 인가를 구현하는 곳은 생각보다 많지 않다.

보완하기 위해 쓰는 방법 :
로그인 하면 토큰을 2개 주는데 refresh토큰과 access토큰을 준다.
refresh토큰은 긴 수명을 가진 토큰이고, access토큰은 짧은 수명을 가진 토큰이다.

로그인을 한다면)

서버는 토큰 2개를 클라이언트에게 보내고 refresh토큰을 데이터베이스에 저장한다.
클라이언트는 access토큰이 수명을 다하면 refresh토큰을 서버에 보낸다.
서버는 데이터베이스에 저장된 값과 대조해보고 맞다면 새로운 access토큰을 보내준다.

구현 방법은 구현 할 수 없지만 토큰방식에 refresh와 access토큰 방식을 구현해보면 좋을 것 같다.

0개의 댓글