서비스에 인증 붙이고 있다.
복잡하게 구성할 필요 없으니 간편하고 대중적인 Google OAuth를 이용하고 있다.
현재 우리 구조도를 따지면 프론트와 백단이 분리되어있다.
즉 인증 시작은 프론트인데, 인증 처리는 백엔드에서 진행해야한다.
프론트와 백엔드 사이에서 인증 정보를 교환해야하는데, 거기에 Google이 껴있는 것이다.
어떻게 구성될지는 천천히 설명할테니 일단 OAuth부터 알아보자
OAuth란
Open Authorization, 인가를 위한 개방형 표준 프로토콜이다.
핵심은 비번 공유 안하고, 권한을 다른 앱에 위임(니가해)하는 것이다.
Google 로그인 생각하면 편한데,
우리는 다른 앱에서 구글로 로그인하기 눌렀을 때, 패스워드 없이 그냥 인증을 진행한다.
인증을 하면? 그 권한이 인가되어 앱에서는 인증을 직접 안했는데 이용 권한을 부여한다.
인증(Authentication) VS 인가(Authorization)
OAuth를 이해하려면 인증과 인가를 구분할 줄 알아야한다.
인증은 "내가 누군지" 증명하는 과정이다.(예: ID/비밀번호로 로그인하기)
인가는 "내가 뭘 할 수 있는지" 권한을 확인하고 부여받는 것이다.
호텔 이용을 생각하면 이해가 빠른데,
우리는 호텔에 들어가서 카운터에서 우리의 인적사항을 가지고 인증을 받는다.
인증이 되면 카운터에서는 우리에게 키 카드를 준다.
키 카드는 모든 방을 열 수는 없지만, 우리에게 배정된 객실에 대한 접근 권한을 인가 받는다.
심지어 키 카드만 있으면 당신이 아니더라도 객실에 접근이 가능하다.
만약 당신이 다시 카운터로 가서 인증을 하고, 이전 키 카드를 도난당했다고 하면 기존 카드는 정지되고 다시 새로운 카드를 받는다.
OAuth 구성요소
OAuth를 사용하면서 보게될 몇가지 용어가 존재한다.
Resource Owner(리소스 소유자): 개인정보라는 리소스를 가진 사용자, 바로 우리들이다.
Client(클라이언트): 인증에서 클라이언트는 우리가 아니다. 권한을 요청하는 써드파티 애플리케이션(우리가 만들 프로젝트)가 바로 Client다.
Authorization Server(인가 서버): 인증에서 서버는 권한을 부여하는 주체이며 Access Token을 발급한다.
Resource Server(리소스 서버): 실제 자원(데이터)를 보유하고 Access Token을 검증한다.
Server가 두개라서 헷갈릴 수 있는데, Google을 기준으로 보자면 Google 서비스 범위 내에서 권한 부여랑 검증하는 포인트랑 개별로 있다고 보면 된다.
Access Token(접근 토큰): Client가 리소스에 접근하기 위해 사용하는 키 카드라고 보면 된다. 매번 인증받기는 귀찮으니 간단하게 토큰으로 권한을 검증하는 것이다.
Scope(범위): Client가 요청하는 권한의 구체적인 범위인데 Google 인증 같은 경우는 이메일이나 프로필 사진등이 해당된다.
Google OAuth는 어떻게 진행되는가.
일단 시작은 프론트다.
프론트 화면에 Google로 로그인 버튼을 마련한다.
React -> Google
로그인 버튼 클릭 시, 브라우저에서 Google 인증 페이지로 리다이렉트 시킨다.
이때 React는 URL에 다음 정보를 포함해서 요청을 보낸다.
response_type=code: 인증 코드좀 주세요
client_id=...: 구글에 등록된 제 아이디입니다.(공개된 정보)
scope=... :이메일이랑 프로필 사진좀요
redirect_uri=우리 백엔드 서버 callback 주소
redirect_uri이 중요한데, 인증이 끝나면 사용자를 해당 주소로 다시 보내달라는 뜻이다.
즉, 사용자가 Google 페이지에서 정보 제공 동의 화면에서 '허용' 누르면 이제 백엔드로 간다는 것이다.
Google -> FastAPI
구글에서 이동할때 우리는 response_type으로 code를 요청했다.
FastAPI에서는 Google에서 전해준 code를 받고
다시 Google에 요청을 보낸다.
FastAPI -> Google
전달 받은 code와 함께,
절대로 노출되면 안되는 client_secret 정보를 가지고
Google의 토큰 엔드포인트에 요청을 보낸다.
Google은 code랑 client_secret이 모두 유효한지 확인하고,
유효하다면 FastAPI에게 Response로 Access Token을 발급한다.
FastAPI 부가 처리
이제 유효한 토큰 정보를 또 받았으니
Google 리소스 서버에 토큰과 관련된 사용자 정보를 요청하고,
해당 정보로 DB에 유저 정보를 추가하거나 업데이트를 할 수 있다.
필요하다면 우리 서비스에 맞게
PyJWT 등의 라이브러리로 전용 JWT을 생성도 가능하다.
우리만의 정보를 담아야할 필요가 있고,
Access Token을 검증하기 위해 Google에 의존적이 되기 때문에
효율적인 검증을 위해서 자체적인 JWT으로 관리하는 것이다.
FastAPI -> React(응답)
이제 모든 처리가 완료되었으니 FastAPI는 React에게 로그인 성공 응답을 보낸다.
응답을 보낼때는 이제 React 쪽에서 사용될 Access Token 또는 JWT 토큰을 가져다가 보내준다.
React -> FastAPI(요청)
사용자는 이제 마이 페이지등의 인증이 필요한 API를 요청할 떄마다.
자연스럽게 Authorization 헤더에 JWT 토큰을 'Bearer 토큰"으로 담아 보낸다.
React는 자동으로 토큰 담아 보내니 복잡하게 관리할 필요 없고,
백엔드는 헤더만 확인해서 토큰이 위변조 됬는지 않았는지, 만료 여부만 체크하고 검증을 한다.
정리
위 구조를 통해 Google은 최초 1회 인증만 진행하도록 하고,
이후부터는 복잡한 인증 없이 아주 빠르게 검증만 들어가는 것으로 인증 구조가 완성된다.