인증 / 인가

기멜·2021년 11월 22일
1

study

목록 보기
2/3

📖 인증과 인가에 대해서 설명할 수 있다.

학습 목표
1. 인증, 인가에 대해 설명할 수 있다.
2. 단방향 해쉬가 무엇인지 설명할 수 있다.
3. salting & key stretching이 무엇인지 설명할 수 있다.
4. Bcrypt와 JWT가 무엇인지 설명할 수 있다.

  • 인증과 인가는 API에서 가장 자주 구현되는 기능 중 하나.
  • Private한 API는 물론이고 Public한 API도 기본적인 인증과 인가를 요구.

인증 (Authentication)

1. 인증

  • 유저의 아이디와 비번을 확인하는 절차
    (인증을 하기 위해선 먼저 유저의 아이디와 비번을 생성할 수 있는 기능이 필요)

1-1. 로그인 절차

  1. 유저 아이디와 비번 생성
  2. 유저 비번 암호화 해서 DB에 저장.
  3. 유저 로그인 -> 아이디와 비밀번호 입력
  4. 유저가 입력한 비밀번호 암호화 한후 암호화되서 DB에 저정된 유저 비밀번호와 비교.
  5. 일치하면 로그인 성공
  6. 로그인 성공하면 access token을 클라이언트에게 전송.
  7. 유저는 로그인 성공후 다음부터는 access token을 첨부해서 request를 서버에 전송함으로서 매번 로그인 해도 되지 않도록 한다.

1-2.유저 비밀번호 암호화

  • 유저의 비밀번호는 절대 비밀번호 그대로 DB에 저장 하지 않는다.
    • DB가 해킹을 당하면 유저의 비밀번호도 그대로 노출 된다.
    • 외부 해킹이 아니더라도 내부 개발자나 인력이 유저들의 비밀번호를 볼 수 있다.
  • 유저의 비밀번호는 꼭 암호화 해서 저장 해야 한다.
    • 그럼으로 DB가 해킹을 당해도 비밀번호가 그대로 노출되지 않으며
    • 내부 인력도 비밀번호를 알 수가 없음.
  • 비밀번호 암호에는 단방향 해쉬 함수(one-way hash function)가 일반적으로 쓰인다.
    • 단방향 해시 함수는 원본 메시지를 변환하여 암호화된 메시지인 다이제스트(digest)를 생성한다. 원본 메시지를 알면 암호화된 메시지를 구하기는 쉽지만 암호화된 메시지로는 원본 메시지를 구할 수 없어서 단방향성(one-way) 이라고 한다.
    • 예를 들어, "test password"를 hash256이라는 해쉬 함수를 사용하면 0b47c69b1033498d5f33f5f7d97bb6a3126134751629f4d0185c115db44c094e 값이 나온다.
    • 만일 "test password2"를 hash256 해쉬 함수를 사용하면 d34b32af5c7bc7f54153e2fdddf251550e7011e846b465e64207e8ccda4c1aeb 값이 나온다. 실제 비밀번호는 비슷하지만 해쉬 함수 값은 완전히 틀린것을 볼 수 있다. 이러한 효과를 avalance라고 하는데 비밀번호 해쉬 값을 해킹을 어렵게 만드는 하나의 요소이다.

1-3. Bcrypt

  • 단방향 해쉬 함수도 몇가지 취약점이 있다.
    • Rainbow table attack - 미리 해쉬값들을 계산해 놓은 테이블을 Rainbow table이라고 한다.
    • 해시 함수는 원래 패스워드를 저장하기 위해서 설계된 것이 아니라 짧은 시간에 데이터를 검색하기 위해 설계된 것이다 (Remember Set?). 그렇기 때문에 해시 함수는 본래 처리 속도가 최대한 빠르도록 설계되었다. 이러한 속성 때문에 공격자는 매우 빠른 속도로 임의의 문자열의 다이제스트와 해킹할 대상의 다이제스트를 비교할 수 있다(MD5를 사용한 경우 일반적인 장비를 이용하여 1초당 56억 개의 다이제스트를 대입할 수 있다). 이런 방식으로 패스워드를 추측하면 패스워드가 충분히 길거나 복잡하지 않은 경우에는 그리 긴 시간이 걸리지 않는다 (대부분 사용자의 패스워드는 길거나 복잡하지 않을 뿐 아니라, 동일한 패스워드를 사용하는 경우도 많다).
  • 단방향 해쉬 함수의 취약점들을 보안하기 위해 일반적으로 2가지 보완점들이 사용된다.
    • Salting
      • 실제 비밀번호 이외에 추가적으로 랜덤 데이터를 더해서 해시값을 계산하는 방법.
    • Key Stretching
      • 단방향 해쉬값을 계산 한 후 그 해쉬값을 또 해쉬 하고, 또 이를 반복하는 것을 말한다.
      • 최근에는 일반적인 장비로 1초에 50억 개 이상의 다이제스트를 비교할 수 있지만, 키 스트레칭을 적용하여 동일한 장비에서 1초에 5번 정도만 비교할 수 있게 한다. GPU(Graphics Processing Unit)를 사용하더라도 수백에서 수천 번 정도만 비교할 수 있다. 50억 번과는 비교할 수도 없을 정도로 적은 횟수다. 앞으로 컴퓨터 성능이 더 향상되면 몇 번의 반복을 추가하여 보완할 수 있다.

