OAuth란?
Open Authorization 위임 권한부여를 위한 표준 프로토콜이다. 인증과 권한부여를 동시에 제공한다. OAuth는 어플리케이션이 사용자의 패스워드 없이 사용자의 데이터에 접근 가능하도록 허가해준다.
구글, 페이스북, 트위터와 같은 다양한 플랫폼의 특정한 사용자 데이터에 접근하기 위해 제 3자 클라이언트가 사용자 인증을 통해 사용자의 접근 권한을 위임 받을 수 있는 방식을 제공한다.
- 단순히 OAuth 1.0a의 차기버전이 아닌, 상황에 따른 다양한 인증 방식을 시나리오별로 제시한다.
- HTTPS(HTTP+SSL)을 필수로 강제하고, 토큰을 HTTP Header에 숨기는 방식을 사용한다.
OAuth2.0 장점
- 대형 서비스로의 확장성을 지원한다. 자원 서버와 인증 서버를 분리하여 각각의 역할을 명확히 구분한다.
- 사용자의 구글, 페이스북, 네이버 등의 아이디와 패스워드를 직접 제공받아 우리의 서비스에 저장하고 활용할 수 있는 방법이므로, 기존에 잘 구현해놓은 대기업의 서비스 + 데이터를 가져다 사용하면 된다. 이렇게 하면 우리는 우리의 비즈니스에만 집중 할 수 있다
- HTTPS를 사용하기 때문에 상대적으로 개발하기 쉽다.
- 다양한 시나리오에 맞는 인증방식이 있다. 다양한 Token과 Grant Type을 지원한다.
- Token: Bearer Token(표준), MAC Token, JSON Web-Token(JWT), SAML2
- 인증방식: Authorization Code, Implicit, Resource Owner Credential, Client Credentials
OAuth2.0 용어 정리
Resource Owner | 클라이언트 어플리케이션이 접근하길 원하는 데이터를 가지고 있는 사용자 (나, 고객) |
Client | 사용자의 데이터에 접근하고 싶어하는 어플리케이션 (우리가 사용하는 앱이나 웹 서비스) |
Resource Server | API서버로 실제 서비스를 제공하는 서비스 공급자 클라이언트가 접근하길 원하는 데이터를 갖고 있는 시스템 때때로 권한 부여 서버와 리소스 서버가 같은 경우도 있다.(개발자가 어떻게 구현하냐에 따라 다름) |
Authorization Server | OAuth 인증을 처리하는 서비스 공급자의 서버 사용자로부터 권한을 부여받음으로써 클라이언트가 사용자의 데이터에 접근할 권한을 부여해주는 서버 |
Access Token | 리소스 서버에서 사용자에 의해 부여된 데이터에 접근하기 위해서 클라이언트가 사용할 수 있는 유일한 키 (실제적인 사용자의 id, pw를 쓰는게 아니고 access token 을 이용해서 데이터에 접근함) |
Client 분류
Client 인증서를 안전하게 보관 가능한지 여부레 따라 분류한다.
Public Client | Confidential Client |
Client 인증서 없음 redirect_uri을 통해 client 인증을 처리한다. Resource Owner가 소유한 기기(브라우저, 스마트폰 등) |
Client 인증서 보관 안전하게 인증서 보관 가능한 기기에 해당(웹 서버) |
인증 방식
OAuth2 프로토콜은 권한 부여 방식에 따른 프로토콜을 4가지 종류로 구분하고 있다.
구분 | 3-legged | 2-legged |
Public Client | Implicit Grant | Resource Owner Password Credential Grant |
Confidential Client | Authorization Code Grant | Client Credentials Grant |
3-legged Grant Type
- Implicit Grant Type
- Public Client인 브라우저 기반의 어플리케이션(순수한 자바스크립트 Single Page Application)이나 모바일 어플리케이션에서 사용한다.
- 자격증명을 안전하게 저장하기 힘든 클라이언트에 최적화된 방식이다.
- Client 증명서를 사용할 필요가 없으며 OAuth2.0에서 가장 많이 사용한다.
- Autorization Code없이 바로 Access Token이 발급된다.
- 로그인시에 response_type=token 파라미터로 호출
- Authorization Code Grant Type
- 가장 많이 쓰이고 기본이 되는 방식으로, 간편 로그인 기능에서 사용되는 방식으로 클라이언트가 사용자를 대신하여 특정 자원에 접근을 요청할 때 사용하는 방식이다.
- 웹 서버에서 API를 호출하는 등의 시나리오에서 Confidential Client가 사용하는 방식이다.
- 서버사이드 코드가 필요한 인증 방식으로, 인증과정에서 client_secret가 필요하다.
- 로그인 시에 페이제 url에 response_type=code 파라미터 호출
2-legged Grant Type (서버-클라이언트 방식과 유사하다)
- Resource Owner Password Credential Grant Type
- username, password로 직접 Access Token을 받는 방식이다.
- 믿을 수 있는 Client에 한해서만 사용이 필요하다.
- 자사 앱에 직접 로그인하는 방식으로 code 발급없이 바로 로그인이 가능하다.
- 로그인시 API에 POST로 grant_type=password 파라미터로 호출
- Client Credential Grant
- 어플리케이션이 Confidential Client일 때 id와 secret을 가지고 인증하는 방식
- 로그인시 API에 POST로 grant_type=client_credentials파라미터로 호출
OAuth2.0 Flow
OAuth2 프로토콜 중, 가장 많이 쓰이고 기본이 되는 Authorization Code Grant 동작 매커니즘은 아래와 같다.
구글 간편로그인을 한다고 생각해고 정리해보자
- 사용자가 "구글로 로그인하기" 버튼을 누른다.
- 사용자가 구글의 아이디와 패스워드를 입력한다.
- 구글이 사용자에게 Autorization Code를 발급해준다.
- Client가 구글에게 ID + Password + Autorization Code를 함께 구글에게 전송하면 Access Token을 발급받는다.
- Client는 Access Token을 DB에 저장하고 구글에게 사용자가 요청한 서비스를 대신해서 요청한다.
OAuth2.0 스코프
OAuth2.0 스코프라는 개념을 통해서 "유저 리소스에 대한 권한을 설정하고 접근 범위"를 제한할 수 있다. 사용자에 의해 특정 스코프로 제한된 권한 인가권을 발행해서 데이터 접근을 제한한다. 즉 Client는 Scope에 해당하는 권한을 제한적으로 획득할 수 있다. (여러개 요청 가능)
Scope 를 별도로 등록하지 않는다. 왜냐하면 기본값이 opendid, profile, email이기 때문이다. openid 라는 scope가 있으면 OpenId Provider로 인식해서, OpenId Provider인 서비스와 그렇지 않은 서비스로 나눠서 각각 OAuth2Service를 만들어야한다.
Refresh Token
클라이언트가 같은 access token을 오래 사용하면 해킹에 노출될 위험이 증가한다. 그래서 access token의 만료기간을 가능한 짧게 하고 만료가 되면 refresh token으로 access token을 갱신한다.
하지만 오히려 이런방식이 개발이 복잡해지기 때문에 access token이 만료되면 다시 access token을 요청해서 로그인하게 하는 방법이 안전하다는 의견도 있기 때문에 정해진 답은 없다.
왜 Authorization Code를 Access Token으로 변경할까?
보안성을 높이기 위해서이다.
Authorization Code는 사용자가 로그인 & 동의를 하게 되면 Redirect URI을 통해 Authorization Code가 전송된다. 이는 곧 브라우저에 노출되는 것이다. 중요한 데이터를 브라우저에 노출시키면 안된다. 그래서 Authorization Code는 프론트엔드에서 받아서 백엔드로 전달 해야한다. 백엔드는 Authorization Code을 가지고 Authorization Server에게 Access Token을 요청해서 "서버"에 발급받는다.
이 과정을 거치면 Access Token 는 내부에서만 이동했기 때문에 공격자가 탈취할 수 없게 된다. Access Token 을 발급받기위해 client_secret 값이 필요하기 때문에 절대로 노출해선 안된다.
Reference
'TIL' 카테고리의 다른 글
OpenID (OIDC) (0) | 2023.09.01 |
---|---|
[TIL-230829]CSRF (0) | 2023.08.29 |
[TIL-230827]Filter Interceptor (0) | 2023.08.28 |
[TIL-230827] 인증과 인가 (0) | 2023.08.27 |
[TIL-230629] 서블릿(Servlet)이란? (0) | 2023.06.29 |