[Spring boot] Spring boot Security로 시작해보는 인증

Spring Framework를 이용하여 웹 서비스나 REST API 서비스를 개발하게 되면 가장 필요로 하는 것은 바로 인증일 것입니다. 여기서 말하는 인증이란, 내가 개발한 서비스를 이용하기 위해 식별하고자 하는 사용자 혹은 관리자라고 할 수 있습니다.

 

일반적으로 Spring을 이용해서 인증 로직을 구현하고자 한다면, JPA를 이용해 사용자 Entity를 만들고, 연동하여 아이디와 패스워드를 동기화 한 후, 권한을 부여하는 방식으로 로직을 구현할 수 있을 것입니다. 

 

그런데, 이를 직접 구현하지 않아도 이미 잘 만들어진 모듈이 있습니다. 그것이 바로 Spring boot Security입니다. 이번 포스트에서는 Spring boot Security를 왜 사용해야 하는지, 사용하기 위해 어떤 개념들을 공부해야 하는지, 끝으로 어떻게 동작하는지에 대해 알아보고, 최근 자주 사용하는 OAuth2 인증 방식을 이용하여 소셜 로그인을 구현해보기 전, 어떻게 동작하는지에 대해 알아보는 시간을 갖도록 하겠습니다.

 

 

Spring boot Security

스프링 부트에서는 인증과 권한에 관련된 강력한 기능이 제공되는 스프링 부트 시큐리티를 제공합니다. 기존 스프링 시큐리티의 번거로운 설정을 줄이고, 개발자가 보안 문제에 깊이 신경쓰지 않고도 인증에 대한 핵심 로직만을 개발할 수 있도록 한 모듈입니다. 정말 편리하지요.

 

이 모듈을 사용하기 위해서 우리가 짚고 넘어가야 할 중요한 개념은 두 가지입니다. 바로 인증과 권한 부여인데요. 인증은 사용자가 애플리케이션의 특정 동작에 관하여 인증된 사용자인지를 확인하는 절차이고, 권한 부여는 데이터나 프로그램 등의 특정 자원이나 서비스에 접근할 수 있는 권한을 부여하는 일입니다. 

 

쉽게 예를 들자면, 웹 사이트에서 어떤 서비스를 이용하기 위해 내가 어떤 사용자인지 확인하고, 그에 맞는 권한을 부여하여 사용을 도와주는 녀석이라고 생각하시면 됩니다.

 

 

 

OAuth2

또 한 가지 짚고 넘어가야 할 개념이 있는데, 최근에는 다양한 인증 방식이 나오고 있습니다. 일반적인 ID/PW 인증 뿐만 아니라 여기에 AD/LDAP 등의 디렉터리 통합 인증, 그리고 Social Network의 등장으로 OAuth2라는 통합 인증까지 등장했지요.

 

여기서 OAuth란, 토큰을 사용한 범용적인 방법의 인증을 제공하는 표준 인증 프로토콜입니다. 옆에 붙어 있는 2는 버전으로 최근에 가장 많이 사용하는 OAuth 프로토콜 2.0 버전인 것이지요.

 

OAuth2에서 제공하는 승인 타입은 총 4가지가 있습니다.

 

  • 권한 부여 코드 승인 타입 (Authorization Code Grant Type)
    클라이언트가 다른 사용자 대신 특정 리소스에 접근을 요청할 때 사용하는 타입입니다. 리소스 접근을 위한 사용자 아이디와 비밀번호, 권한 서버에 요청해서 받은 권한 코드를 함께 활용하여 리소스에 대한 액세스 토큰을 받으면 이를 인증하여 이용하는 방식

  • 암시적 승인 타입 (Implicit Grant Type)
    권한 부여 코드 승인 타입과 다르게 권한 코드 교환 단계 없이 액세스 토큰을 즉시 반환받아 이를 인증에 이용하는 방식

  • 리소스 소유자 암호 자격 증명 승인 타입 (Resource Owner Password Credentials Grant Type)
    클라이언트가 암호를 사용하여 액세스 토큰에 대한 사용자의 자격 증명을 교환하는 방식

  • 클라이언트 자격 증명 승인 타입 (Client Credentials Grant Type)
    클라이언트가 컨텍스트 외부에서 액세스 토큰을 얻어 특정 리소스에 접근할 때 사용하는 방식

타입은 여러가지가 있는데, 이 중에서 가장 자주 사용하는 타입은 바로 권한 부여 코드 승인 타입입니다. Google, Facebook, Kakao 등 다양한 소셜 미디어 서비스들이 사용하는 타입이며 보통 웹 서버 형태의 클라이언트를 지원하는 데 있어 장기 액세스 토큰을 이용하여 처리합니다.

 

 

 

OAuth2 동작 과정

