눈으로 직접 확인하는 인증과 인가🤩

인증과 인가 비교

인증(Authentification)이란?

유저의 identification을 확인하는 절차가 인증이다. 인증에 앞서 먼저 유저의 아이디와 비번을 생성할 수 있는 회원가입 절차가 있어야 하겠다.

인가(Authorization)란?

유저가 요청하는 request를 실행할 수 있는 권한이 있는 유저인가를 확인하는 절차이다.

인증과 인가의 전체적인 플로우

✅ 최초 회원가입 과정

  1. 유저 아이디와 비번 생성
  2. 유저 비번 암호화 해서 DB 저장

✅ 로그인 진행 시 - 인증의 과정이 진행된다.

  1. 유저가 아이디와 비밀번호 입력
  2. 유저가 입력한 비밀번호는 암호화 되어 DB에 저장된 유저 비밀번호와 비교
  3. 일치하면 로그인 성공하고 클라이언트는 access token을 돌려받음

✅ 이후 로그인 한 유저가 추가 요청 시 - 인가의 과정이 진행된다.

  1. access token은 세션 스토리지, 로컬스토리지, 혹은 쿠키에 담겨 브라우저에서 잘 보관하고 있음
  2. HTTP는 stateless 즉, 이전 로그인 했던 걸 기억하지 못하기에 다음 요청 시 보관하고 있던 access token을 담아 요청을 보냄
  3. 서버에서는 유저가 보낸 access token을 복호화 하여 user id를 얻음
  4. user id를 통해 DB에서 해당 유저의 권한을 확인하여 충분한 권한을 가지고 있으면 해당 요청을 처리, 권한이 없는 경우 Unauthorized Response(401)혹은 다른 에러 코드 전송

상세 과정

💫 Q1. 위의 2번과정에서 그럼 서버 관리자는 유저의 비밀번호를 그대로 다 볼 수 있는 것일까?

아니다. 유저의 비밀번호는 절대로 비밀번호 그대로 DB에 저장되지 않는다. 그대로 들어오는 경우 내부 개발자는 인력이 비밀번호를 다 볼 수 있기에 꼭 암호화 해서 저장해야 한다. 비밀번호 암호에는 일반적으로 단방향 해쉬 함수가 사용되는데 단방향 해쉬 함수는 원본 메세지를 변환하여 암호화된 메세지인 다이제스트를 생성한다. 원본 메세지를 알면 암호화된 메세지를 알 수 있지만, 암호화된 메세지로는 원본 메세지를 구할 수 없기에 단방향이라고 한다.

예시) 
id가 "test password"일 때,  
0b47c69b1033498d5f33f5f7d97bb6a3126134751629f4d0185c115db44c094e

id가 "test password2"일 때,
d34b32af5c7bc7f54153e2fdddf251550e7011e846b465e64207e8ccda4c1aeb

그러나, 단방향 해쉬 함수도 Rainbow table이라는 미리 해쉬값을 계산해 놓은 테이블이 있기에 계산하려면 계산할 수 있고, 처리속도가 빠르다는 단점이 있다.(처리속도가 빠른만큼 공격자가 매우 빠른속도로 임의의 문자열의 다이제스트와 해킹할 대상의 다이제스트를 빠른 시간안에 많이 대조해볼 수 있기에 털릴 위험도 높아진다.)

💫 Q2. 해쉬 함수의 단점을 어떻게 보완할까?

일반적으로 SaltingKey Stretching이라는 두 가지 보완방법이 사용된다. Salting이란 실제 비밀번호 외에 추가적으로 랜덤데이터를 붙여서 해시값을 계산하는 것을 의미하고, Key Stretching이란 단방향 해쉬값을 반복해서 해쉬하는 것을 의미한다. 이런 두가지 방법을 활용해 다이제스트를 예측하기 더 어렵게 만드는 것이다.

💫 Q3. Salting과 Key Stretching은 누가 해줄까?

이 두 가지를 구현한 해쉬 함수 중 가장 널리 사용되는 것이 있는데, 바로 bcrypt이다.
아래는 실제 회원가입 시 password를 bcrypt hash 함수를 사용한 예이다.

프론트(나🙋‍♀️)가 다음과 같이 fetch함수를 통해 user의 정보를 백에게 POST의 방식으로 넘겨준다. (회원가입)

백엔드(🦸‍♂️)에서는 다음과 같은 코드를 통해 user가 작성한 비밀번호를 통해 다이제스트를 생성한다. 아래 코드의 bcrypt.hashpw를 통해 비밀번호가 다이제스트로 생성되어 DB에 저장될 것을 예상해 볼 수 있다.

DB에 아래와 같이 정보가 생성된다.

💫 Q4. 그럼 Access token은 언제 어떻게 생겨날까?

