[ Session ] 인증과 인가 (Authentication & Authorization)

Hailee·2020년 12월 7일
0

 > wecode 

목록 보기
7/11
post-thumbnail

인증, 인가란 무엇일까?

  • API에서 가장 자주 구현되는 기능 중 하나
  • Private, Public한 API 속성에 구애받지 않고 모두 기본적인 인증, 인가를 요구함

웹 개발자라면 필수로 이해하고 있어야 하는 지식..! 각 절차와 암호화, JWT등에 대해서 배워보았던 세션 👩‍💻

학습목표

  1. 인증이란 무엇인가?
  2. 비밀번호 암호화는 어떻게 이루어지는가?
  3. 단방향 해쉬함수 & 레인보우 테이블 어택
  4. 설팅키스트레칭, 그리고 bcrypt
  5. 인가란 무엇인가?
  6. JWT란?

인증 (Authentication)

  • User의 identification을 확인하는 절차
    : 회원가입, 로그인아이디, 이메일주소, 비밀번호, etc 확인하는 절차
  • why?
    : 우리 서비스를 누가 쓰는지
    : 어떻게 사용하는지
    추적 가능하도록 인증이 필요!

인증을 하기 위해 나는 지금까지 회원가입 기능 구현을 해왔던 것...!
항상 암호화 복호화 이런게 궁금하긴 했는데, 직접 구현해본 적은 한번도 없었다🥺🥺
이번 기회에 드디어..! 해보는구나...!

우선 로그인 절차는 어떻게 되는지 생각해보자.
지금까지 로그인은 그저 아이디&비밀번호를 입력받고, DB에서 일치하는 것이 있는지 확인한 후, 로그인 성공처리를 하는 것일 뿐이었다.

과연 인증 절차가 포함된 로그인 절차는 어떻게 될까?

1) 로그인

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

2) 비밀번호 관리는?

  • 시스템이 인터넷에서 격리된 네트워크에 위치하는 경우나 예외적인 개인정보 항목을 다루는 경우를 제외하고는
    국가에서 권고하는 상용 암호화 알고리즘을 이용해 개인정보를 암호화하도록 법적으로 규정되어 있다.
  • Database에 저장 시 개인정보를 해싱하여 복원할 수 없도록 함.
    : DB가 해킹당해도 암호화되어 저장되었기 때문에 유저의 비밀번호는 노출되지 않는다
  • 통신 시 개인정보를 주고받을 때 SSL을 적용하여 암호화 (HTTPS로 전송4)

암호화는 어떻게 하는가?

1) 단방향 해쉬(one-way hash function)

  • 본래 hash 함수는 자료구조에서 빠른 자료의 검색, 데이터의 위변조 체크를 위해 쓰이지만
    복원이 불가능한 단방향 해쉬함수는 암호학적 용도로 사용
  • (MD5, SHA-1 - 보안 취약), SHA-256 등
  • 단방향 해시 함수는 원본 메세지를 변환하여 암호화된 메세지인 digest를 생성한다.
    : 원본을 알면 암호화된 메세지를 구하기 쉽지만, 암호화된 메세지만으로는 원본 메세지를 구할 수 없어서 one-way
    In [21]: import hashlib
-
    In [22]: m = hashlib.sha256()
-
    In [23]: m.update(b"test password")
-
    In [24]: m.hexdigest()
    Out[24]: '0b47c69b1033498d5f33f5f7d97bb6a3126134751629f4d0185c115db44c094e'
-
    In [25]: m = hashlib.sha256()
-
    In [26]: m.update(b"test password2")
-
    In [27]: m.hexdigest()
    Out[27]: 'd34b32af5c7bc7f54153e2fdddf251550e7011e846b465e64207e8ccda4c1aeb'

실제 비밀번호는 비슷하지만, 해시함수 값은 완전히 틀리다
: avalance - 비밀번호 해쉬값 해킹을 어렵게 만듦

  • '24'를 SHA-256으로 해싱하면 👉🏻 겁나 길다
  • 결과는 완벽해보인다(당장 식별이 불가능하므로)
    하지만 같은 알고리즘으로 다시 '24' 라고 해싱하면 항상 같은 결과가 도출된다.

단방향 해쉬 함수의 취약점은? 🤯 🤯

Rainbow Table attack
👉🏻 가능한 모든 경우의 해시값을 미리 유추해둔 테이블

  • 본래 보안, 저장을 위해 설계된 것이 아닌, 단시간에 데이터 검색하기 위해 설계된 함수
    👉🏻 단시간에 비밀번호 뚫리게 되는 것..!!!!!

SALTING & KeyStretching


단방향 해쉬 함수의 취약점을 보완하기 위해 사용되는 2가지!

salting

  • 실제 비밀번호 이외에 추가적으로 랜덤 데이터를 더해서 해시값 계산하는 방법

