[TIL No.26] Ouath 인증방식
오늘의 학습내용
#1 OAuth
(1) OAuth의 개념
OAuth(Open Authorization)란, 웹사이트 또는 응용프로그램(이하 서비스로 통합서술)의 사용자가 로그인을 해서 서비스를 이용하고 싶은 경우에, 개별 서비스에 로그인 자격에 대한 증명을 공유할 필요없이 타사 인증시스템을 이용하여 사용자 데이터에 액세스 할 수 있도록 하는 프레임워크를 말한다. 자격에 대한 증명을 공유한다는 말이 좀 어려운데 회원가입을 하여 개인정보를 등록하고 이런 일련의 절차를 서비스마다 하지 않고 이미 개인정보를 보유하고 있는 다른 서비스에 로그인 자격의 검증을 위탁하는 것을 말한다.
(2) OAuth의 작동원리
밑에 실습부분에서도 작동원리에 따라 작성되어있는 코드가 어느 단계에 해당하는지 파악하는데부터 시작했고 시간을 많이 쏟았다. 얼핏보면 단계도 많고 복잡해 보이지만 토큰을 활용한 인증방식인데 외부 서버가 두 개 더 끼어있어서 그렇지 잘 살펴보면 그렇게 복잡하지는 않다.
이하의 설명은 OAuth 2.0 기준의 설명이며, IBM Documentation을 굉장히 많이 참고하였다.
Authorization code flow와 Authorization code flow with refresh token 부분을 중점적으로 살펴보자.
오늘 배운 것과 그림이 조금 달라서 문서를 읽다가 약간 헷갈리긴 했는데 순서대로 파악해보면 이렇다.
1. Client에서 (인증의 엔드포인트까지 과정의) 모든 것이 시작된다. Client identifier와 어디로 redirect 되어야하는지 해당 URI와 인증 요청 범위를 포함한 요청을 User agent를 거쳐 Authorization sever에 전달한다. 전달받은 Authorization sever는 액세스 허용 여부에 따라 User agent를 리디렉션 URI로 보낸다.
2. Authorization sever는 유저가 인증하는 내용에 따라 권한을 부여하거나 거부한다. // 리디렉션 URI로 보내졌을 때 아마 실습에서 나올 Github로 인증하는 화면에서 사용자가 제대로 로그인해서 인증이 성공하면 권한이 부여될 것이고 로그인에 실패한다면 거절될 것이다.
3. 권한이 부여됨에 따라 User agent를 거쳐 Client에게 Authorization code를 건네준다.
4. Authorization code를 포함하여 Client credentials와 함께 access token을 요청하고 redirect URI도 함께 포함되어있다.(설명이 불충분하여 수정 예정)
5. Authorization code를 확인하여 Access token을 발급해주고 경우에 따라 refresh token도 같이 발급해준다.
오늘 배운 그림과 유사한 이 그림에서는 조금 다르게 인증과정이 이루어지는데, 다음과 같다.
사진에 나와있지만 실선은 브라우저를 거쳐서 커뮤니케이션 하는 것이고, 점선은 서버끼리 커뮤니 케이션 하는 것이다. 클라이언트 어플리케이션에도 서버가 있어서 클라이언트 서버와 OAuth 서비스 API 서버 사이의 커뮤니케이션이 서버끼리의 커뮤니케이션이다.
따라서 초반에 사용자가 어플리케이션을 통해 OAuth service API로 인증을 요청하여 Authorization code를 받을 때까지의 과정은 브라우저를 거쳐서 이루어지고
Authorization code로 /token 경로의 토큰을 관리하는 서버에 access token을 요청하고 받는 커뮤니케이션 과정이 있고,
그렇게 받은 access token을 /userinfo 경로의 userinfo를 관리하는 서버에 넘겨주고 user data를 받아와서 최종적으로 user data를 my page같은 페이지에 띄워주면 성공이다.
그런데 매번 로그인할 때마다 소셜로그인을 클릭 정도로 하는 것은 괜찮은데, 아이디와 비밀번호를 매번 다시 입력하라고한다면 사실상 기존의 로그인 방식과 큰 차이가 없다고 생각할 것이고 매우 번거로울 것이다. 그래서 리프레시 토큰 그랜트 타입을 사용해서 로그인한다.
Refresh Token Grant Type의 흐름은 다음과 같으며 쉽게 요약하면 위 그림의 실선부분을 생략하고 refresh token이 있는데 access token은 만료된 경우(어제 포스팅에도 설명되어 있다) 점선부분의 서버 간 통신만 다시해서 유저 데이터를 가져오는 방식으로 브라우저 쪽의 커뮤니케이션은 생략되었기 때문에 사용자의 번거로움을 줄일 수 있다.
그 외에도 인증단계가 한 단계 낮은 Implicit grant type도 있지만 지금 거의 사용되지 않으므로 생략하였다.
#OAuth 인증방법 실습
오늘의 실습은 Github의 OAuth 인증서비스를 이용하여 어플리케이션에 OAuth 인증을 추가하는 기능을 구현하는 것을 해보았다. Refresh Token Grant Type은 지원되지 않아서 이번에 한 것은 Authorization code grant type에 한정된다.
오늘은 과제는 다행히도,,, 서버쪽은 구현이 이미 되어있어서 어떻게 동작하는지 해석만 하면 되었고, 클라이언트 쪽 코드를 구현해야했다.
과제의 순서에 따라가면서 그림의 1번부터 최종적으로 13번까지 어떻게 구현할 수 있는지 살펴보자.
(1) 사용자가 사이트에 접속한다. 랜딩페이지는 <Login /> 컴포넌트로 pages/login 파일이다.
(2) 해당 페이지에서 Github로 로그인을 누르게되면 다음과 같은 일이 벌어진다.
그런데 일단, 로그인을 눌러서 OAuth 인증을 이용하려면 application을 OAuth application을 등록해주어야 한다.
https://www.oauth.com/oauth2-servers/accessing-data/create-an-application/
Create an Application - OAuth 2.0 Simplified
Before we can begin, we'll need to create an application on GitHub in order to get a client ID and client secret. On GitHub.com, from the "Settings" page,
www.oauth.com
위 사이트에서 등록하는데, 현재는 배포용이 아니라 url을 로컬 3000번 등 내가 사용하는 어플리케이션 주소로 등록하면 된다. 그 후에 CLIENT_ID와 CLIENT_SECRET을 발급받아서 필요한 파일에 채워주면 된다.(이 부분은 env 형식 파일로 구현되어있는데 아직 스스로 할 줄은 모르므로 백엔드에 관심있거나 하실 줄 아시는 분들은 그 부분은 직접구현해서 또는 쉽게 구현하는 방법을 안다면 구현해서 해보면 되겠다)
export default function Login() {
const CLIENT_ID = '2136100774f1b8ccc0ec';
const loginRequestHandler = () => {
return window.location.assign(
`https://github.com/login/oauth/authorize?client_id=${CLIENT_ID}`
);
};
...
}
이런식으로 깃허브 쪽에 로그인 요청을 한다.
이 화면에서 다음 행위를 하면
(3) 권한을 허락해준다.
(4) redirect를 하면서 Authorization code를 client에 부여한다.
로딩중 화면이 나오고있는 상태에서
(5) client는 client 쪽 sever로 post 요청을 보내는데, Authorization code를 주면서 sever끼리 코드와 토큰을 주고받으라고 권한을 넘긴다.
(6) 서버에서는 Github Auth 서버에 인증코드를 주고 access token을 요청한다.
(7) Auth 서버는 인증코드가 일치하는지 확인하고 access token을 준다.
(8) access token을 성공적으로 받게되면 로그인이 성공해서 Mypage 로 이동하는데 여전히 로딩중이 뜰 것이다. 아직 마이페이지에 로딩할 정보가 도착하지 않았기 때문이다.
(9) 대신 로그인 되었다는 상태변경이 있고 (10) access token과 함께 userinfo를 달라고 userinfo쪽 서버로 요청을 보낸다.
(11) Github Resource sever가 별도로 있어서 access token을 해당 서버에 주고 user data를 받아온다.
(12) user data를 넘겨줄 것이고
(13) 드디어 mypage에 표시할 수 있는 data를 받았으므로 로딩이끝나서 표시할 수 있게된다.
다음과 같은 화면이 나오면 외부인증서비스를 이용해 인증하는 것을 구현하는 것에 성공했다. 여기서 추가로 로그아웃까지 구현했는데 해당 구현내용은 delete 요청을 보내서 서버에서 해당 권한 부여를 취소하는 것으로 구현하였다.
이번에는 코드 공유보다는 흐름이 어떻게 되는지 위주로 정리해보았다. 나중에 이해도가 더 높아지면 코드까지 정리해 볼 수도 있겠으나 내 생각에는 AWS를 이용해서 어떻게 서버에서 처리하는지도 기억에서 희미해질 것 같긴하지만,,,ㅋㅋㅋㅋ 그럴 때마다 대략적인 복습이라도 이 포스팅을 통해서 해보도록 해야겠다.