모든 사용자가 액세스할 수 없는 콘텐츠를 보호해야 하는 경우 인증이 필요하다.
가령 특정한 백엔드 라우트들은 보호가 필요하고, 모든 사람이 접근할 수 있으면 안된다.
즉, 리액트 앱과 같은 프론트엔드 앱이 특정 백엔드 리소스에 접근하려 할 때, 접근권한이 주어지기 전에 반드시 인증을 받아야 한다.
모든 것은 사용자 자격(user credentials) 증명을 가지고 요청을 보내는 것에서 시작한다.
허가 응답의 모양은 네/아니오
모양만으로는 충분하지 않다.
서버가 네
라고만 대답하면 나중에 클라이언트가 서버에 다시 요청을 보낼 경우, 과거에 접근 승인을 받을 때 사용한 정보를 다시 붙이면 되니까 허가 받은 것 처럼 조작할 가능성이 있다.
따라서 서버에서는 단순한 네/아니오
모양이 아니라, 과거에도 서버에서 허가를 받았다는 증거에 대한 서버에서 검증한 어떤 것을 회신해줘야 한다.
그러므로 보호된 리소스에 접근하려는 미래의 요청에 그냥 네
만 보여줘서는 안된다. 조작할 수도 있기 때문이다.
이를 위해 서버 측 세션이나 인증 토큰을 사용한다.
서버 측 세션은 대중적인 솔루션으로, 특히 프론트엔드와 백엔드가 분리되지 않은 풀스택 앱에서 자주 사용된다.
백엔드가 클라이언트 관련 정보를 반드시 저장해야 하기 때문에 백엔드와 프론트엔드 사이에 긴밀한 결합이 필요하다.
하지만 리액트 앱은 클라이언트와 긴밀히 결합되어 있지 않고 클라이언트 측 정보도 저장하지 않는 백엔드 API를 자주 사용한다.
리액트 앱은 프론트/백이 분리되어 있기 때문에 리액트 앱에서 서버측 세션을 사용하는 것은 이상적이지 않다.
사용자가 로그인하고 인증된 후, 서버에 고유 식별자를 저장하는 것이다.
(Store unique identifier on server, send same identifire to client.)
기본적으로 "네"를 서버에 저장하고 ID를 이용해 그 대답을 특정 클라이언트와 연결하여 그 ID를 다시 클라이언트한테 보낸다.
클라이언트는 이후 요청에서 해당 ID를 전송하여 보호된 리소스에 접근한다. ID는 "네"라는 대답과 연동되어 서버에 저장되어 있기 때문에 서버는 이 클라이언트가 보호된 리소스에 접근할 권한이 있는지 확인할 수 있다.
(Client sends identifier along with requests to protected resources.)
사용자가 유효한 자격 증명을 전송한 후, 서버에서는 허가 토큰을 생성하지만 저장은 하지 않는다.
(Create (but not store) "permission" token on server, send token to client.)
토큰은 기본적으로 알고리즘에 따라 생성된 스트링으로 몇 가지 정보를 포함한다.
백엔드에서 토큰을 생성하고 그것을 다시 클라이언트에게 전송한다.
토큰을 생성한 백엔드만 해당 토큰의 유효성을 확인하고 검증할 수 있다.
백엔드만 알수 있는 개인키를 활용해 토큰을 생성하기 때문이다.
이후 다시 클라이언트가 백엔드에 요청을 보낼 때 해당 토큰을 요청에 첨부하여 보내면, 백엔드는 토큰을 살펴보고 검증하고 또 그 토큰이 바로 그 백엔드에서 만들어진 토큰인지 확인한다. 유효한 토큰이라는 결론이 나면 보호된 리소스에 대한 접근이 승인된다.
(Client sends token along with requests to protected resources.)
이 부분은 백엔드 부분으로 backend > auth.js에 작성된 nodeJS로 작성된 부분
결국 서버는 사용자가 로그인하면 인증 토큰을 포함한 응답을 회신한다.
그러면 클라이언트 측 리액트 앱에 토큰을 저장하여, 이후에 보낼 요청에 이 토큰을 첨부하여 보내면, 해당 토큰을 사용자의 로그인 여부를 판단하는 인디케이터(지표)로 사용한다.
그러면 사용자라 로그인한 경우 로그아웃 버튼이 보이도록 UI를 업데이트 할 수도 있고, 현재 사용자가 로그인 상태인지 아닌지 확인할 수 있다.