그렇다면 이렇게 소셜 미디어 서버로부터 내 애플리케이션으로 권한을 부여하는 데 어떤식으로 동작이 되는 것일까요?

 

위와 같은 시퀀스 다이어그램으로 동작하긴 하지만, 그림으로 보기에는 굉장히 복잡합니다. 간단히 설명을 드리가 전에, 각 Object가 무엇인지를 먼저 말씀드리면...

 

  • Resource Owner: 서비스를 사용하려는 사용자
  • Client: 웹 사이트 혹은 API 서버
  • Permission Server: 소셜 미디어 권한 부여 서버
  • Resource Server: 소셜 미디어 리소스 서버

이렇게 구성이 되어 있는데요. 권한 서버는 해당 사용자가 우리 소셜 미디어의 사용자인지를 체크하는 것이고, 리소스 서버는 이를 인증할 수 있도록 제공해주는 토큰 발급 서버입니다.

 

먼저 처음에는 Client(웹 사이트)가 파라미터로 Client ID, Redirect URI, 응답 타입을 code로 지정하여 권한 서버에 전달합니다. 이 때 Client ID는 여러분들이 한 번 쯤 소셜 미디어 개발 API를 사용할 때 받는 Client ID를 말합니다. 즉 내가 만든 웹 서비스가 아닌 소셜 미디어의 클라이언트를 이야기하는 것이지요.

 

정상적으로 소셜 미디어에서 클라이언트 인증이 확인되었다면, 권한 부여 코드를 클라이언트에게 보냅니다. (이 때, 권한 부여 코드가 code이면, 권한 부여 코드 승인 타입, token이면 암시적 승인 타입) 클라이언트는 이 코드를 사용하여, 마지막으로 액세스 토큰을 권한 서버에 추가로 요청합니다. 이 때 필요한 파라미터는 Client ID, Client Secret, Redirect URI, 인증 타입입니다. 

 

마지막으로 응답 받은 액세스 토큰을 사용하여 리소스 서버에 사용자의 데이터를 요청합니다. 여기서 말하는 사용자의 데이터란, 이메일, 이름 등 다양한 개인 정보가 포함되어 있습니다.

 

이렇게 내가 만든 서버가 소셜 미디어의 로그인을 사용하기 위해서는 소셜 미디어 서버에 사용자의 개인 정보를 요청하기 위한 토큰 발급 과정을 포함하여 총 3단계의 API 요청을 거치게 됩니다. 기존의 ID/Password 로그인 방식에 비핵서 API 요청을 많이 한다는 점이 보이는 것이지요. 

 

하지만 사용자 입장에서는 복잡한 회원 가입 절차 없이 기존의 소셜 계정으로 내 서비스를 이용할 수 있다는 메리트가 있기 때문에 서비스 측면에서는 회원 가입 기능을 축소하는 점에 있어 편리하다고 할 수 있지요.

 

 

 

OAuth2를 사용한 인증 과정

위의 시퀀스 다이어그램을 통해서 내 애플리케이션이 소셜 미디어 서버를 통해 어떤식으로 사용자의 정보를 가질 수 있는지를 이해하였습니다. 그렇다면 내 서비스로 인증 과정을 진행하고, 권한을 부여하는 것은 어떤식으로 동작하는 것일까요?

 

보통 User, Password 형태로 로그인을 구현한다면 일반적으로 로그인 정보를 서버 내 세션에 저장해놓을 것입니다. 이와 마찬가지로 소셜 로그인도 세션을 먼저 확인한 다음, 기존 세션이 존재한다면 URI를 요청하고, 그렇지 않다면 가입된 사용자인지를 확인한 다음, 그렇지 않을 경우에 소셜 서버에 요청하여 사용자 정보를 가져온 후, 자동 회원 가입 절차를 진행하는 방향으로 소셜 로그인을 구현할 수 있습니다.

 

이 때, 각 소셜 서비스별로 User 객체를 다르게 주는 이유는 서비스별로 반환하는 정보들이 다 다르기 때문입니다. 따라서 그들 도메인에 맞게 Class를 별도로 구현해야 하고, DB에 저장하면 됩니다.

 

 

 

마치며...

여기까지 간단하게 Spring boot Security와 OAuth2에 대해 알아봤습니다. 우리가 사용할 때는 쉽고 편하게 사용할 수 있던 소셜 로그인 서비스를 직접 구현하고 동작 방식을 확인해본다면, 처음에는 굉장히 어려울 수도 있을 것입니다. 그러나 그 원리를 제대로 안다면, 그렇게 어렵지는 않습니다.

 

다음 포스트에서는 새로운 프로젝트를 만들고, Spring boot Security를 이용하여 OAuth2를 구현해보도록 하겠습니다.

comments powered by Disqus

Tistory Comments 0