본문 바로가기
프로그래밍/기타

[REST API] REST API의 Security With JWT

by 사바라다 2019. 11. 1.

안녕하세요. 오늘은 REST API에 대해서 아야기하는 마지막 시간입니다. 주제는 security입니다. security는 우리가 개발을 하면서 빼놓을 수 없는요소입니다. 하지만 귀찮아서, 기능 개발이 재밌어서, 시간이 없어서 등등 많은 이유로 많은 개발자들이 접근하지 않는분야기도 합니다.(예전의 저만 그렇게 생각했을 수도 있어요.. ㅎㅎ;) 오늘은 REST API에서의 security에 대해서 알아보도록 하겠습니다.

개요

REST API의 Security를 생각할 때 가장먼저 생각해야할 제약조건은 stateless입니다. stateless란 서버는 client의 로그인과 같은 application state를 기록하지 않는 다는 의미입니다. 우리가 일반적으로 알고 있는 basic, OAuth 등과 같은 Security 방법은 Session 등을 통하여 서버에 인증정보를 저장하였습니다. 그렇다면 stateless한 security라는 것은 어떤 걸까요?

컴퓨터 보안의 8대 원칙 by The Protection of Information in Computer Systems

먼저 The Protection of Information in Computer Systems라는 논문을 통해 컴퓨터 보안을 위한 8가지 원칙을 알아보도록 하겠습니다.

  • 최소 권한(Least Privilege): 유저는 필요한 작업에 대한 최소한의 권한만을 가지고 있어야 하며 더이상 필요없을 경우 그 권한은 수거되어져야합니다.
  • 기본 실패(Fail-Safe Defaults) : 명시적으로 "허가"되지 않은 모든 리소스들은 "거부"가 기본입니다.
  • 매커니즘의 경제성(Economy of Mechanism) : 설계는 최대한 단순해야합니다.
  • 완벽한 조정(Complete Mediation) : 모든 접근 시도는 검사되어져야합니다. 그러기 위한 설계가 필요합니다.
  • 열린 설계(Open Design) : 시스템 설계시 공격자의 무지에 의존해서는 안됩니다. 즉 모두가 아는 알고리즘을 사용해야 합니다.
  • 권한 분리(Separation of Privilege) : 권한을 하나만 가지고 있어서는 안됩니다. 사용자는 작은 권한들의 조합을 사용하는것이 좋습니다.
  • 최소한의 공통 메카니즘(Least common mechanism) : 공유 메카니즘 (예, /tmp 또는 /var/tmp 디렉토리 사용) 의 수와 그 사용을 최소화해야합니다. 공유 객체는 정보 흐름 및 의도되지 않은 상호작용에 대해 잠재적으로 위험한 채널을 제공할 수 있습니다.
  • 심리학적 수용성/사용의 편리함(Psychological acceptability/Easy to use) : 사용자가 일반적으로 사용했을때 자동적으로 보호 메커니즘이 적용될 수 있어야합니다.

REST API에 Security를 적용하기위한 방법

위의 설계 원칙을 기반으로 REST API에서의 Security를 어떻게 적용하면 좋을지 보겠습니다.

  • SSL(HTTPS) 사용
    • HTTPS를 사용하여 주고 받는 모든 통신은 암호화되기 때문에 Basic Auth와 같은 단순한 인증수단으로도 충분히 보안을 유지할 수 있습니다
  • password의 Hashing
    • password는 소중합니다. 때문에 저장될때 관리자도 알 수 없도록 Hashing을 하여 저장하는것이 좋습니다. 알고리즘으로는 MD5, SHA, bcrypt 등을 이용할 수 있습니다.
  • 정보를 URL 표시 제한
    • 사용자 이름, 패스워드, Token 등은 절대 URL에 표기하지 않는게 좋습니다. 아래와 같은 상황은 피합시다.
https://api.domain.com/user-management/users/{id}/someAction?apiKey=abcd123456789

 

 

  • 요청에 TimeStamp를 추가하는 것을 고려하자
    • brute force 공격 (전수조사)을 막는 방법으로 timestamp를 추가하여 요청시간과 서버시간을 비교하여 특정 범위에 들어야만 request를 받아들이는 등의 방법을 생각해 볼수 있습니다.

 

JWT(json web token) 이용

JWT는 Clame 기반의 토큰입니다. Clame 기반 토큰 방식이란 Token안에 사용자 정보 및 기타 데이터 등을 포함한다는 의미입니다. 일반적으로 사용하는 OAuth의 token을 생성하면 아래와 같이 token이 나옵니다.

{
    "access_token": "35aeeabf-3c36-4228-b074-9c8e23ba52c4",
    "token_type": "bearer",
    "refresh_token": "ad073a11-a23c-4a57-89b0-1672d695eb52",
    "expires_in": 466,
    "scope": "openid"
}

보시면 바로 아시겠지만 access_token은 token그 자체의 일만 할 수 있습니다. 만료일, 사용자 정보 등은 별도로 표기해야합니다. 이제는 jwt기반의 토큰을 보겠습니다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

jwt토큰은 위와 같은 형식입니다. "."을 기준으로 각기 다른값을 가지게 되며 3가지의 분할 할 수 있습니다.

  1. HEADER : 알고리즘 / token type
  2. PAYLOAD : data
  3. SIGNATURE : 서명

이렇게 나뉘어져 있습니다. 위의 jwt는 BASE64로 인코딩 되어있으며 해독하면 아래와 같습니다. 아래를 보시면 기본적인 정보가 기입되어져 있는것을 알 수 있습니다.

{
  "alg": "HS256",
  "typ": "JWT"
}
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  your-256-bit-secret
)

위변조는 어떻게 확인할 수 있을까요? 3번째의 서명을 통해서 서버는 정상인지 비정상인지 확인할 수 있습니다.  jwt의 서명은 header부분과 payload부분을 base64로 인코딩하고 header의 알고리즘을 공개키를 통해 암호화합니다. 그러면 서버에서는 이를 개인키로 해독해서 사용합니다. 이렇게 함으로써 위변조를 막을 수 있습니다.

마무리

이렇게 하여 우리는 stateless하게 보안을 어떻게 유지할 수 있을지 확인해보았습니다.

지금까지 1달정도는 계속해서 rest api와 관련된 이야기를 해보았습니다. 다음번에는 다른이야기로 찾아뵙겠습니다.

감사합니다.

참조

https://restfulapi.net/security-essentials/

https://jwt.io/

https://elfinlas.github.io/2018/08/12/whatisjwt-01/

댓글