title: "[Spring] Oauth 이슈"
excerpt: "진행중인 사이드 프로젝트를 하면서 생긴 이슈 정리"
categories:
toc: true
toc_sticky: true
date: 2021-09-02T14:10:00
진행중인 사이드 프로젝트에서 생겼던 이슈를 정리합니다.
모든 코드는 깃허브에 있습니다.
스터디 위키 정리중에창훈님께서 스프링 시큐리티에 대한 정보를 공유해주셨습니다.
그안에 포함되어있는 스프링 시큐리티 Oauth2에 대해서 포스팅을 해볼 것입니다.
OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준입니다. 이 매커니즘은 여러 기업들에 의해 사용되는데, 저희 서비스로 생각한다면 구글, 카카오, 애플, 깃허브, 페이스북 들이 있으며 사용자들이 타사 애플리케이션이나 웹사이트의 계정에 관한 정보를 공유할 수 있게 허용해줍니다.
OAuth인증은 소비자와 서비스 제공자 사이에서 일어나는데 이 인증 과정은 다음과 같습니다.
여기서 소비자는 내 서비스
임을 명시하고
서비스 제공자는 구글
로 가정하겠습니다.
이 Oauth에 대한 인증은 기본적으로 Spring Security 내에 명시가 되어있습니다.
바로 CommonOAuth2Provider
라는 Enum 클래스인데요.
이 클래스를 사용해서 Bean
을 등록하는것도 가능합니다.
public enum CommonOAuth2Provider {
GOOGLE {
@Override
public Builder getBuilder(String registrationId) {
ClientRegistration.Builder builder = getBuilder(registrationId,
ClientAuthenticationMethod.CLIENT_SECRET_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.issuerUri("https://accounts.google.com");
builder.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo");
builder.userNameAttributeName(IdTokenClaimNames.SUB);
builder.clientName("Google");
return builder;
}
},
//....
}
하지만 제가 구현한 방식은 이 방법이 아니라 application.yaml
에서 설정을 해주었습니다.
security:
oauth2:
client:
registration:
google:
client-id: ENC(6/Ponyj/US/TvdVEZJfmcsPmvaXwKaeCWyudJyZDkNoTnloH+R4r0dR8MFFrA90SkJag3l4b67WQrIqR9Oz8Y6IK45M9ypW0DMxUGsOFc3rFijwDrAhK2Q==)
client-secret: ENC(FoXXYeauW6EKov8iMfbE57X8cV9jEf4WSQ+FFmjnNIakgPv768fkng==)
scope: profile, email
설정을 해주면 Oauth2Configurer
를 통해 구현되게 되는데요.
ENC()
는 jasypt
라는 보안으로 인한 암호화 모듈인데요 다른 글에서 포스팅을 하도록 하겠습니다. 😅
OAuth2LoginAuthenticationFilter
에는 Default URI인 /login/oauth2/code/*
가 들어있습니다.
그래서 위의 yaml에서 redirect_uri를 잡아주지 않는다면 이 default를 통해 redirect 하게 됩니다.
그래서 구글 api에도 /login/oauth2/code/google
로 설정해주었습니다.
저희 cors원칙을 설정해주기 위해서 리다이렉션 URI를 /api/v1/login/oauth2/google
과 같이
추가해주기 위해 yaml google에는 아래를 추가해주었습니다.
redirect-uri: '{baseUrl}/api/v1/login/oauth2/{registrationId}'
SecurityConfig
의 일부입니다.
public class SecurityConfig {
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.httpBasic().disable()
// =====일반 로그인 처리 로직 진행=====
// Oauth 로그인 수행
.oauth2Login(login ->
login
.userInfoEndpoint()
.userService(customOauth2UserService)
)
}
}
이렇게하고 구글 api설정도 바꿔주면 진행이 잘될거라고 생각했습니다.
디버깅을 통한 login 이라는 Oauth2LoginConfigurer
의 일부입니다.
{: text-center}
login을 처리하는 url은 바뀌지않고 OAuth2LoginAuthenticationFilter
의 default 값이 들어있는 것을 확인하였습니다.
위 코드에서 login 객체에 보면 프로세싱 url은 변함없이 기본값을 할당하고 있었습니다.
이유는 할당한 채로 제가 커스텀하여 할당하지 않았기 때문에 저 상태로 기본값이 저장되어 있던 것입니다. 😱
해결은
.oauth2Login(login ->
login.loginProcessingUrl("/api/v1/login/oauth2/*")
.userInfoEndpoint()
.userService(customOauth2UserService)
)
이렇게 프로세싱 url을 정해주고 다시 실행하니 정상적으로 실행 되는 것을 확인하였습니다. 👍
이렇게 해서 모든 Oauth 로그인이 돌아가는 형식으로 구성되어 있습니다.
그렇게 하여 ClientResistration
에는 yaml에서 설정했던 id, secret, redirect-uri가 여기서 할당된것을 확인할 수 있습니다.