Spring/security

[시큐리티] OAuth 2

라임온조 2023. 3. 30. 12:56

1. 개념

권한 부여 프레임워크. 내가 만든 서비스에서 구글이나 네이버 같은 다른 플랫폼의 사용자 정보에 접근하기 위한 권한을 위임 받을 수 있도록 해주는 것.

 

2. 구성 요소

1) 리소스 서버

내가 만든 서비스에서 다른 플랫폼의 사용자 정보에 접근하려고 할 때, 다른 플랫폼의 사용자 정보를 리소스라고 한다. 그리고 이러한 리소스를 제공해주는 서버가 리소스 서버이다. 즉, 구글이나 네이버 같은 플랫폼의 서버가 리소스 서버라고 할 수 있다.

2) 사용자(리소스 소유자)

내가 만든 서비스를 사용하는 사용자이면서, 구글이나 네이버 같은 다른 플랫폼을 사용하여 그 플랫폼의 리소스를 소유하고 있는 사람

3) 클라이언트

사용자를 대신해 리소스 서버에 접근하는 주체로, 보통 내가 만든 서비스를 의미한다.

4) 권한 부여 서버

클라이언트가 리소스 서버가 가지고 있는 리소스에 접근할 수 있는 권한을 부여해준다. 클라이언트가 권한이 있으면 권한 부여 서버가 토큰을 발급해주고, 클라이언트는 토큰을 이용해서 리소스 서버에 접근해 리소스를 얻을 수 있다. 리소스 서버는 토큰이 올바른 토큰임을 확인한 후 올바른 경우에 클라이언트에게 리소스를 가져가게 해 준다.

 

3. OAuth 2 구현

그랜트(grant)라고 하는 토큰을 이용해 권한 부여를 진행한다. 즉, 클라이언트가 권한 부여 서버에게 토큰을 받으면 리소스 서버에 접근할 수 있는 권한이 생기는 것.

이러한 그랜트에는 여러 유형이 있다.

1) 승인 코드 그랜트 유형

사용자가 권한 부여 서버에 인증을 한 후, 클라이언트는 이 인증 결과를 바탕으로 권한 부여 서버와 상호작용하여 리소스 서버에 접근할 권한을 얻는 방안

나의 서비스에서 자체 로그인 말고 네이버, 구글 로그인등을 활용하는 것이 이 방안이다.

 

① 1단계 : 인증 요청

클라이언트는 사용자가 인증해야 하는 권한 부여 서버의 엔드포인트로 사용자를 리디렉션한다. 여기서 사용자는 본인을 인증한다. 인증에 성공하고 나면 클라이언트가 권한 부여 서버에 접근하는 것을 사용자가 허가했다는 코드를 반환한다.

사용자와 권한 부여 서버 간의 상호 작용이 수행됨.

 

클라이언트가 사용자를 권한부여 서버로 리디렉션 할 때 요청 쿼리에 포함시켜야 할 내용들

  • response_type
    • 클라이언트가 코드를 기대한다는 것을 권한 부여 서버에게 알리는 값인 code를 포함하고 있음
    • 여기서 코드란 클라이언트가 사용자 대신에 리소스에 접근할 수 있도록 사용자가 인증했다는 증명
  • client_id
    • 클라이언트를 식별하는 클라이언트 ID 값
  • redirect_uri
    • 사용자가 권한 부여 서버 인증에 성공한 후 가게될 곳
  • scope
    • 허가된 권한
  • state
    • CSRF 보호를 위한 토큰

 

② 2단계 : 인증 요청

클라이언트는 토큰을 얻기 위해 1단계 이후 얻은 코드로 권한 부여 서버를 호출한다. 인증에 성공하면 권한 부여 서버는 클라이언트가 리소스 서버에 접근할 수 있는 엑세스 토큰을 반환한다.

클라이언트와 권한 부여 서버 간의 상호작용이 수행됨

 

클라이언트가 권한 부여 서버에게 제시해야 하는 내용들

  • code
    • 1단계에서 사용자가 권한 부여 서버와 상호작용 한 후 받은 사용자의 허가 코드
  • client_id 및 client_secret
    • 자신이 위의 코드를 가로챈 것이 아니라는 것을 증명하는 클라이언트의 자격 증명
  • redirect_uri
    • 클라이언트가 권한 부여 서버 인증에 성공한 후 가게 될 곳
  • grant_type
    • 현재 실행된 인증 흐름이 무엇인지 지정

 

③ 3단계 : 리소스 호출

권한 부여 서버에게서 엑세스 토큰을 받고 나면 클라이언트는 이 토큰을 활용해서 리소스 서버의 엔드포인트를 호출해 데이터를 요청한다.

 

④ 예시

사용자 A는 B라는 서비스를 이용하고 있다. 그런데 B를 이용하다가 구글에 있는 본인의 데이터를 가져오고 싶어졌다. 그래서 A는 B에게 구글에 접근하고 싶다고 요청한다. 이를 위해서는 A가 구글에 접근하길 원한다는 사실을 구글의 권한을 부여해주는 권한부여 서버에게 알려야 하기 때문에, B는 A가 구글에 접근하길 원한다는 사실을 권한부여 서버에 알리라고 한다. A는 권한부여 서버에게 본인이 구글에 접근하고 싶다고 말한다. 그럼 권한부여 서버는 A가 허락했다는 것을 B에게 알린다. 그럼 B는 권한부여 서버에게 구글에 접근할 수 있는 토큰을 보내달라고 하고, 권한 부여 서버는 토큰을 보내준다. 그르면 B는 아까 받은 토큰을 이용해 구글에게 A의 데이터를 얻고 싶다는 요청을 보내고, 구글은 토큰을 확인한 후 올바른 토큰이면 A의 데이터를 보내준다.

 

