티스토리 뷰
1. OAuth는 무엇인가요?
OAuth가 사용되기 전에는 각 사의 개발방식에 따라 인증방식을 통해 인증하고 권한을 부여하는 API서비스를 제공하고 있었습니다. OAuth는 이렇게 제각각인 인증방식을 표준화한 인증방식입니다. OAuth를 이용하면 이 인증을 공유하는 애플리케이션끼리는 별도의 인증이 필요없습니다. 따라서 여러 애플리케이션을 통합하여 사용하는 것이 가능하게 됩니다.
아래의 예제를 통해 살펴보겠습니다.
인프런의 회원가입 화면입니다. '구글, 페이스북, 깃허브 가입' 방식으로 회원가입하는 서비스를 OAuth라 할 수 있습니다. 별도의 아이디나 비밀번호 입력없이 구글, 페이스북 등이 구현한 OAuth를 이용하여 인증 후 회원가입이 완료 될 수 있습니다.
위의 OAuth 회원가입 Flow를 나열하면,
1. K군이 Github회원가입을 클릭합니다.
2. Github 로그인 화면이 나오면 로그인을 진행합니다.
3. Github 페이지 내에서 인프런 어플리케이션이 Github 계정에 접근해도 괜찮은지 승인여부를 보여줍니다.
4. 승인버튼을 누릅니다.
5. 회원가입이 완료됩니다.
위의 흐름도를 살펴보면 Github의 OAuth의 역할이 인증(Authentication)이 아닌 인가(Authorization)를 관리하는 프레임워크란걸 짐작 할 수 있습니다.
일반 유저는 제 3의 어플리케이션에 인증(Authentication)을 하기 위한 목적으로 Client가 OAuth에게 인가를 받은 것이기 때문에 OAuth는 인가(Authorization)프로토콜입니다.
2. OAuth2.0의 구성
2.1 OAuth2.0의 객체
① resource owner : 일반 User(=K군)
② resource server : 정보자원을 호스팅하는 서버, access tokens을 사용하여 보호된 자원을 승인하고 응답(=구글, 페이스북, 깃허브)
③ client : 제 3의 Application(=인프런)
④ authorization server : 권한을 부여하는 서버(=구글, 페이스북, 깃허브)
2.2 토큰 용어
① Refresh Token
Refresh Token은 Access Token을 얻기 위해 사용되는 토큰입니다. Access Token이 유효하지 않거나 혹은 기간이 만료되었을 때 새
로운 Access Token을 얻기 위해 사용되는 토큰이라고 생각하시면 됩니다.
② Access Token
액세스 토큰은 보호된 데이터에 접근하는데 사용되는 인증서입니다. 클라이언트에 발급 된 권한 부여를 나타내는 문자열이며, 문자열
은 대개 클라이언트에게 이해하기 어려운 문자열로 되어 있습니다. 엑세스 토큰은 일반 User에게 부여한 범위와 지속 기간을 나타내
며 resource server와 authorization server에 의해 시행됩니다.
A - Client(=인프런)이 인증을 인가 해주는 엑세스 토큰 발급을 요청
B - authorization serve는 클라이언트를 인증하고 권한 부여를 검증하며, 유효할 경우 Aceess Token과 Refresh Token을 발급
C - Client(제 3 Application)은 엑세스 토큰을 제시하여 Resource Server의 보호된 데이터를 요청
D - Resource Server는 엑세스 토큰이 유효 할 경우, 보호된 데이터를 Response 합니다.
E - 액세스 토큰이 만료 될 때까지 단계 C 및 D가 반복됩니다. 액세스 토큰이 만료되었다는 것을 클라이언트가 알고 있으면 단계 G로 건너
뜁니다.
F - 엑세스 토큰이 유효하지 않으면, Reosource Server는 에러를 송신합니다.
위의 Flow를 살펴보면, 유저가 깃허브, 페이스북, 구글 로그인을 할 때 Resource Server/ Authorization Sercer에게 발급 받은 Access,
Refresh Token을 Client(제 3의 어플리케이션)이 받아서 로그인을 할 수 있도록 도와주는 형태를 지니고 있습니다.
2.3 권한 인증방식
2.3.1 권한 인증방식 TYPE
OAuth2.0에서 권한 인증방식은 크게 4가지로 구성되어있습니다.
① Client Credentials Grant
- 클라이언트가 자원 소유자인 경우에 사용됩니다.Machine to Machine 간의 인증이 필요할 때 사용하거나 사용자 권한을 구체적으로
요구하지 않았을 때 사용합니다. Client Credentials는 username + password 또는 소셜 로그인과 같은 일반적인 인증 방식이 적합하지
않습니다.
클라이언트는 자기를 인증할 수 있는 정보를 Authorization Server(권한 서버)에 보내면서 access token을 요청하게 됩니다.
Step A - 인증요청
Step B - 인증에 대한 응답
Step C - 데이터 요청
② Authorizatio Code Grant(Applicaiton이 Native app/ Server에서 실행 중인 Application )
Step A - 인증요청
클라이언트 애플리케이션은 응답 유형, 클라이언트 ID 혹은 클라이언트 secret 및 리디렉션 URL을 지정하여 사용자를 인증 서버로 리디렉션하여 권한 부여 요청을 합니다.
Step B - 사용자 인증
Authorization Server(=깃허브, 구글 등)에서 로그인하라는 메시지가 표시됩니다.
Step C - 권한 응답
인증이 성공하면, Authorization Server(=깃허브, 구글 등)에서 HTTP 헤더에 Query String으로 권한코드(=Authorization Code)가 제공된 Client(=인프런)에게 다시 돌려보냅니다.
Step D - Access Token 요청
Client Application(=인프런)은 주어진 Authorization Code(권한 코드)를 사용하여 Access Token을 얻기 위해 Authorization Server(=구글, 깃허브 등)에 다시 요청합니다. 이 요청에는 HTTP 헤더에 Authorization이 포함되어야 하며, Grant Type(권한 유형), 승인 코드, 리디렉션 URL은 메시지 본문에 전송되어야 합니다.
Step E - Access Token 응답
요청이 유효하다면, Authorization Server는 Access Token, 만기 기간, Refresh Token, 그리고 Application의 특정한 매개 변수들을 보내줍니다. 여기서 Access Token, 만기기간, Refresh Token은 OAuth를 구현한 각 사들의 공통적인 부분에 해당하고, Application의 특정한 매개 변수들은 각 사들이 응답할 떄 추가적으로 필요한 정보에 해당합니다.
Step F - 자원요청
Client는 엑세스 토큰을 사용 하여 Resource Server(=깃허브, 구글) 에게 자원을 요청합니다.
② Implicit Grant(Single Page Application) - https://jsonobject.tistory.com/369
- 웹 서버가 아닌 모바일 네이티브 앱 및 브라우저 기반의 JS 애플리케이션(SPA)에 가장 적합하도록 설계된 grant_type타입입다.
- Authorization code와의 차이점이라면 response_type으로 code가 아닌 token을 요청하고 반환합니다. 사용자가 로그인 및 권한 위임에
동의하면 redirect_uri에 token 파라메터를 통해 access_token을 바로 내려줍니다.
- 이 방식은 Access Token이 그대로 사용자(또는 외부)에게 노출됨으 유효한 클라이언트인지 확인할 방법은 redirect_uri 뿐입니다 (절대
사용자(외부)에 노출되지 않아야 할 client_secret은 전혀 사용되지 않습니다.)
- refresh_token 또한 노출되지 않아야 하기 때문에 발급되지 않습니다. 따라서 Access Token이 만료되면 같은 인증 과정을 반복해야 합
니다.
Step A - 인증요청
먼저 클라이언트 애플리케이션은 응답 유형, 클라이언트 ID, 상태(사이트 간 요청 위조(CSRF) 공격을 방지하기 위해 애플리케이션에서 생성한 상태 토큰값으로 URL 인코딩을 적용한 값) 및 리디렉션 URL을 지정하여 Authorization Server에 권한 부여 요청을 합니다.
Step B - 사용자 인증
기존에 등록된 client id의 redirect_uri가 일치하는지 확인 후 사용자 인증을 합니다.
Step C - Access Token 응답
인증에 성공하면 Authorization Server는 액세스 토큰, 상태, 토큰 유형 및 토큰 만기 시간으로 응답합니다.
Step D - 자원요청
Client는 엑세스 토큰을 사용 하여 Resource Server(=깃허브, 구글) 에게 자원을 요청합니다.
③ Resource Owner Password Credentials Grant ( Application에서 완전하게 사용자 증명을 신뢰 할 경우)
- 자원 소유자의 계정 아이디와 비밀번호 같은 계정 인증 정보가 access token을 얻기 위한 Authorization Grant(권한 증서)로 사용됩니다.
- 사용자의 인증 정보를 클라이언트가 알고 있을 경우 사용 할 수 있는 타입입니다.
- 계정이 도용되지 않도록 API 서버가 통제 가능한 앱에만 적용 할 수 있습니다.
- Access Token을 취득 후에는 ID와 Password를 보관할 필요가 없습니다.
즉, 자사앱을 사용할 경우에 적합하다고 생각합니다. 예를 들어 IOS의 아이튠즈 등...
Step A - 인증요청
클라이언트는 Authorization 헤더에 Client 자격증명을 넣어야 하고, Body에는 grant type과 사용자 증명서를 보내어 요청해야합니다.
Step B - Access Token 응답
인증에 성공하면 Authorization Server는 액세스 토큰, 상태, 토큰 유형 및 토큰 만기 시간으로 응답합니다.
Step C - 자원요청
Client는 엑세스 토큰을 사용 하여 Resource Server(=깃허브, 구글) 에게 자원을 요청합니다.
[Reference]
http://blog.weirdx.io/post/39955
https://cheese10yun.github.io/oauth2/
https://auth0.com/docs/api-auth/grant/password
https://d2.naver.com/helloworld/24942
https://tools.ietf.org/html/rfc6749#section-1.1
https://meetup.toast.com/posts/105
http://blog.weirdx.io/post/39955