Spring Boot 의 REST API의 Oauth2 Client
1. Spring Boot에서 Spring Security의 Oauth2 Client 사용하기
xxxxxxxxxx
Spring Boot Security OAuth2 Client 예제 : https://www.baeldung.com/spring-security-5-oauth2-login
Spring Boot를 이용해 서버개발을 하던 중 Oauth2를 이용하여 사용자 인증 및 권한을 관리해야 했습니다. 위의 예제를 따라하시면 금방 구현해낼 수 있습니다.
Google Console 사용자 인증정보
조금 헷갈리는 부분이 리디렉션 URI
를 설정하는 부분인데, 원래는 임의로 리디렉션 URI를 설정해도 되지만, Spring Boot의 OAuth2 자동설정을 이용해서 OAuth2 Client를 구축했다면 위의 URI를 사용해야 합니다.(내부에서 자동으로 저 URI가 사용되기 때문입니다.)
2. Spring Security에서 제공하지 않는 다른 Provider의 Oauth2 사용하기 (Spring Boot Security Oauth2 Client + KAKAO Oauth2)
위와 같이 Spring boot에서 제공해주는, google, facebook과 같은 로그인 연동만이 필요하다면 얼마나 좋겠습니까. 하지만, 현실은 그렇지 않더군요.. 때문에 다른 Provider
에서 제공하는 Oauth2를 사용하기 위한 설정을 살펴보도록 하겠습니다. 우선은 Kakaotalk
의 Oauth2를 이용해보겠습니다.
2.1 OAuth2 인증 절차 Sequence Diagram
우선 OAuth2를 우리 시스템에 도입하기 전에 OAuth2가 동작하는 과정을 인지한다면, 조금 더 쉽게 구현할 수 있을 것입니다.
xxxxxxxxxx
OAuth2 인증 과정 : https://galid1.tistory.com/106
위 링크를 참고해주세요. 위의 글을 읽기 귀찮다면, 아래의 Sequence Diagram을 보셔도 좋습니다.
Resource Owner(정보의 주인)의 승인 과정
Access Token발급 과정
2.2 카카오 API 사용을 위한 준비
xxxxxxxxxx
KAKAO API 사용준비 : https://developers.kakao.com/docs/restapi/getting-started
위의 링크로 이동하면 kakao 개발자 가이드를 참조할 수 있습니다. 위의 링크를 따라가면 Spring Security에서 Kakao talk 로그인을 통해 인증을 할 준비를 마칠수 있습니다. 우선 각 단계를 직접 해보면서 다음단계로 넘어가겠습니다.
1. 개발자 등록
그 다음 https://developers.kakao.com/ 로 이동하여 로그인을 한 뒤 개발자 등록을 마칩니다.
2. App 생성
로그인한 뒤 좌측의 앱만들기 탭을 이용하여 앱을 생성합니다.
3. 사용자 관리 설정
카카오 로그인을 사용하기 위해서는 위의 알림 문구처럼 사용자 관리 설정을 해야 합니다. 사용자 관리 설정에서는 앱에서 필요로 하는 정보를 카카오로 부터 가져오기 위해 scope를 설정하는 것을 진행합니다. 필요에 따라 적절히 설정하면 됩니다.
4. Redirect URL 추가
앞서 만든 App을 선택한 뒤 좌측의 설정-일반
탭에서 플랫폼 추가를 클릭합니다.
테스트를 위해 localhost를 사이트 도메인으로 입력하고, redirect Path
는 Spring Boot Security Oauth2 Client에서 설정할 Redirect Path와 일치시켜야 하기 때문에 여기서 입력한 Redirect Path를 기억해두어야 합니다.
2.3 KAKAO REST API 살펴보기
여기까지 진행하셨으면, KAKAO API를 사용할 준비는 끝났습니다. 이제는 KAKAO API를 사용하는 방법을 알아보도록하겠습니다.
xKAKAO REST API : https://developers.kakao.com/docs/restapi/quick-reference
우선, 위의 링크로 이동합니다.
로그인 기능을 구현할 것이므로 로그인 코드받기를 클릭하여 이동합니다.
여기로 이동하면 로그인인증 요청을 위한 URL
과 각 Parameter
에 대한 자세한 설명을 볼 수 있습니다. 우리 Spring Boot Server에서는 이 규격에 맞게 요청을 만들어 인증을 구현하면 됩니다. 당연히 표에 보이는 필수 값
들은 parameter
에 포함시켜 넘겨주어야 합니다.
client_id
client_id 는 처음 app을 생성할때에도 나타나지만, 그때 기록을 해두지 않았다면, 내 애플리케이션 - 설정 - 일반
에서 확인이 가능합니다.
redirect_uri
예를 들어 우리의 도메인을 http://localhost:8080
, redirect path을 /login/oauth2/code/kakao
로 설정했기 때문에, redirect_uri는 http://localhost:8080/login/oauth2/code/kakao
가 됩니다.
reponse_type
그림에서도 볼 수 있듯이 code
문자열값으로 고정이 되어있으므로 code라는 문자열을 그대로 사용하면 됩니다.
2.4 Spring Security에서 Oauth2 Client를 사용하기 위한 개념
우선 우리가 OauthClient를 Spring Boot에 등록하고 사용하기 위해서는 ClientRegstration, ClientRegstrationRepository
를 알아야 합니다.
ClientRegistration
Oauth2 제공자
에 등록된 Client (즉, 우리 App)
의 정보를 나타내는 클래스입니다.
ClientRegistration은 registrationId를 통해 기초설정이 된 ClientRegistration을 저장해두고 추후 사용하는 곳에서 ClientRegistration.getBuilder(registrationId) 을 이용해서 가져와 추가 설정을 할 수 있습니다.
ClientRegistrationRepository
Oauth2 제공자들에 등록된 우리 App의 정보들(client_id, secret, redirect_uri)
들은 궁극적으로 Oauth2 제공자(google, facebook, kakao 등)
에 저장되고 소유되기 때문에, 우리 App의 Server에서 요청하기 위해서는 이 정보들을 별도로 가지고 있어야합니다.
따라서 이런 Oauth2 에 등록된 App의 정보들의 복사본이 저장되어 관리되는 클래스가 ClientRegistrationRepository
입니다. 구현체로는 InMemoryClientRegistrationRepository
가 대표적입니다.
2.5 Spring Boot Security의 Oauth2 Client 자동 등록 살펴보기
SpringBoot에서는 Oauth2 인증 제공자
에 대한 설정을 손쉽게 할 수 있도록 Oauth2ClientAutoConfiguration
을 제공하고 있습니다.
Oauth2ClientAutoConfiguration
xxxxxxxxxx
SecurityAutoConfiguration.class) (
EnableWebSecurity.class, ClientRegistration.class }) ({
type = ConditionalOnWebApplication.Type.SERVLET) (
OAuth2ClientRegistrationRepositoryConfiguration.class, OAuth2WebSecurityConfiguration.class }) ({
public class OAuth2ClientAutoConfiguration { }
말그대로 Oauth2Client
에 대한 설정을 자동으로 해주는 클래스입니다. 이 클래스는 OAuth2ClientRegistrationRepositoryConfiguration, OAuth2WebSecurityConfiguration
을 @Import 하고 있습니다. 각각을 조금 더 살펴보겠습니다.
OAuth2ClientProperties.class) (
ClientsConfiguredCondition.class) (
class OAuth2ClientRegistrationRepositoryConfiguration {
private final OAuth2ClientProperties properties;
OAuth2ClientRegistrationRepositoryConfiguration(OAuth2ClientProperties properties) {
this.properties = properties;
}
ClientRegistrationRepository.class) (
public InMemoryClientRegistrationRepository clientRegistrationRepository() {
List<ClientRegistration> registrations = new ArrayList<>(
OAuth2ClientPropertiesRegistrationAdapter.getClientRegistrations(this.properties).values());
return new InMemoryClientRegistrationRepository(registrations);
}
}
이 클래스는 RegistraionRepository
에 잘 알려진 OAuth2 Provider들(Google, GitHub, FaceBook 등)에 대한 각각의 ClientRegistration
설정을 해주는 역할을 합니다.
clientRegistrationRepository()
의 @ConditionalOnMissingBean()
을 보면 알 수 있듯이 ClientRegstrationRepository
빈을 직접 설정 파일에 생성하여 주입하는 경우에는 Spring Boot에서 자동으로 설정해주는 값을 이용할 수 없으므로, Spring Boot Security Oauth2 Client
에서 제공하지 않는 다른 Provider(KAKAO)
를 이용하면서 동시에 Google, FaceBook OAuth
을 사용하고 싶다면 꼭 설정을 직접 해주어야 합니다.
CommonOAuth2Provider
public enum CommonOAuth2Provider {
GOOGLE {
public Builder getBuilder(String registrationId) {
ClientRegistration.Builder builder = getBuilder(registrationId,
ClientAuthenticationMethod.BASIC, DEFAULT_REDIRECT_URL);
builder.scope("openid", "profile", "email");
builder.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth");
builder.tokenUri("https://www.googleapis.com/oauth2/v4/token");
builder.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs");
builder.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo");
builder.userNameAttributeName(IdTokenClaimNames.SUB);
builder.clientName("Google");
return builder;
}
},
FACEBOOK, GITHUB...
추가적으로 CommonOauth2Provider
는 Spring Security에서 잘 알려진 Oauth2 제공자(Google, Facebook, github 등)을 조금 더 손쉽게 설정하기 위해 제공되는 클래스입니다.
2.6 Spring Boot + SpringSecurity OAuth2 Client + KAKAO OAuth2 예제
정말 간단하게도 딱 2가지 파일만 추가적으로 작성하면 됩니다.
CustomOAuth2Provider
public enum CustomOAuth2Provider {
KAKAO {
public ClientRegistration.Builder getBuilder(String registrationId) {
ClientRegistration.Builder builder = getBuilder(registrationId, ClientAuthenticationMethod.POST, DEFAULT_LOGIN_REDIRECT_URL)
.scope("profile")
.authorizationUri("https://kauth.kakao.com/oauth/authorize")
.tokenUri("https://kauth.kakao.com/oauth/token")
.userInfoUri("https://kapi.kakao.com/v1/user/me")
.userNameAttributeName("id")
.clientName("Kakao");
return builder;
}
};
private static final String DEFAULT_LOGIN_REDIRECT_URL = "{baseUrl}/login/oauth2/code/{registrationId}";
protected final ClientRegistration.Builder getBuilder(
String registrationId, ClientAuthenticationMethod method, String redirectUri) {
ClientRegistration.Builder builder = ClientRegistration.withRegistrationId(registrationId)
.clientAuthenticationMethod(method)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUriTemplate(redirectUri);
return builder;
}
public abstract ClientRegistration.Builder getBuilder(String registrationId);
}
CommonAuth2Provider
클래스를 참고하여 만든 클래스로, 기본적으로 OAuth2Client
에 필요한 정보들(redirect_uri, authorizationUri, tokenUri, userInfoUri)
이 추가되어있는 Builder를 반환합니다.
SpringSecurityConfig
이 클래스에서는 Spring Security 관련한 설정과, 우리가 사용할 OAuth2 인증 제공자 설정을 해야합니다.
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login", "/oauth2/**", "/")
.permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
public ClientRegistrationRepository clientRegistrationRepository(
"${spring.security.oauth2.client.registration.kakao.client-id}") String kakaoClientId, (
"${spring.security.oauth2.client.registration.kakao.client-secret}") String kakaoClientSecret) { (
List<ClientRegistration> registrations = new ArrayList<>();
registrations.add(CustomOAuth2Provider.KAKAO.getBuilder("kakao")
.clientId(kakaoClientId)
.clientSecret(kakaoClientSecret)
.jwkSetUri("temp")
.build());
return new InMemoryClientRegistrationRepository(registrations);
}
}
우선 Spring Boot에서는 OAuth2의 인증에 관련한 Url 설정들이 자동으로 되어있는 OAuth2WebSecurityConfigurerAdapter
빈이 자동으로 등록이 되는데, 위와 같이 직접 WebSecurityConfigurerAdapter
클래스를 상속받는 설정파일을 Bean에 등록하게 되면 별도로 설정을 해주어야 합니다. 때문에, configure(HttpSecurity http)
메소드를 구현하여 설정을 진행합니다.
추가적으로 우리가 사용할 Oauth2 인증 제공자
설정이 담긴 ClientRegistrationRepository
를 Bean으로 등록해야합니다. 이때 앞서 생성했던 CustomOAuth2Provider
를 이용해서 App마다 변경이 될수 있는 정보들(Client_id, Client_secret) 만을 ClientRegistration
생성시 따로 기입하여 ClientRegistration
을 생성한 뒤 그것을 추가한 InMemoryClientRegistrationRepository
를 반환합니다.
'FrameWork > Spring Security' 카테고리의 다른 글
Spring Security - SpringSecurity 이용하기 4 (Database를 이용한 Login 구현) (4) | 2020.02.23 |
---|---|
Spring Security - SpringSecurity 이용하기 3 (logout 기능 추가하기) (0) | 2020.02.23 |
Spring Security - SpringSecurity 이용하기 2 (login Success Handle) (0) | 2020.02.22 |
Spring Security - SpringSecurity 이용하기 1 (custom login form 구현) (2) | 2020.02.12 |
SpringSecurity - SpringSecurity 간단한 설정과 예제 (2) | 2019.07.01 |