TIL DAY 18-2 || Django Authorization with JSON Web Token(JWT)

TK·2021년 3월 9일
2

TIL

목록 보기
25/55

Authorization

인가(Authorization)는 유저가 요청하는 request를 실행할 수 있는 권한이 있는 유저인가를 확인하는 절차이다.

예를 들어서 어떤 유저가 쇼핑몰의 카탈로그를 볼 수는 있지만, 카탈로그의 수정은 안된다는 점이다. 특정 권한이 있는 유저만 카탈로그의 수정이 가능하다.

이렇게 권한이 있는 유저인지 판별하고 인증하는 과정이 인가(Authorization) 과정이라고 한다.

Authorization Process

Authorization 절차

  1. Authentication 절차를 통해 access token을 생성한 뒤 유저(브라우저)에게 준다(로그인 성공 시 브라우저에 토큰 발급). 
  2. access token 에는 유저 정보를 확인할 수 있는 정보가 들어가 있어야 한다. ex)user_id
  3. 브라우저는 받은 토큰을 session storage 나 local storage 에 저장한다.
  4. 유저가 request를 보낼때 access token 을 첨부해서 보낸다.
  5. 서버에서는 유저가 보낸 access token 을 복호화 한다.
  6. 복호화된 데이터를 통해 (예를들어) user id를 얻는다.
  7. user id를 사용해서 database에서 해당 유저의 권한(permission)을 확인하다.
  8. 유저가 충분한 권한을 가지고 있으면 해당 요청을 처리한다.
  9. 유저가 권한을 가지고 있지 않으면 Unauthorized Response(401) 혹은 다른 에러 코드를 보낸다.

Pros & Cons of Session/Cookie Authorization

Pros

  • 세션/쿠키 방식은 기본적으로 쿠키를 매개로 인증을 거친다.
  • 여기서 쿠키는 세션 저장소에 담긴 유저 정보를 얻기 위한 열쇠일 뿐이다.
  • 따라서 쿠키가 담긴 HTTP 요청이 도중에 노출되더라도 쿠키 자체(세션 ID)는 유의미한 값을 갖고있지 않다.
  • 중요정보는 서버 세션에 저장한다.
  • 사용자는 고유한 ID 값을 발급받기 때문에, 서버에서는 브라우저에 발행한 쿠키/세션 ID 값을 받았을 때 바로 어떤 회원인지 확인할 수 있어서 서버 자원에 접근이 용이하다.

Cons

  1. 쿠키를 탈취당하더라도 유의미한 정보가 없기 때문에 안전할 수 있다고 했지만 만일 A 사용자의 HTTP 요청을 B 사용자(해커)가 쿠키 자체를 가로챌 수 있다. 해당 쿠키를 이용해 서버에 요청을 보내면 서버는 B를 A라고 오인해서 정보를 넘겨줄 가능성이 존재한다.

이에 대한 해결책은

  • HTTPS를 사용해 요청 자체를 탈취해도 요청의 정보를 읽기 힘들게 한다.
  • 세션에 유효시간을 넣어준다.
  1. 서버에서 세션 저장소를 사용하기 때문에 서버에서 추가적인 저장공간을 필요로 하고 이에 따라 부하도 커질 가능성이 높다.

  2. 서버의 확장성이 좋지 않다. A 서버에 있는 세션 저장소에 세션 정보가 있는데, 브라우저가 B 서버에 요청을 보내면 A 저장소에 있는 세션 정보를 B 에 공유해줘야하는 복잡한 작업이 필요하기 때문에 확장성이 좋지 않다.

Pros & Cons of JSON Web Token(JWT)

Pros

  • 세션/쿠키는 별도의 저장소의 관리가 필요하지만 JWT는 토큰을 발급한 후 base64 encoding 으로 암호화 한 signature 만 검증만 하면 되기 때문에 서버측에서는 유저의 세션을 유지 할 필요가 없으므로 추가 저장소가 필요 없다.

  • Stateless 한 서버를 만드는 데 가장 중요한 사실이다.

Cons

  1. 세션/쿠키의 경우 만일 쿠키가 악의적으로 이용된다면, 해당하는 세션을 지워버리면 되지만 JWT는 한 번 발급되면 유효기간이 완료될 때 까지는 계속 사용이 가능하다. 따라서 해커는 유효기간이 지나기 전까지 정보 탈취가 가능하다.

이에 대한 해결책은

  • 기존의 access token의 유효기간을 짧게 하고 Refresh Token이라는 새로운 토큰을 발급하여 피해를 줄일 수 있다.
  • OAuth2 를 사용한다.
  1. Payload 정보는 따로 암호화 되지 않기 때문에 넣을 수 있는 정보가 제한적이다.

  2. 세션/쿠키 방식에 비해 JWT의 길이가 길기 때문에 인증이 필요한 요청이 많아질 수록 서버의 자원낭비가 발생하게 된다.

How to use JWT ?

{
  "typ": "JWT",
  "alg": "HS256"
}

헤더에는 타입과 알고리즘 방식을 표기한 뒤 base64 로 encoding 한다.

참고: JSON 형태의 객체가 base64 로 인코딩 되는 과정에서 공백 / 엔터들이 사라진다. 따라서, 실제로는 다음과 같은 문자열을 encoding 하게 된다.
{"alg":"HS256","typ":"JWT"}

payload

  • Payload 부분에는 토큰에 담을 정보가 들어있다.
  • 여기에 담는 정보의 한 ‘조각’ 을 클레임(claim) 이라고 부른다.
  • 이는 name(key) / value 의 한 쌍(pair) 으로 이뤄져있다.
  • 토큰에는 여러개의 claim 을 넣을 수 있다.
{
    "iss": "velog.io/tk_kim", # 토큰 발급자
    "exp": "1485270000000", # 만료일(현재보다 뒤로 설정되어 있어야 함, NumericDate 로 표기)
    "userId": "11028373727102", # 비공개 클레임 (private claim)
    "username": "tk_kim" # 비공개 클레임
}

이것 또한 base64 로 encoding 한다.

Signature

이 서명은 header의 인코딩 값(base64) 과 payload 의 인코딩값을 합친 것을 주어진 비밀키로 해쉬를 하여 생성한다.

Header(base64) + Payload(base64) 를 SECRET KEY 로 HASH 한 뒤, base64 로 encoding 해주면 된다.

이제 모든 파트를 . 으로 구분하여 하나로 합치면 다음과 같은 결과가 나온다.

https://jwt.io/

python 에서는 이 모든것을 쉽게 해줄 수 있는 모듈 jwt 가 존재한다.

사용법을 알아보자.

  • 로그인 인증 (Authentication) 을 수행해서 인증정보를 확인한다.

  • 맞으면 jwt.encode()

  1. 첫 번째 파라미터에 payload (여기선 user_id)
  2. 두 번째 파라미터에 장고의 SECRET_KEY
  3. 세 번째 파라미터에 algorithm 방식을 넣는다.

user_id 를 브라우저에 보내고 나중에 요청받을 때 user_id 로 db에 접근하여 어떤 유저인지 확인하면 된다.

SECRET_KEY 를 통해 header 와 payload 를 hash 하여 signature 를 만든다. 따라서 이 값이 절대 유출되면 안된다.

유출되면 해커가 이 값을 이용해 signature 를 복사해 낼 수 있다.

참고자료 :
1. 쉽게 알아보는 서버 인증 1편(세션/쿠키 , JWT) https://tansfil.tistory.com/58
2. [JWT] JSON Web Token 소개 및 구조 https://velopert.com/2389

profile
Backend Developer

0개의 댓글