인증과 인가
-
인증이란?
유저가 누구인지 확인하는 절차, 회원가입하고 로그인 하는 것.
-
인가란?
유저에 대한 권한을 허락하는 것.
- 누가, 언제, 어떻게 쓰고 있는가를 파악하기 위해 어떤 사이트에서든 인증, 인가가 있음.
- 인증과 인가는 API에서 가장 자주 구현되는 기능중 하나.
- Private한 API는 물론이고 Public한 API도 기본적인 인증과 인가를 요구.
인증
Q. 어떻게 하면 정보를 첨부해 통신을 보낼 수 있을까? 민감한 정보는 아니면서 일정시간 동안 유효하게, 그리고 도용되지 않게.
opt1. 아이디와 비밀번호를 같이 보낸다. => 매번 서버에서 확인을 해야 함, 정보의 민감성
opt2. 시간제한이 있는 임시 아이디를 보낸다 => 어떤 유저인지 파악하기 힘듦, 그 유저의 정보를 또 따로 저장을 해야 함.(실제 유저 정보와 맵핑을 따로 해야 함)
opt3. 일정 시간 동안 인가에 유효한 정보로 대체한다. ==> JWT(JSON Web Tokens) 이용
======= JWT ========
- table ID를 준다.
- 그 정보를 JSON 형태로 전달(객체)
- 유효기간도 전달
- { "id": 1,
"exp": 2019_12_19
}
- http headers(주요한 내용을 넣는)에서 이용할 수 있도록 JSON 을 'token'화 함.
- '.'을 기준으로 3부분으로 나뉘어짐.
- 첫번째, 두번째는 코드화(encoding), 누구든 decode 할 수 있음
- 마지막은 암호화(복호화를 아무나 하지 못함, 웹코드를 서버한 페이지는 할 수 있음), 도용의 문제를 막기 위해
- 다른 서버는 복호화를 할 수 없음. => 인가가 안 됨
- 서버가 직접 발행한 웹토큰만 복호화할 수 있음
- Authorization header 부분에 같이 첨부해서 보냄. 프론트에서 리퀘스트가 있으면 저장하고 있던 토큰을 백에 첨부해서 같이 보냄.
Q. 유저의 비밀번호 암호화는 어떻게 해야 할까?
-
유저의 비밀번호는 절대 비밀번호 그대로 DB에 저장 하지 않음.
DB가 해킹을 당하면 유저의 비밀번호도 그대로 노출될 뿐더러 내부 개발자나 인력이 그 정보를 볼 수 있음. ==> 유저의 비밀번호는 꼭 암호화 해서 저장!!
-
비밀번호 암호에는 단방향 해쉬 함수(one-way hash function)가 일반적으로 쓰임.
단방향 암호화. (복호화가 안 되는 암호, 원본의 문자를 알아낼 수가 없음), 외부에서 정보가 해킹당했을때, 내부에서 정보가 유출될 때를 모두 대비해 단방향 암호화로 만듦.
Q. 암호화된 문자의 원본을 어떻게 알 수 있을까?
- 동일한 알고리즘을 이용하면 동일한 값이 나옴.
- 복호화해서 확인할 수 없기 때문에 똑같은 알고리즘을 이용해 동일한 결과값이 나오면 같은 값인 것을 알 수 있음. ==> 암호화값이 다르면 원본값이 다른 것. 유저의 비밀번호 원본 문자는 서버에서 알 수가 없음.
- 클라이언트가 암호화하는 것이 아니라 서버쪽에서 암호화 하는 것. 백에서 암호화를 맞춰봄.
단방향 암호화를 decoding 하는 방법
*Bruceforce Attack: 무식하게 같은 값이 나올 때까지 모든 암호값을 다 때려 맞춰보는 것. 조합 가능한 숫자와 문자, 특수기호 등을 다 조합해 봐야 하므로 시간이 너무 많이 걸림.
*Rainbow Atack: 미리 계산된 테이블을 갖고 조합해보는 것. 서칭을 해봄으로써 원본값을 찾을 수 있음.
- 'rainbow attack'이 가능한 이유: 해쉬 암호화는 연산화되는 시간이 짧음. 비밀번호를 암호화하기 위해 만든 알고리즘이 아니기 때문에 누구라도 쉽게 값을 찾아낼 수 있음.
기존의 단방향 해쉬에서 진화한 암호 알고리즘 ===>>>
'Bcrypt': 1) Salting : 원본값에 '소금을 뿌리듯이' random값을 추가 하는 것.
2) Key Chaining : 연산을 느리기 위해 해쉬 값이 구해지면 그 해쉬 값을 기반으로 또 해쉬를 하고 해쉬를 하고 n번 하는 것. 최종값을 저장. => rainbow attack이 어려워짐.
==> 단방향 해쉬 함수의 단점을 보완
인가
:유저가 요청하는 request를 실행할 수 있는 권한이 있는 유저인가를 확인하는 절차.
- 'JWT'를 쓰면 인가가 수월함. 서버가 유저 정보를 갖고 있으므로 데이터에서 유저의 권한 정보도 읽어들이면 됨.
- 'access token'을 통해 해당 유저 정보를 얻을 수 있음으로 해당 유저가 가지고 있는 권한(permission)도 확인 가능.
Authorization 절차
- Authentication 절차를 통해 access token을 생성한다. access token에는 유저 정보를 확인할 수 있는 정보가 들어가 있어야 한다 (예를 들어 user id).
- 유저가 request를 보낼때 access token을 첨부해서 보낸다.
- 서버에서는 유저가 보낸 access token을 복호화 한다.
- 복호화된 데이터를 통해 user id를 얻는다.
- user id를 사용해서 database에서 해당 유저의 권한(permission)을 확인하다.
- 유저가 충분한 권한을 가지고 있으면 해당 요청을 처리한다.
- 유저가 권한을 가지고 있지 않으면 Unauthorized Response(401) 혹은 다른 에러 코드를 보낸다.
// reference: https://stackoverflow.com/c/wecode/questions/125