OAuth 2.0은 인증을 위한 표준 프로토콜의 한 종류로, 보안된 리소스에 액세스하기 위해 클라이언트에게 권한을 제공(Authorization)하는 프로세스를 단순화하는 프로토콜 중 한 방법이다.
즉, 한 인터넷 서비스의 기능을 다른 서비스에서도 사용하도록 하는 것이다. (예: google, github, facebook 등 소셜 로그인)
OAuth의 플로우를 간단히 나타내면 아래와 같다.
Resource Owner
액세스 중인 리소스의 유저 (사용자)
Client
Resource owner를 대신하여 보호된 리소스에 액세스하는 응용프로그램 (우리가 만들 서비스). 클라이언트는 서버, 데스크탑, 모바일 또는 기타 장치에서 호스팅할 수 있다.
Resource server
client의 요청을 수락하고 응답할 수 있는 서버 (google, github, facebook 등)
Authorization server
Resource server가 액세스 토큰을 발급받는 서버.
즉, Client 및 Resource Owner 를 성공적으로 인증한 후 액세스 토큰을 발급하는 서버
Authorization grant
클라이언트가 액세스 토큰을 얻을 때 사용하는 자격 증명의 유형
Grant type이란?
클라이언트가 액세스 토큰을 얻는 방법. 대표적으로 Authorization Code Grant type, Refresh Token Grant type이 있다.
Authorization Code Grant type
액세스 토큰을 받아오기 위해서 먼저 Authorization Code를 받아 액세스 토큰과 교환하는 방법.
이렇게 하는 이유는 보안을 강화하기 위해서이다. Client에서 Client-secret을 공유해 액세스 토큰을 가지고 오는 것은 탈취 위험이 있기 때문에 ( Client 단에 있으므로) Client에서는 Authorization Code만 받아오고 Server에서 Access token 요청을 진행한다.
Refresh Token Grant type
일정 기간 유효 시간이 지나서 만료된 액세스 토큰을 편리하게 다시 받아오기 위해 사용하는 방법.
Access token보다 Refresh token의 유효 시간이 대체로 조금 더 길게 설정하기 때문에 가능한 방법이다. 서버마다 refresh token에 대한 정책이 다 다르기 때문에 Refresh token을 사용하기 위해서는 사용하고자 하는 서버의 정책을 살펴볼 필요가 있다.
Authorization code
access token을 발급받기 위해 필요한 임시 비밀번호(client id와 client secret이 포함되어 있음). client ID로 이 code를 받아온 후, client secret과 code를 이용해 Access token 을 받아온다.
Access token
Authorization code와 client secret을 이용해 받아온 이 Access token으로 이제 resource server의 보호된 리소스에 접근할 수 있다.
Scope
scope는 토큰의 권한을 정의한다. 주어진 액세스 토큰을 사용하여 액세스할 수 있는 리소스의 범위이다. (리소스 서버에서 우리가 사용하고 싶은 기능)
client가 resource server(여기서는 깃헙)을 이용하기 위해 사전에 승인을 받는 과정이다.
Github 에서 Setting - Developer settings - OAuth Apps - New OAuth App 에서 내 앱을 등록할 수 있다.
resource server마다 다르지만 공통적으로 Client ID, Client Secret, Authorized redirect URIs (여기서는 Authorization callback URL - 발급받은 authorization code를 전달해줄 주소) 를 제공한다.
Client Secret이 절대 외부에 노출되지 않도록 주의하자.
Github 에서 발급받은 Client ID, Client Secret을 .env 파일에 넣어주었다.
GITHUB_CLIENT_ID=64dd459a4180d0d19c7a
GITHUB_CLIENT_SECRET=ce2d3201131098d043d1680810c0a1d99bb78464
Github로 로그인 버튼을 누르면 Authorization Code와 함께 리다이렉트 해주어야 한다. 깃헙에 Authorization Code를 요청하는 과정이다.
버튼을 누르면 아래와 같은 주소로 가게 한다.
GET https://github.com/login/oauth/authorize
뒤에 추가적인 파라미터들을 붙여줄 수 있다. (공식문서 참고)
https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps
(Client/App.js)
Authorization code를 받아온 후 리다이렉트 된 브라우저가 렌더될 때, authorization code를 서버에 보내주는 함수가 실행된다.
(Server/controller/callback.js)
서버에 Authorization code를 보내주면, 서버는 이를 다시 깃헙 서버로 보내 Access token을 요청을 보낸다.
POST https://github.com/login/oauth/access_token
axios.post 요청을 보낼 때
headers: { Accept: "application/json" }
를 넣지 않으면 access token의 정보는 문자열로 온다(default value). 이걸 넣어줌으로써 객체 형태로 받아올 수 있다. axios.post( "https://github.com/login/oauth/access_token",{
client_id: clientID,
client_secret: clientSecret,
code: authorizationCode,
},
{
headers: { Accept: "application/json" },
}
)
post 요청의 결과로 깃헙 서버는 우리의 서버에 Access token을 보내준다.
그럼이제 (Client/App.js) 에서
받아온 Access Token을 가지고 login 상태와 accessToken의 상태를 바꿔준다.
{
isLogin: true,
accessToken: res.data.accessToken,
}
그럼 이제 login이 되었으므로 mypage 컴포넌트가 렌더될 것이다.
Github API를 통해 사용자 정보를 받아와야 한다.
props로 전달받은 Access Token으로 리소스에 대한 API 요청을 보낸다. get 요청을 보낼 때 headers에 Bearer Token을 담아줌으로써 Access Token을 전달할 수 있다.
https://docs.github.com/en/rest/reference/users#get-the-authenticated-user
인증된 사용자가 기본 인증 또는 user
scope가 있는 OAuth를 통해 인증되면, 응답에 public 및 private 프로필 정보가 나열된다.
인증된 사용자가 user
scope가 없는 OAuth를 통해 인증된 경우 응답에는 public 프로필 정보만 나열된다.
axios.get("https://api.github.com/user", {
headers: {
authorization: `token ${accessToken}`,
},
});
전체적인 로직 플로우는 아래와 같다.