OAuth란 인증의 개방 표준이고 누구나 구현할 수 있습니다.
조금 더 구체적으로는 OAuth는 안전한 위임 엑세스를 가지는 클라이언트 애플리케이션을 제공하기 위한 표준입니다.
OAuth는 버전이 1.0a와 2.0이 있는데 여기서는 OAuth 2.0에 대해서 말하겠습니다.
현재에 와서 많이 사용하는 표준이 OAuth 2.0이기 때문입니다.
OAuth는 아이디와 비밀번호를 통해 인증하는 방식인HTTP Basic Authentication에 대응하여 만들어졌습니다.
HTTP Basic Authentication 방식은 현재에 와서도 API 인증의 주요 방식입니다.
현재에 와서 바뀐 점이 있다면 아이디와 비밀번호를 통해 인증하는 것이 아니라 API키와 ID, 시크릿을 통해 인증을 합니다.
OAuth이전에는 이용하고자 하는 애플리케이션에 제 3사이트에 있는 내 정보를 주기 위해 제 3사이트의 아이디와 비밀번호를 애플리케이션에 전송해줘야 했습니다.
이는 비밀번호의 원래 의도에 반하는 형태였기에 좋지 못했습니다.
OAuth는 위의 문제를 해결해줬습니다.
federated identity를 만들었는데 이 방식은 유저가 identity provider에게 요청을 보내 identity provider가 암호화된 토큰을 만들고 이를 애플리케이션에 제공함으로써 애플리케이션이 유저를 인증하게 만들어 줍니다.
애플리케이션이 identity provider를 신뢰한다면 이러한 방식은 계속 사용될 수 있습니다.
아래는 앞서 설명한 내용을 그림으로 나타낸 것입니다.
현재에 와서는 대부분의 API들이 REST API로 넘어갔고 많은 API들이 만들어졌습니다.
개발자들은 API들을 보호할 필요가 있었는데 과거에 아이디와 비밀번호를 직접 입력하여 사용하는 방식은 문제가 있었습니다. 그렇기 때문에 패스워드를 주지않고 API를 보호하는 방법을 찾아야 했습니다.
아래는 애플리케이션이 권한을 요청하는 것입니다.
이것이 OAuth입니다.
OAuth는 REST/API들을 위한 인증을 위임하는 프레임워크입니다.
이는 애플리케이션이 사용자에 대한 제한된 범위의 접근 권한을 가지게 함으로써 유저의 패스워드없이 사용자에 대한 정보를 얻을 수 있게 됩니다.
OAuth는 인증과 인가를 분리하였고 다른 기기의 기능들을 통해 다양한 사용 사례를 지원했습니다.
OAuth의 작동방식을 간단하게 요약해 보겠습니다.
1. 앱이 유저의 권한을 요청합니다.
2. 유저가 해당 앱에 권한을 허용하고 권한에 대한 코드를 앱에 전달합니다.
3. 앱은 사용자에게 받은 권한에 대한 코드를 서버에 전달함으로써 엑세스 토큰을 얻습니다.
4. 이 엑세스 토큰을 통해 사용자가 허용한 범위내에서 애플리케이션은 사용자의 정보에 접근할 수 있습니다.
OAuth의 핵심 요소에는 Scopes, Actors, Clients, Tokens, Authorization Server, Flows가 있습니다.
Scopes는 인가 화면에서 애플리케이션이 권한 허용 승인을 요청하는 화면에 있는 권한 허용 범위입니다.
해당 권한 허용은 토큰을 요청하기 전에 허가가 필요한 권한에 대해 물어보는 것입니다.
아래가 Scopes의 예시입니다.
Scopes는 인가 정책의 결정과 실제 이 정책이 실행되는 것을 분리하게 해줍니다.
이것이 OAuth의 핵심 측면 중 하나입니다.
OAuth에는 4종류의 Actors가 있습니다.
Resource Owner
리소스 서버의 데이터를 가지는 사람입니다.
사용자라고 보시면 됩니다.
Resource Server
사용자가 사용하고 있는 다른 애플리케이션의 API서버입니다.
리소스 데이터를 저장하는 API서버입니다.
Client
사용자가 사용하고자 앱입니다.
또한 이 앱은 사용자의 데이터에 접근하는 앱입니다.
Authrization Server
OAuth의 주요 엔진입니다.
이 서버를 통해 클라이언트는 사용자의 리소스에 접근 할 수 있는 토큰을 얻습니다.
참고로 아래는 클라이언트의 종류를 나타냅니다.
Confidential의 경우 시크릿을 믿고 맡길 수 있는데 다른 사용자가 이들의 시크릿 키를 알아낼 수 없기 때문입니다.
public의 경우 시크릿키가 다른 사람에게 공개될 수 있습니다.
Access Token
클라이언트가 리소스 서버의 데이터에 접근하기 위해 필요한 토큰입니다.
이 토큰은 짧은 시간 동안만 유효합니다.
Refresh Token
Access Token보다 오랜 시간 유효합니다.
이 토큰은 새로운 Access Token을 얻기 위해 사용됩니다.
Refresh Token을 획득하기 위해서는 주로 인증을 요구합니다.
Refresh Token은 취소될 수 있습니다.
로테이트를 통해 요청마다 새로운 토큰을 주고 이를 서버에 따로 기록함으로써 토큰이 탈취되어 다른 사용자가 이용하고 있는지 확인할 수 있습니다.
로테이트는 시스템에서 따로 만들어줘야 합니다.
유의해야 할 점은 OAuth는 토큰으로 어떤 것을 써야하는지는 정의하지 않았다는 것입니다.
그렇기 때문에 토큰으로 어떤 것이든 쓸 수 있습니다.
주로 JWT가 사용되긴 합니다.
Authorization Server에서 토큰을 발행하는 절차를 알아보겠습니다.
이 방식의 단점은 개발자가 해야 할 일이 증가한다는 것입니다. 클라이언트 개발자는 OAuth를 위해 리프레쉬 토큰을 관리해야 합니다.
리프레쉬 토큰 대신 API key를 사용할 수도 있지만 보안이 취약해집니다.
보안을 증가시키는 방법이지만 개발자들이 해야할 일이 증가하게 되어 매우 귀찮은 일이 되어버립니다. 다행히도 최근에는 프레임워크나 해당 언어의 라이브러리나 패키지를 통해 간편하게 할 수 있는 일이 되었습니다.
앞에서 권한을 허용하고 토큰을 통해 정보를 얻는 과정을 살펴보았습니다. 이 과정은 프론트에서 권한을 허용하는 일과 백에서 토큰을 통해 정보를 얻는 과정으로 분리하여 볼 수 있습니다.
프론트에서 일어나는 일을 보겠습니다.
1. 사용자는 앱에 접속해 권한 위임 과정을 시작합니다.
2. 클라이언트는 사용자의 권한 범위에 해당하는 인가 요청을 보냅니다.
3. Authorization Server는 사용자에게 클라이언트가 해당 권한 범위의 인가를 받는게 맞는지 물어봅니다.
4. 사용자가 인가를 받는게 맞다면 사용자는 권한 허용에 대한 정보를 클라이언트에게 주게 됩니다.
프론트에서 일어나는 일이 끝나면 백에서의 흐름이 시작됩니다.
1. 클라이언트는 엑세스 토큰을 얻기 위해 Authorization Server에 요청을 보냅니다. 이때 요청과 함께보내는 정보에는 client id, client credentials, Code가 있습니다.
여기서 코드는 프론트에서 사용자가 인가를 받는다고 했을때 받는 코드입니다. 이 코드는 사용자가 클라이언트에 보내게됩니다.
2. 엑세스 토큰을 받고 Resource Server에 엑세스 토큰과 함께 요청을 보냄으로써 사용자의 정보에 접근합니다.
Implict Flow
엑세스 토큰을 필요로 하는 백엔드 서버가 없이 통신이 이루어지는 방식입니다.
엑세스 토큰은 바로 사용자에게 갑니다.
대부분 리프레쉬 토큰은 지원하지 않습니다.
사용자와 클라이언트가 같은 기기에 있습니다.
보안에 취약합니다.
Authorization Code Flow
위에서 계속 설명하던 방식입니다.
프론트 단과 백 단이 분리되어 있습니다.
프론트 단은 Authorization Code grant를 얻기 위해 사용되며
백 단은 앞서 만든 Authorization Code를 이용하여 엑세스 토큰은 받기 위해 사용합니다.
사용자와 클라이언트가 서로 다른 기기에 있습니다.
보안에 강한데 이유는 클라이언트가 엑세스 토큰을 가지고 있기 때문입니다.
Client Credential Flow
사용자가 존재하지 않습니다.
사용자 대신 클라이언트 애플리케이션이 인증을 수행합니다.
서버와 서버간 통신에 사용되는 방식입니다.
Authorization Code Flow방식에서 백 단만 있는 것이 이 방식입니다.
Resource Owner Password Flow
사용자의 아이디와 비밀번호로 직접 인증을 받는 방식과 비슷합니다.
권장되지 않는 방식입니다.
구식 클라이언트를 처리해야 하는 경우에 사용됩니다.
Assertion Flow
Client Credential Flow와 유사합니다.
federated 방식을 지원합니다.
federated 방식은 서로 다른 identity 관리 시스템 사이에서 사용자의 identity를 연결하는 방법입니다.
제 3자 identity provider를 통해 엑세스 토큰을 얻는 것입니다.
아래는 federated identity를 통해 인증을 받는 과정입니다.
Device Flow
TV와 같은 컨트롤러만 존재하고 브라우저는 존재하지 않습니다.
브라우저가 사용가능한 장치를 통해 인증을 하고 해당 컨트롤러에 풀링을 통해 해당 컨트롤러가 인증되게 하는 방식입니다.
OAuth는 인가 프레임워크입니다.
프로토콜이 아닙니다.
OAuth는 인증과정에서 사용자 정보를 보여줄 필요가 없습니다.
일부 클라이언트는 인증과 동시에 사용자의 정보를 보여주는데 이는 표준이 아닙니다.