Spring Security (4) - OAuth2

spaghetti·2025년 3월 19일

Spring Security

목록 보기
6/7

웹서비스를 개발하다보면 카카오, 네이버, 구글과 같은 소셜 로그인을 구현해야할 때가 있다. 이 때 OAuth2 개념과 마주하게 되는데, 기본 개념과 spring에서 구현하는 방법을 알아보고자 한다.


OAuth2 란?

이는 권한부여와 인증을 위한 표준 프로토콜로 타사 웹사이트나 웹이 나의 리소스(애플리케이션)에 접근 할 수 있도록하는 개방형 표준이다.
spring security에서는 http basic 방식과 form login 방식이 존재하는데 이는 단점들이 존재한다.

  • http basic 인증방식은 모든 엔드포인트 요청에 자격증명(id와 비밀번호)를 포함시켜 보내야한다. 즉, 네트워크를 통해 데이터를 자주 공유해야하고 클라이언트에서도 자격증명 데이터를 저장/관리하고 있어야하므로 보안적으로 위험하다.
  • form login 방식은 세션공유 방식으로 여러개의 서버가 있을 경우 세션공유 문제가 발생하고 SSO 지원하기에는 불편함이 있다. 외부 서비스/모바일 서비스 등의 연동이 불가하므로 MSA 방식이 많아지고 있는 요즘에는 구현하는데 많은 어려움이 따른다.

이러한 문제를 해결하고자 권한부여 서버를 통해 사용자의 자격증명을 유지하고 이 서버를 이용해서 사용자를 인증할 수 있는 OAuth2가 등장했다.

1) 용어

  • 사용자 : 리소스 서버가 노출하는 리소스를 소유하는 개인

  • 클라이언트 : 사용자를 대신해 사용자가 소유한 리소스에 접근하는 애플리케이션이다. 흔히 프론트가 이러한 역할을 한다. 웹 애플리케이션, 모바일 앱, 데스크 톱등 다양한 형태를 가지고 있다.

  • 리소스 서버 : 사용자가 소유한 리소스를 호스팅하는 서버로 흔히 우리가 구현하는 백 애플리케이션이라고 보면 된다. 리소스 서버는 access token이 어디서 발급되었는지 신경쓰지 않는다. 그저 해당 토큰의 유효성을 확인하고 이 정보를 어떻게할지 결정하는 것으로 제한된다.

  • 권한부여 서버 : 리소스 서버가 노출하는 사용자의 리소스에 접근할 권한을 부여하는 애플리케이션으로, 사용자의 신원을 확인하고 로그인처리를 하며 토큰을 발급해주는 곳이다. 흔히 소셜 로그인을 담당하는 구글, 네이버 등이 이에 해당한다고 볼 수 있다.

  • BFF(Backend For Frontend) : 프론트엔드를 위해 별도로 설계된 백엔드인데, 프론트엔드와 백엔드 사이에서 최적화된 API를 제공하는 백엔드 레이어다. 이를 통해서 프론트엔드가 직접 인증서버에 접근하지 않고 BFF가 토큰을 관리하면서 보안을 강화하는 방법이다. BFF 개념은 좀 더 넓은 의미로 쓰이므로 자세한 것은 해당 링크로 참고.

2) 흐름

1️⃣ 프론트엔드가 로그인 요청을 하면, 인증서버에서 로그인 페이지로 리다이렉션(ex. 구글 로그인)
2️⃣ 로그인 인증시 ~client?code=xxx와 같이 authorization code를 보내주는데, 이 code를 BFF로 보낸다.
3️⃣ BFF인증서버로 해당 code를 전송하고 access token을 발급해준다.
4️⃣ BFF는 access token을 받아 내부에 저장한다.
5️⃣ 사용자프론트엔드에서 API를 요청하면, BFF가 내부적으로 토큰을 사용하여 리소스 서버와 통신한다.
6️⃣ 리소스 서버는 해당 토큰을 통해 인증서버와 통신하여 토큰을 검증 후 권한이 확인되면 필요한 데이터를 전송한다.

흐름을 보면 authorization code와 access token 두개의 다른 토큰이 발행되는데, 사실 구현방법은 두가지가 있다.

  • 승인코드 방법
    위에서 말한 흐름의 방법으로 소셜 로그인 양식 페이지를 오픈해서 우선 코드와 상태값을 제공(상태값을 제공하지 않는 경우도 있는 듯)한다. 이때 인증 서버와 클라이언트는 여러 검증을 하는데
    1) 클라이언트는 상태값이 요청에 보낸 것과 같은지 검증
    2) 다른 사람이 리다이렉션 uri를 호출하려는 것인 아닌지 검증
    등등을 한 후 access token을 발급받는 과정을 거친다.
    이는 access token이 바로 리소스 접근이 가능하기 때문에 승인된 코드를 이용하여 다시 한번 자격증명을 하는 방식으로 안정성을 높이고자 고안된 방식이다.

  • 암호방법
    클라이언트가 직접 사용자 자격증명을 수집하고 이를 인증해서 access token을 바로 얻는 방법이다. 이는 사용자와 클라이언트가 자격증명을 공유한다고 가정하기 때문에, 클라이언트와 권한부여 서버를 같은 조직에서 구축하고 관리할때만 안전한 방법이라고 한다. 두번의 토큰을 발급받는 과정이 사라지기 때문에 조금 더 간단하지만 보안적으로는 덜 안전하다.

💡OIDC(Open ID Connect)
이는 OAuth2 기반으로 만들어진 OAuth 중 ID 계층(인증)을 담당하는 것이다. OAuth2가 기본적으로 제공하지 않는 scopes, endpoint discovery와 같은 영역을 표준화 하였다. OIDC 개념이 없을때는 Oauth의 핵심 목적이 인증이 아닌 인가였기 때문에 사용자의 신원정보는 전혀 알 수 없었다.
그래서 OIDC는 핵심 목적이 인증이기 때문에 사용자 정보만 보내고 권한과 같은 authorization 정보는 보내지 않는다. (이는 access token을 발급받을때 알 수 있음) 그래서 보통 클라이언트 애플리케이션 - 인증서버 사이에서만 해결한다.
또한 OIDC가 생기면서 이전에 Spring boot에서도 인증서버와 연동할때 spring 에 의존적인 라이브러리가 필요했으나 단순하고 독립적으로 지원할 수 있는 방식으로 변화하였다.


[출처]

profile
개발 그렇게 하는거 아닌데의 그렇게를 맡고있습니다

0개의 댓글