2) 암호 그랜트 유형

사용자와 클라이언트가 사용자의 자격증명을 공유해서, 클라이언트가 이 자격증명을 이용해 권한 부여 서버와 상호작용하며 리소스에 접근할 수 있는 권한을 얻는 방안

 

① 1단계 : 액세스 토큰 요청

클라이언트는 사용자의 자격 증명을 얻고, 이를 권한 부여 서버에 보내서 올바른 경우 액세스 토큰을 얻는다. 

 

클라이언트가 권한 부여 서버에게 액세스 토큰을 요청할 때 보내야 할 내용들

  • grant_type
    • password 값
  • client_id 및 client_secret
    • 클라이언트가 자신을 인증하기 위한 자격 증명
  • scope
    • 허가된 권한
  • username 및 password
    • 사용자의 자격 증명 내용
    • 일반 텍스트 형식으로 요청 헤더의 값에 넣어져서 전송된다

 

② 2단계 : 액세스 토큰을 이용해 리소스 호출

1단계에서 액세스 토큰을 얻은 클라이언트는 이 토큰으로 리소스 서버의 엔드포인트를 호출하며 리소스를 요청한다. 헤더에 액세스 토큰을 추가해서 보낸다. 응답에 성공하면 리소스를 얻을 수 있다.

 

③ 예시

사용자 A는 B라는 서비스를 이용하고 있다. 그런데 B를 이용하다가 구글에 있는 본인의 데이터를 가져오고 싶어졌다. 그래서 A는 B에게 본인의 자격 증명을 준다. B는 권한 부여 서버에게 A의 자격 증명을 주고, 권한 부여 서버는 자격 증명이 올바른 것인지 확인한 후 올바르면 B에게 구글에 접근할 수 있는 토큰을 준다. B는 구글에게 이 토큰을 이용해 데이터를 얻고 싶다는 요청을 보낸다.

 

3) 클라이언트 자격 증명 그랜트 유형

클라이언트의 자격 증명을 권한 부여 서버에게 보낸 후 인증을 받고, 제대로 된 인증일 경우 권한 부여 서버로부터 리소스에 접근할 수 있는 권한을 받는 방안

 

① 1단계 : 액세스 토큰 요청

클라이언트는 권한 부여 서버에 클라이언트의 자격 증명을 보낸 후 액세스 토큰을 얻는다

 

클라이언트가 권한 부여 서버에 보내야 하는 내용

  • grant_type
    • client_credentials 
  • client_id 및 client_secret
    • 클라이언트의 자격 증명
  • scope
    • 허가된 권한

 

② 2단계 : 리소스 호출

클라이언트는 1단계에서 받은 액세스 토큰을 이용해 리소스를 호출한 후 리소스를 얻는다. 요청 헤더에 액세스 토큰을 추가한다.

 

4. 갱신 토큰(Refresh Token)

1) 개념

만료되지 않는 액세스 토큰이 있다고 할 때, 누군가가 이 토큰을 가로챈다면 리소스를 계속 사용할 수 있게 된다. 따라서 보안에 취약해진다.

이를 방지하기 위해 토큰의 수명을 짧게 만들어야 하는데, 이 짧게 만들어진 액세스 토큰이 만료되고 난 이후 새로운 액세스 토큰을 얻기 위해 클라이언트가 권한 부여 서버에게 보내는 것이 갱신 토큰이다. 

2) 작동

클라이언트가 승인 코드 그랜트 유형이나 암호 그랜트 유형을 이용해 권한 부여 서버로부터 액세스 토큰과 갱신 토큰을 받는다. 만약 액세스 토큰이 만료되면 클라이언트는 권한 부여 서버에게 갱신 토큰을 보내고 새롭게 액세스 토큰과 갱신 토큰을 받는다.

 

클라이언트가 액세스 토큰 만료시 권한 부여 서버에게 보내야 하는 내용

  • grant_type
    • refresh_token 값을 나타내는 grant_type
  • refresh_token
    • refresh_token 값 자체
  • client_id 와 client_secret
    • 클라이언트의 자격 증명
  • scope
    • 맨 첫 액세스 토큰 얻었을 때 권한 부여 서버에게 보냈던 것과 같거나 범위가 좁은 권한 

 

5. 허점

1) 클라이언트에서 CSRF 이용

애플리케이션이 CSRF 보호 매커니즘을 적용하지 않으면 CSRF가 가능한 위험에 빠질 수 있다.

2) 클라이언트 자격 증명 도용

클라이언트의 자격 증명이 보호되지 않는다면 공격자가 도용할 수 있다

3) 토큰 재생

토큰을 네트워크를 통해 보내는 동안 누군가 가로채면 가로챈 토큰을 이용해 계속해서 리소스에 접근할 수 있는 토큰 재생 문제가 발생할 수 있다.

4) 토큰 하이재킹

인증 프로세스를 방해하고 리소스에 액세스하기 위한 토큰을 훔치는 것. 갱신 토큰을 가로채서 새 액세스 토큰을 얻는 위험이 발생할 수 있다.

 

 

'Spring > security' 카테고리의 다른 글

[시큐리티] OAuth2 - 승인 코드 그랜트 유형 깃허브로 연습  (0) 2023.03.31
[시큐리티] 토큰  (0) 2023.03.29
[시큐리티] CORS  (0) 2023.03.28
[시큐리티] CSRF  (0) 2023.03.27
[시큐리티] 필터  (0) 2023.03.23