key stretching

  • 단방향 해쉬값을 계산한 후 그 해쉬값을 또 해쉬하고.. 계속 반복하는 것!

이러한 salting, key stretching을 구현한 해쉬 함수 중 가장 널리 사용되는 것이 바로 bcrypt!

bcrypt

Salting & Key Stretching 대표적 라이브러리

  • bcrypt는 앞서 말한 개념들을 실제로 적용하기 편하게 해주는 대표적인 라이브러리
  • 다양한 언어 지원, 쉽게 적용 가능..!
  • bcrypt는 hash 결과값에 소금값, 해시값 및 반복횟수를 같이 보관하기 때문에
    비밀번호 해싱 적용에 있어 DB 설계를 복잡하게 할 필요가 없다
  • bcrypt를 통해 해싱된 결과값(Digest)의 구조는 이런 식..! 👇🏻👇🏻

JWT(JSON Web Tokens)

  • 유저가 로그인에 성공한 후 백엔드 서버가 access token 라는 암호화된 유저 정보를 첨부해서 클라이언트에게 request를 보낸다.
## 유저 로그인
POST /auth HTTP/1.1
Host: localhost:5000
Content-Type: application/json
{
    "username": "joe",
    "password": "pass"
}
## access token
HTTP/1.1 200 OK
Content-Type: application/json
{
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6MSwiaWF0IjoxNDQ0OTE3NjQwLCJuYmYiOjE0NDQ5MTc2NDAsImV4cCI6MTQ0NDkxNzk0MH0.KPmI6WSjRjlpzecPvs3q_T3cJQvAgJvaQAPtk1abC_E"
}

프론트 서버에서 access token을 통해 복호화 후 사용자 및 정보 확인 후

{
    user_id = 1 
}

브라우저의 storage에 저장 후 다음 요청마다 비교!


이렇게 access token 생성 방법은 여러가지가 있는데, 가장 널리 사용되는 기술중 하나가 바로 JWT (JSON Web Tokens)
👉🏻 유저 정보를 담은 JSON 데이터를 암호화해서 client, server 간 주고받는 것!

왜 ID, PW 대신 Token?

  • 성능
    : No heavy bcrypt call, just a simple hash
  • 클라이언트 서버의 저장 공간
    : No actual ID and password stored in the client such as cookie.
    : Also, token is very server specific - not reused in any other site.

  • header
    : 토큰의 타입, 해시알고리즘 정보 포함(복호화를 위해)
  • payload
    : exp 등 만료시간을 나타내는 공개 클레임
    : 클라이언트, 서버간 협의하에 사용하는 비공개 클레임 (비공개 유저정보)
  • 서명
    : JWT가 원본 그대로라는 것을 확인할 때 사용
    : BASE64URL로 인코딩 된 header, payload, JWT secret을 헤더에 지정된 암호 알고리즘으로 암호하하여 전송
    프론트엔드가 JWT를 백엔드 API 서버로 전송하면 서버에서는 전송받은 JWT의 서명부분을 복호화하여
    서버에서 생성한 JWT가 맞는지 확인

인가 (Authorization)

  • 사용자가 서버에 로그인하면 해당 사용자가 맞는지 확인하는 과정!
    : user가 요청하는 request를 실행할 수 있는 권한이 있는 유저인가?
    👉🏻 해당 유저는 고객 정보를 볼 수 는 있지만 수정할 수는 없다.. etc
  • 인가 또한 JWT를 통해 구현될 수 있다.
    : access token을 통해 해당 유저 정보를 얻을 수 있으므로
    해당 유저가 가지고 있는 권한(permission)도 확인할 수 있다.

인가 절차는 어떻게 되는가?

  1. Authentication 절차를 통해 access token을 생성한다. access token에는 유저 정보를 확인할 수 있는 정보가 들어가 있어야 한다 (예를 들어 user id).
  2. 유저가 request를 보낼때 access token을 첨부해서 보낸다.
  3. 서버에서는 유저가 보낸 access token을 복호화 한다.
  4. 복호화된 데이터를 통해 user id를 얻는다.
  5. user id를 사용해서 database에서 해당 유저의 권한(permission)을 확인하다.
  6. 유저가 충분한 권한을 가지고 있으면 해당 요청을 처리한다.
  7. 유저가 권한을 가지고 있지 않으면 Unauthorized Response(401) 혹은 다른 에러 코드를 보낸다.
  • HTTP의 특징은?
    : request / response 요청 & 응답
    : stateless한 성질 (저장하지 않는 성질)
    👉🏻 각각이 독립적 / 이전의 요청을 기억하지 못함
  • 서버는 사용자가 로그인 했을경우, 'headers'에 메타데이터를 보내서 확인
profile
웹 개발 🐷😎👊🏻🔥

0개의 댓글