인가 (Authorization)

  • 유저가 요청하는 request를 실행할 수 있는 권한이 있는 유저인가를 확인하는 절차 이다.(해당 유저는 고객 정보를 볼 수 있는 있지만 수정 할 수는 없다)

인증은 쉽게말해 로그인이라고 생각하면 됩니다. 내가 이 사이트에 가입된 회원임을, 즉 특정 서비스에 일정 권한이 주어진-
내 계정으로'만' 할 수 있는 활동을 시도할 때
사이트가 내가 로그인 되어있음을 알아보고 허가를 해주는 겁니다.
로그인이 유지되는 상태에서 일어나는 일이라고 보면 되는거죠.
정리하자면, 인증은 사용자가 자기 계정을 사용할려고 할 때 ‘인증!’ 하고 멈춰세워서 로그인을 시키는 겁니다.
인가는, 그런 인증을 받은 사용자가 서비스 한에서 돌아다닐 때 서버가 얘가 로그인을 한 사용자라는 것을 알아보고
“응~ 어서와~” 하고 허가를 해주는겁니다.

서버 부담없이 이 인가를 구현하기 위해 고안된 게 ‘토큰 방식’인 JWT입니다. JSON Web Token.
이제 사용자가 로그인을 하면 토큰이라는 표를 출력해서 건내줍니다. 대신 찢어서 주지 않고 그냥 줍니다.
서버가 뭔가를 기억하고 있지 않다는 얘기죠. 인코딩 또는 암호화된 3가지 데이터를 이어붙인겁니다.
점이 두 군데 들어가 있습니다. 마침표를 기준으로 세 부분으로 나뉘는 겁니다.
각각 header, payload, verify signature로 구분됩니다.
지금부터 1번 헤더 / 2번 페이로드 / 3번 서명 으로 부르겠습니다.

2번 페이로드부터 시작합니다. 이걸 Base64로 디코딩해보면 JSON형식으로 여러 정보들이 들어있습니다.
이 토큰을 누가 누구에게 발급했는지, 이 토큰이 언제까지 유효한지 그리고 서비스가 사용자에게 이 토큰을 통해 공개하기 원하는 내용. 이를테면 사용자의 닉네임이나 서비스상의 레벨, 관리자 여부 등을 서비스 측에서 원하는대로 담을 수 있죠. 이걸 사용자가 악용하는 것을 방지하기 위해서 1번과 3번이 있는 겁니다.

1번 헤더와 2번 페이로드, 그리고 ‘서버에 감춰놓은 비밀 값’ 이 셋을 이 암호화 알고리즘에 넣고 돌리면 3번 서명 값이 나오는 겁니다.

서버는 요청에 토큰 값이 실려들어오면 1,2번의 값을 ‘서버의 비밀 키’와 함께 돌려봐서 계산된 결과값이 3번 서명 값과 일치하는 결과가 나오는지 확인합니다. 만약 2번 페이로드의 정보가 서버가 아닌 누군가에 의해 조금이라도 수정되었다면 당연히 안 맞겠죠? 정보를 조작한 사용자이거나 해커인걸로 간주돼서 거부됩니다.
3번 서명 값과 계산 값이 일치하고, 유효기간도 지나지 않았다면 그 사용자는 로그인 된 회원으로서 인가를 받는겁니다.

이처럼 시간에 따라 바뀌는 어떤 상태값을 안 갖는 것을 stateless하다고 합니다.
좋긴하지만 이 방법에는 치명적인 결함이 있습니다.
내가 쥐고 있을 필요가 없어서 편하기는 한데, 그래서 통제는 못한다.

profile
프론트엔드 개발자를 꿈꾸는 도화지 위를 달리는 여자

0개의 댓글