전통적으로 특정 애플리케이션의 서비스를 이용하는 사용자에 대한 인증 처리는 해당 서비스를 직접적으로 제공하는 애플리케이션에서 담당해 왔습니다.
인증 서버를 별도로 분리해서 인증을 처리하든 하나의 서버에서 사용자의 인증도 처리하고 그와 동시에 애플리케이션의 서비스도 함께 제공하든 어쨌든 서비스를 제공하는 애플리케이션에서 해당 서비스를 이용하는 사용자의 크리덴셜(Credential)을 직접적으로 관리하는 것이 일반적입니다.
일정관리를 해주는 위와 같은 애플리케이션이 있다고 가정합니다.
위 애플리케이션에서 사용자에게 캘린더 형태의 서비스를 제공하기 위해서 Google의 Calendar API를 이용하는 기능이 추가되었습니다.
이 경우, 일정 관리 서비스에 대한 회원 가입을 통해 사용자의 크리덴셜을 관리해야 함은 물론이고, Google Calendar API를 이용하기 위해 Google에서 사용하는 사용자의 크리덴셜까지 일정 관리 서비스와 공유해야 합니다.
사용자가 일정 관리 서비스에 대한 회원 가입을 하는 시점 또는 캘린더 서비스를 사용하는 시점에 API를 이용하기 위해 Google에서 사용하는 크리덴셜을 일정 관리 서비스 애플리케이션에 추가적으로 제공해야 합니다. 그리고 제공한 Google에 대한 크리덴션은 일정 관리 서비스 애플리케이션에 저장됩니다.
여기서 문제점
이러한 문제점을 해결하기 위해 OAuth 2 인증 프로토콜을 사용합니다.
특정 애플리케이션(Client)에서 사용자의 인증을 직접 처리하는 것이 아니라 사용자 정보를 보유하고 있는 신뢰할 만한 써드 파티 애플리케이션(Google, Naver, GitHub..)에서 사용자의 인증을 대신 처리해 주고 Resource에 대한 자격 증명용 토큰을 발급한 후, Client가 해당 토큰을 이용해 써드 파티 애플리케이션의 서비스를 사용하게 해주는 방식입니다.
위 애플리케이션에 OAuth 2 프로토콜을 적용시킨 것입니다.
애플리케이션을 사용하는 사용자의 Google 전용 크리덴셜이 애플리케이션에 직접적으로 제공되지 않아도 됩니다.
로그인 자체는 구글 로그인 인증을 이용하고, 구글 로그인에 성공하면 Access Token을 전달받아서 Google Calendar API를 사용하기 위해 Access Token을 이용합니다.
일정 관리 서비스 애플리케이션에 구글의 크리덴셜이 직접적으로 제공되지 않기 때문에 일정 관리 서비스 애플리케이션에서 사용하는 크리덴셜 저장소에 저장될 필요가 없으므로 사용자의 크리덴셜을 이중으로 관리하지 않아도 됩니다.
그만큼 보안성도 향상된다는 의미와 같습니다.
또한 추가적인 인증 서비스 제공 용도로 특정 서비스를 제공하는 애플리케이션에서 사용자의 크리덴셜을 남기고 싶지 않을 경우 OAuth 2 로그인 인증 방법으로 로그인하면 됩니다.
위 사진은 OAuth2를 구성하는 컴포넌트 간의 상호 작용을 통한 인증 처리 흐름입니다.
Resource Owner는 Client 역할을 하는 웹 애플리케이션에게 OAuth2 인증을 요청합니다.
로그인을 위해 Client가 자체적으로 로그인 화면을 제공하는 것이 아닙니다. 로그인은 써드 파티 애플리케이션에 하기 위해, 이 요청을 Client인 웹 애플리케이션에 전송하는 것입니다.
Client는 Resource Owner가 Resource Owner의 계정 정보를 관리하고 있는 써드 파티 애플리케이션에 로그인할 수 있도록 써드 파티 애플리케이션의 로그인 페이지로 리다이렉트합니다.
Resource Owner는 로그인 인증을 진행하고 로그인 인증에 성공하면,
Authorization Server가 Resource Owner의 로그인 인증이 성공적으로 수행되었음을 증명하는 Access Token을 Client에게 전송합니다.
Access Token을 전달받은 Client는 이제 Resource Owner의 대리인 역할을 수행할 수 있게 되었으며, Resource Owner 소유의 Resource를 요청합니다.
Resource Server는 Client가 전송한 Access Token을 검증해서 Client가 Resource Owner의 대리인으로서의 자격이 증명되면 Resource Owner의 Resource를 Client에게 전송합니다.
Authorization Code Grant는 권한 부여 승인을 위해 자체 생성한 Authorization Code를 전달하는 방식으로, 가장 많이 쓰이고 기본이 되는 방식입니다.
Authorization Code Grant 방식에서는 Refresh Token을 사용할 수 있습니다.
권한 부여 승인 요청 시 응답 타입(response_type)을 code로 지정하여 요청합니다.
Resource Owner는 소셜 로그인 버튼을 누르는 등의 서비스 요청을 Client(애플리케이션)에게 전송합니다.
Client는 Authorization Server에 Authorization Code를 요청합니다. 이때 미리 생성한 Client ID, Redirect URI, 응답 타입을 함께 전송합니다.
Resource Owner는 로그인 페이지를 통해 로그인을 진행합니다.
로그인이 확인되면 Authorization Server는 Authorization Code를 Client에게 전달합니다. (이 전에 요청과 함께 전달한 Redirect URI로 Code를 전달합니다.)
Client는 전달받은 Authorization Code를 이용해 Access Token 발급을 요청합니다. AccessToken을 요청할 때 미리 생성한 Client Secret, Redirect URI, 권한 부여 방식, Authorization Code를 함께 전송합니다.
요청 정보를 확인한 후 Redirect URI로 Access Token을 발급합니다.
Client는 발급받은 Access Token을 이용해 Resource Server에 Resource를 요청합니다.
Access Token을 확인한 후 요청받은 Resource를 Client에게 전달합니다.
별도의 Authorization Code 없이 바로 Access Token을 발급하는 방식입니다.
이는 자격증명을 안전하게 저장하기 힘든 Client(자바스크립트 등 스크립트 언어를 사용하는 브라우저)에게 최적화된 방식입니다.
Refresh Token 사용이 불가능하며, 이 방식에서 Authorization Server는 Client Secret을 통해 클라이언트 인증 과정을 생략합니다.
권한 부여 승인 요청 시 응답 타입(response_type)을 token으로 지정하여 요청합니다.
Resource Owner는 소셜 로그인 버튼을 누르는 등의 서비스 요청을 Client(애플리케이션)에게 전송합니다.
Client는 Authorization Server에게 접근 권한 요청을 합니다.
요청과 함께 미리 생성한 Client ID, Redirect URI, 응답 타입을 전송합니다. (⭐ Authorization Code를 획득하기 위한 요청이 아닙니다)
Resource Owner는 로그인 페이지를 통해 로그인을 진행합니다.
로그인이 확인되면 Authorization Server는 Client에게 Access Token을 전달합니다.
Client는 Access Token을 이용해 Resource Server에게 Resource를 요청합니다.
Access Token을 확인한 후 요청받은 Resource를 전달합니다.
간단하게 로그인 시 필요한 정보(username, password)로 Access Token을 발급받는 방식입니다. 자신의 서비스에서 제공하는 애플리케이션의 경우에만 사용되는 인증 방식으로, Refresh Token의 사용도 가능합니다.
예를 들어 네이버 계정으로 네이버 웹툰 애플리케이션에 로그인, 카카오 계정으로 카카오 지도 애플리케이션에 로그인하는 경우가 Resource Owner Password Credential Grant에 해당합니다.
다시 말해 Authorization Server, Resource Server, Client가 모두 같은 시스템에 속해 있을 때만 사용이 가능합니다.
Resource Owner는 로그인 버튼을 누르는 등의 서비스 요청을 Client(애플리케이션)에게 전송합니다.
이때 로그인에 필요한 정보(Username, Password)를 이용해 요청합니다.
Client에서는 Resource Owner에게서 전달받은 로그인 정보를 통해 Authorization Server에 Access Token을 요청합니다. 미리 생성한 Client ID, 권한 부여 방식, 로그인 정보를 함께 전달합니다.
요청과 함께 온 정보들을 확인한 후 Client에게 Access Token을 전달합니다.
Client는 Access Token을 이용하여 Resource Server에게 Resource를 요청합니다.
Access Token을 확인한 후 요청받은 Resource를 전달합니다.