인증(Authentication) & 인가(Authorization)

seoltang·2022년 1월 17일
0

인증 (Authentication)

인증은 왜 필요할까?

우리 서비스를 누가 쓰는지, 어떻게 사용하는지 추적이 가능하도록 하기 위해 필요하다.

인증에 필요한 것은 무엇이 있는가?

아이디, 이메일주소, 비밀번호 등이 있다. 이 중 가장 중요한 것은 비밀번호이다.

비밀번호는 어떻게 관리해야 하는가?

비밀번호는 암호화되어 관리하도록 법규상으로 강제된다.

Database에 저장 시 개인정보를 해싱하여 복원할 수 없도록 한다.

단방향 해쉬

  • 본래 해쉬(hash)함수는 자료구조에서 빠른 자료의 검색, 데이터의 위변조 체크를 위해서 쓰이지만, 복원이 불가능한 단방향 해쉬 함수는 암호학적 용도로 사용한다.
  • 단방향 해쉬 함수(one-way hash function)는 원본 메시지를 변환하여 암호화된 메시지인 다이제스트(digest)를 생성한다. 원본 메시지를 알면 암호화된 메시지를 구하기는 쉽지만 암호화된 메시지로는 원본 메시지를 구할 수 없어서 단방향성(one-way)이라고 한다.
  • (MD5, SHA-1)(둘은 보안 취약), SHA-256 등이 있다.
  • '1234'를 SHA-256 해싱하면 다음과 같다.
    03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4
  • 결과만 봐서는 당장 식별이 불가능하므로 완벽해보인다. 하지만 같은 알고리즘으로 '1234'를 다시 해싱하면 항상 같은 결과가 도출된다.

Salting & Key Stretching

Salting

  • 단순해쉬값이 해킹에 쉽게 노출되기 때문에 Salting이라는 아이디어가 생겨났다.
  • 입력한 비밀번호와 임의로 생성한 문자열(Salt)를 합쳐서 해싱해서 이 해시값을 저장하는 방법이다.
  • 이때 비교를 위해 해시값과 소금(Salt)값을 같이 저장해야 한다.

Key Stretching

  • 여기에 해커가 패스워드 무작위 대입을 통해 해시값을 계산하는 데 필요한 시간을 대폭 늘리기 위해 Salting 및 해싱을 여러 번 반복해서 원본 값을 유추하기 어렵게 만드는 것이 키 스트렛칭(Key Stretching)이다.

bcrypt

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

  • bcrypt는 Salting과 Key Stretching을 적용하기 편하게 해주는 대표적인 라이브러리이다.
  • 다양한 언어를 지원하고 있으며, 사용이 간편하여 쉽게 적용 가능하다.
  • bcypt는 hash 결과값에 소금값과 해시값 및 반복횟수를 같이 보관하기 때문에 비밀번호 해싱을 적용하는 데 있어 DB 설계를 복잡하게 할 필요가 없다.
  • bcrypt를 통해 해싱된 결과 값(Digest)의 구조는 아래와 같다.

인가 (Authorization)

  • 해당 유저가 request에 해당하는 권한이 있는지 확인하는 절차

Authorization 절차

  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의 특징 중 하나는 stateless(저장하지 않는 성질)이다. 서버는 사용자가 로그인한 후 물건을 구매하려고 할 경우, 로그인했다는 것을 어떻게 알 수 있을까?
→ headers에 메타데이터를 보내서 확인한다. 이 메타정보를 바로 JWT(JSON Web Tokens)라고 한다.

JWT (JSON Web Tokens)

access token을 생성하는 방법은 여러 가지가 있는데, 그 중 가장 널리 사용되는 기술 중 하나가 JWT(JSON Web Tokens)이다.
JWT는 유저 정보를 담은 JSON 데이터를 암호화해서 클라이언트와 서버 간에 주고 받는 것이다.

헤더(header)

  • 토큰 타입, 해시알고리즘 정보가 포함된다.
  • 헤더의 내용은 BASE64 방식으로 인코딩해서 JWT의 가장 첫 부분에 기록된다.
  • ex) {"alg": "HS256", "typ": "JWT"}

내용(payload)

  • 만료시간을 나타내는 exp와 같이 미리 정의된 집합인 Registered Claim
  • 공개용 정보 전달을 목적으로 하는 Public Claim
  • 클라이언트와 서버 간 협의 하에 사용하는 Private Claim
  • 위의 세 가지 요소를 조합하여 작성한 뒤 BASE64 인코딩하여 두 번째 요소로 위치한다.
  • ex) {"user-id": 1, "exp": 1539517391}

header와 payload는 BASE64 인코딩한 것이므로(암호화한 것이 아님) 누구나 원본을 볼 수 있으니 개인정보를 담아서는 안 된다.

서명(signature)

  • JWT가 원본 그대로라는 것을 확인할 때 사용하는 부분이다.
  • 시그니쳐는 BASE64URL 인코드된 header와 payload 그리고 JWT secret(별도 생성)을 헤더에 지정된 암호 알고리즘으로 암호화하여 전송한다. (복호화 가능)
  • 프론트엔드가 JWT를 백엔드 API 서버로 전송하면 서버에서는 전송받은 JWT의 서명 부분을 복호화하여 서버에서 생성한 JWT가 맞는지 확인한다.
  • 마치 계약서의 위변조를 막기 위해 서로 사인하는 것과 같다고 볼 수 있다.

생성된 JWT의 예시

profile
공부 기록

0개의 댓글