자 이제, user가 로그인을 할 것이다. 프론트에서는 아래 코드를 통해 유저가 입력하는 아이디와 비밀번호를 서버에 넘겨준다.

로그인에 성공했다! 그러면 백에서 access token이란 것을 돌려준다. 일반적으로는 로그인 한 후 비밀번호가 일치하면 메인으로 이동하겠으나, 콘솔을 통해 돌려받은 토큰을 확인해 보았다.

💫 Q5. 잠깐! 다시, 그런데 애초에 access token은 어떻게 생겨났지?

로그인에 성공했을 때, 먼저 서버에서 Access token을 생성할 것이다. 생성하는 방법은 여러가지가 있으나 그 중 가장 널리 사용되는 기술 중 하나가 바로 JWT(JSON Web Tokens)이다. 말 그대로 유저 정보를 담은 JSON 데이터를 암호화해서 클라이언트와 서버간에 주고받는 기술을 의미한다.

백엔드에서 아래와 같은 코드를 통해 유저가 로그인시 입력한 password를 암호화한 것과, 기존에 회원가입시 입력한 password를 암호화 한 것이 같으면, access token을 생성하고 있음을 알 수 있다. (jwt를 통해 access token을 생성한 후 SUCCESS 메세지와 함께 클라이언트에게 돌려주고 있다.)

JSON Web Token은 일반적으로 xxxxx.yyyyy.zzzzz와 같은 구조로 되어 있다. '.'으로 구분하여, 각각은 토큰의 형식과 사용된 알고리즘이 적혀 있는 Header와, 객체에 대한 내용을 담고 있는 Payload 그리고 마지막으로 메세지가 전달되는 길에 변경되지 않았음을 보장하고 있는Signature부분으로 나뉜다.

백엔드와의 통신과정에서 받은 나의 Access TokenJWT 공식페이지에서 decode 해보았다.

빨간 글씨의 Header를 통해 해당 토큰은 JWT토큰이며, HS256 알고리즘이 사용되었다는 것을 알 수 있다. 두 번째 핑크색 부분을 통해 내 데이터는 DB에 id: 21번으로 저장되어 있음을 알 수 있다. 일반적으로 해당 부분은 토큰이 중간에 탈취당하더라도 DB가 없으면 확인할 수 없도록 민감하지 않은 정보를 사용한다. 마지막으로, 파란색 부분은 signature부분을 나타낸다.

💫 Q6. 클라이언트는 전달받은 Access Token을 어떻게 사용할까?

전에도 언급했듯, HTTP는 내가 이미 인증의 과정을 거쳤다는 것을 모른다!! 그렇기에 이제는 요청 시에 내가 받았던 Access Token을 같이 실어 보냄으로써 '나 이미 인증받았어요!'라고 말하고 있는 것이다. 다음과 같이 프론트에서는 이후 통신에서 인가가 필요한 곳에 access token을 header에 실어 보낸다.

백에서는 프론트에서 요청시에 전달한 access token을 decode하여 위의 예시와 같이 ID:21이라는 정보를 받게 되고, DB에서 ID:21에 있는 유저 정보와 대조하여 이후 요청을 어떻게 처리할 지 결정한다.
(데이터가 너무 작게 나와 천사지훈님께서 다시 DB를 만들어서 캡처본을 전달해주셨다!! 아래의 경우 ID:4번으로 decode 되었을 것이다!!🤩)

마무리하며,

인증 인가 과정을 해보며 처음으로 백과 프론트가 만났고 나에게는 너무너무 신세계였다!!!! 백에서 오는 에러 메세지도 토큰도 너무 신기했다. HTTP 통신에 대해 처음 공부할 때, token이 무엇이고 어떻게 생긴 것인지 너무 궁금했는데, 오늘 인증인가를 진행해 보며 머리에 둥둥 떠다니던 개념들이 눈 앞에 보여 너무 신기했다. 프론트에서 요청을 보내고 받는 것은 직관적으로 보여 알겠는데, DB에 정보가 어떻게 저장되고 bcrypt함수는 어떤식으로 작성되고 jwt방식은 어떻게 적용하는지 등등이 추가적으로 궁금해 동기분들께 여쭈어보았다. 천사같은 지훈님 정현님 두 분께서 직접 코드와 DB를 보여주시고 token도 해독해주시며 지식을 나눔해주셨고 궁금했던 사항이 모두 해소되었다.
오늘 느낀 것은 크게 세 가지다.
우선... 너무 재밌다! 너무 신세계다!!!!!! 두 번째는 프로젝트 진행시에 반드시 반드시 반드시! 변수명을 맞추고 문서화해서 관리해야 멘붕이 오지 않을 것 같다고 생각했다. 마지막으로 동기분들 정말정말 감사합니다. 도움이 되는 프로트엔드 개발자가 되겠습니다.👶

좋은 웹페이지 즐겨찾기