인증이란?
- 사용자의 신원을 증명하는 것
- 예를들어 로그인하는 과정을 인증이라 한다.
- 로그인 하게 되면 JWT를 이용해 인증을 유지한다.
인증은 왜 필요한가?
- 우리 서비스를 누가 쓰며 어떻게 사용하고 있는지 추적이 가능하도록 하기 위해 필요합니다.
인증에 필요한 것은 무엇이 있을까요?
- id, Email, Password
- 가장 중요한 것은 password
비밀번호 어떻게 관리해야 하는가?
데이터베이스에 저장시 개인정보를 해싱하여 복원할 수 없도록 해야한다.비밀번호는 절대 그대로 저장하지 않는다.
통신시 개인 정보를 주고 받을때 ssl을 적용하여 암호화 (https)
임호화는 어떻게 할까요?
단방향 해쉬란?
- 본래 해쉬함수는 자료구조에서 빠른 자료의 검색, 데이터의 위변조 체크를 위해서 쓰이지만, 복원이 불가능한 단반향 해쉬함수는 암호화적 용도로 사용한다.
- (MD5, SHA-1)(둘은 보안취약), SHA-256등이 있다.
- '1234'를 SHA-256 해싱하면 다음과 같다.
- 그냥 보기에는 식별이 불가능할 정도로 보이지만, 같은 알고리즘으로 '1234' 다시 해싱하면 항상 같은 결과를 도출하는 문제점을 가지고 있다.
다시말해,원본을 유추할수 없지만 , 레인보우 테이블 같은 이용해서 원본값을 알아낼수 있다는 허점이 있다. 보안이라는 것은 100% 평생 완벽히 할수 없다. 원본값으로 바로 알아 낼수 없지만 수만은 경우의 수를 돌려서 유추해낼수 있다. 보안의 시간을 늦춰주는게 salting과 keyStretching이다.
salting & keyStretching?
말 그대로 소금치고 늘린다??!!
- 단순해시값이 해킹에 쉽게 노출되기 떄문에 Salting이라는 아이디어가 생겨났다.
- 입력한 비밀번호와 임의로 생성한 문자열(Salt)를 합쳐서 해싱해서 이 해시값을 저장하는 방법이다.
- 물론 이때에 비교를 위해 해시값과 소금값을 같이 저장해야 한다.
- 여기에 해커가 패스워드 무작위 대입을 통해 해시값을 계산하는데 필요한 시간을 대폭 늘리기 위해 Salting및 해싱을 여러번 반복해서 원본값을 유추하기 어렵게 만드는 것이 키 스트래칭이다.
bcrypt
Salting & Key Stretching 대표적 라이브러리
- bcrypt는 앞서 말한 개념들을 실제로 적용하기 편하게 해주는 대표적인 라이브러리
- 해시 결과값에 소금값과 해시값 및 반복횟수를 같이 보관하기때문에 비밀번호 해싱을 적용하는데 있어 DB설계를 복잡하게 할 필요가 없다.
- bcrypt를 통해 해싱된 결과 값(Digest)의 구조는 아래와 같다.
인가는 무엇인가?
- 해당 유저가 request에 해당하는 권한이 있는지 확인하는 절차
예시) 쿠팡에서 처음 회원가입을 하고 로그인을 하면 인증과정을 거친것이다. 주문목록 조회은 로그인이 되어 있어야 볼수 있다. 선제적인 로그인 과정 필요한 기능들이 있다. 권한이 있는지 확인해주는 절차가 인가이다.
Http의 특징은 무엇일까?
- 바로 request/response 요청과 응답.
- 📌statelee한 성질(저장하지 않는 성질)
예를 들어 장바구니 담아 좋아요 할때 계속 로그인하는 것은 너무 불편할 것이다.
서버는 사용자가 로그인 했을 경우, 로그인했다는 것을 어떻게 알수 있을까?
- 바로 header에 메타데이터를 보내서 확인한다.
- 이 메타정보를 바로 JSON Web Token일명 'JWT'라고 합니다.
- 토큰을 발급-> 프론트엔드 저장-> 인가를 해야하는 API기능때 토큰을 같이 보낸다.
JSON Web Token
헤더(header)
- 토큰의 타입과 해시알고리즘 정보가 들어간다.
- 헤더의 내용은 BASE64방식으로 인코딩해서 JWT의 가장 첫 부분에 기록된다.
내용(payload)
- 다음은 내용(payload)에 대한 내용이다.
- 만료시간을 나타내는 exp와 같이 미리 전의된 집합인 Registered Claim
- 공개용 정보 전달을 목적으로 하는 Public Claim
- 클라이어트와 서버간 협의하에 사용하는 Private Claim
서명(signiture)
-
JWT가 원본 그대로라는 것을 확인할때 사용하는 부분(우리 서버가 만들어낸 부분)
-
시그니처는 BASE64URL 인코드된 header와 payload 그리고 JWT secret(별도생성)을 헤더에 지정된 암호 알고리즘으로 암호화하여 전송한다.(복호화 기능)
-
프론트엔드가 jwt를 백엔드 API서버로 전송하면 서버에서는 전송받은 JWT의 서명부분을 복호화하여 서버에서 생성한 JWT가 맞는지 확인한다.
-
마치 계약서 위변조를 막기위해 서로 사인하는 것과 같다고 보면 편하다.
남의집에 들어갈때 우리열쇠로 들어가면 안되는것처럼 우리집에 들어올때도 우리의 키로 복구화 되면 우리서버에 데이터베이스에 1번에 아이디에 관련된거구나 알수있다.