들어가기 전에
며칠 전 UMC x CMC의 5번째 Ne(o)rdinary Hackathon에 참여했었다.
이때 OAuth 로그인을 담당하신 분이 계셔서 OAuth를 사용은 했지만 내가 직접 구현하지는 않았다.
예전 TravelPlanner 프로젝트를 진행할 때도 다른 팀원분이 Security 설정과 interface를 완벽히 만들어져 있는 상황에서 내 코드를 구현한 것이라 완벽한 이해가 되지 않았다.
그 후, TAVE 12기 백발백준 프로젝트를 진행하며 Github OAuth 로그인과 전반적인 Security를 혼자 담당하게 되었는데, 1주일 동안 고생하며 구현했었다. 아래는 그것을 구현한 이슈이다.
https://github.com/Tave100Shot/Server/issues/7
feat: Security Github OAuth2.0 · Issue #7 · Tave100Shot/Server
GitHub OAuth2 연결 Resources Owner가 깃허브에 로그인 후 Access Token return TODO CustomOAuth2User OAuth2User 구현 Member와 GithubUserInfo 로 구성 CustomOAuth2UserService DefaultOAuth2UserService 구현 로그인한 사람의 정보를 가
github.com
힘들게 OAuth2.0을 구현했는데 마침 회사에서 OAuth 2.0을 발표해야할 일이 생겼다.
이번 기회에 이론에 대해 좀 더 자세히 학습한 내용들을 정리해보았다.
OAuth 2.0 이론
OAuth 등장인물
OAuth 에는 3명이 등장한다.
1. 나의 서비스
2. 우리 서비스를 사용하는 사용자
3. 나의 서비스가 연동하려는 그들의 서비스 (Google, Naver, Kakao,..)
가장 간단한 방법
1. 우리 서비스를 사용하려는 사람들에게 '우리가' Id, PassWord를 받는다.
2. 우리가 그걸로 로그인한다.
하지만 이렇게 진행할 수 없는 이유
1. 사용자 입장에선 불쾌하다.
사용자 입장에선 Google, Naver와 같은 아이디를 처음 보는 '우리의 서비스'에게 맡겨야 한다.
처음 보는 사람들은 우리를 믿을 수 있을까?
나 같으면 안 믿고 우리 서비스를 시작조차 안 할 것이다.
2. 다 같은 그룹의 회사인데 서비스가 나누어져 있을 때
같은 그룹 회사이므로 고유의 계정이면 좋은데, 서비스가 다르다고 아이디와 비밀번호를 매번 로그인해야 하는 경우가 발생
OAuth를 사용하면 변하는 것들
1. 사용자가 그들의 서비스 (Google, Naver, Kakao,..)에 로그인한다.
2. 그들의 서비스는 우리한테 accessToken이라고 하는 일종의 비밀번호를 발급한다.
여기서 accessToken를 발급하면 좋은 장점
1. 이것은 비밀번호가 아니다.
2. 그들의 서비스의 모든 기능이 아닌, 우리 서비스에 필요한 일부의 기능만 사용한다.
역할별 이름 정의
1. Resource Server - 그들의 서비스 (Google, Naver, Kakao, ..)
2. Resource Owner - User, 로그인하려는 사용자
3. Client - 우리의 서비스
등록 과정
Client가 Resource Server에 로그인하려고 하면, 사전에 등록해야 할 정보가 있다.
사전에 등록해야할 정보에는 아래와 같다.
Client Id
Client Secret
Authorized redirect URLs
Resource Owner가 Resource Server에 로그인에 성공했을 때 accessToken을 바로 주는 것이 아닌, Authorized Code를 부여하는데, 그것을 부여할 URL이다. Http 통신은 statless 이기 때문에, redirect 하여 정보를 전달한다.
인증 과정
Resource Owner의 승인
등록 과정을 거치면, Client와 Resources는 위 3가지 정보를 서로 알고 있게 된다.
그 과정에서 A, B, C, D... 여러 기능 중 B, C 기능만 사용한다고 등록해놓는다.
Resource Owner가 우리 서비스에서 Resource Server 정보를 사용해야 하는 상황이 생기게 되면 우리는 Resource Server에 로그인하라는 화면을 보여주게 된다.
구글 혹은 네이버 등으로 로그인하는 화면에서, 우리는 https:// ~~~ /?client_id=1&scope=B,C&redirect_uri=https://client/callback 이렇게 생긴 주소를 링크로 제공하면 된다.
그 후, 로그인을 성공하게 되면 Resource Server는 Client가 제공한 client_id와 redirect_uri가 같은지 비교하고 맞다면, Resource Owner에게 B, C에 대한 기능을 Client에게 제공할지를 묻는다.
Resource Owner 가 허용한다면 허용했다는 정보가 Resource Server로 전송이 되고, Resource Server는 Resource Owner가 B, C에 대한 기능을 허용했다는 정보를 저장한다.
Resource Server의 승인
Resource Server가 바로 Access code를 제공하지 않는다.
그때 사용하는 임시 비밀번호가 Authorized Code이다.
Resource Server는 Resource Owner에게 https://client/callback?code=3 이라는 주소를 헤더 Location 값에다가 담아서 전송한다.
응답할 때 헤더에 Location이라는 값에다가 값을 넣으면 이를 redirection이라고 하는데, Resource Server가 Resource Owner에게 저 주소로 이동하라고 명령한 것이다.
저 주소는 우리의 주소 https://client/callback?code=3 이렇게 데이터를 받을 수 있게 된다.
그럼 우리는 authorization code는 3이라는 값을 받게 된다.
그렇다면 우린 Resource Server에 직접 접속하게 되는데,
Resource Server는 Client id, Client Secret, authorization code, redirect_url 모든 정보들이 올바른지 확인하는 작업이다.
여기서 모두 일치하다면 Resource Server는 우리에게 accessToken을 발급한다.
accessToken 발급
Resource Server는 우리에게 AccessToken=4 라는 값을 보내준다.
우리가 accesToken을 DB나 다른 곳에 저장을 하고, 우리가 다시 요청을 하면, resourceServer는 accessToken을 보고 Resource Owner 사용자의 B, C에 대한 기능을 허용하겠다는 것을 확인하고, 우리에게 정보를 제공한다.
API 호출
우리가 Resource Server의 기능을 사용하기 위해 accessToken을 포함해서 요청해야 한다.
각 서비스에 맞게 요청하면 되는데, 요청할 때 accessToken을 보내는 방법은 2가지가 있다.
1. 헤더에 Authorization에 Bearer <access_token>와 같이 보낸다.
2. query parameter로 보낸다.
refreshToken 발급
보통 oauth 서비스들의 accessToken은 보통 수명이 있다.
수명이 끝나면 우리가 API에 접속했을 때 data를 주지 않으므로 다시 발급을 해야 한다.
하지만 매번 이렇게 발급하는 것이 쉬운 일이 아니므로 refresh Token을 발급한다.
여기서 한 가지 개념이 더 나오는데, 사실 우리가 지금까지 봤던 Resources Server는 Resources Server만이 아닌, Authorization Server와 Resources Server로 나뉜다. 우리가 인증받는 모든 과정들이 Authorization Server 여기에 있다. 그리고 진짜 Resources Server는 access token이 맞는지만 확인하는 역할을 한다.
그렇다면 다시 정리하자면 우리가 로그인하는 지난 모든 과정을 통해 Authorization Server로부터 access token과 refresh token을 함께 발급받는다. 그리고 resources에다가 accesstoken으로 API에게 호출하다가 accessToken의 유효기간이 만료되면 Authorization Server에게 refreshToken을 전송하여 accessToken을 발급받는다. 제공하는 회사에 따라 refresh Token을 함께 재발급하는 곳이 있기도 하고, 없기도 하다.