The Spring Boot 2.x auto-configuration class for OAuth Client support is OAuth2ClientAutoConfiguration.
It performs the following tasks:
Registers a ClientRegistrationRepository @Bean composed of ClientRegistration(s) from the configured OAuth Client properties.
Registers a SecurityFilterChain @Bean and enables OAuth 2.0 Login through httpSecurity.oauth2Login().
If you need to override the auto-configuration based on your specific requirements, you may do so in the following ways:
https://docs.spring.io/spring-security/reference/servlet/oauth2/login/core.html
@Configuration
public class OAuth2LoginConfig {
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
}
private ClientRegistration googleClientRegistration() {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
}
}
이렇게 하면 자동으로
httpSecurity.oauth2Login().
여기에서 해당 config 설정을 읽는다.
본 프로젝트에서는 이렇게 변경
properties에 secret 변수 설정후,
@Configuration
public class OAuth2LoginConfig {
@Value("${spring.security.oauth2.client.registration.google.client-id}")
String clientId;
@Value("${spring.security.oauth2.client.registration.google.client-secret}")
String secretId;
@Value("${spring.security.oauth2.client.registration.google.redirect-uri}")
String redirectUri;
@Value("")
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(Collections.singletonList(this.googleClientRegistration()));
}
private ClientRegistration googleClientRegistration() {
return ClientRegistration.withRegistrationId("google")
.clientId(clientId)
.clientSecret(secretId)
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri(redirectUri)
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
}
}
이후에,
@Slf4j
@Configuration
@EnableWebSecurity(debug=true)
@RequiredArgsConstructor
public class SecurityConfig {
private final TokenProvider tokenProvider;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final ClientRegistrationRepository clientRegistrationRepository; //OAuth2LoginConfig에서 @Configuration으로 등록된 bean 주입
// PasswordEncoder는 BCryptPasswordEncoder를 사용
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors(Customizer.withDefaults())
// token을 사용하는 방식이기 때문에 csrf를 disable합니다.
.csrf(AbstractHttpConfigurer::disable)
.exceptionHandling((exceptionHandling) -> //컨트롤러의 예외처리를 담당하는 exception handler와는 다름.
exceptionHandling
.accessDeniedHandler(jwtAccessDeniedHandler)
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
)
.formLogin((formLogin)->formLogin.disable())
// enable h2-console
.headers((headers)->
headers.contentTypeOptions(contentTypeOptionsConfig ->
headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)))
// disable session
.sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests((authorizeRequests)->
authorizeRequests
.requestMatchers(HttpMethod.OPTIONS,"/**/*" ).permitAll()
//users 포함한 end point 보안 적용 X
.requestMatchers("/users/**").permitAll() // HttpServletRequest를 사용하는 요청들에 대한 접근제한을 설정하겠다.
.requestMatchers("/users/profile/**").permitAll() // 개인 정보 수정은 권한 필요
.requestMatchers("/error/**").permitAll()
.requestMatchers(HttpMethod.GET ,"/memos/**").permitAll()
.requestMatchers(HttpMethod.GET,"/mypage/**").permitAll()
.requestMatchers("/swagger-ui/**","/v2/api-docs",
"/swagger-resources",
"/swagger-resources/**",
"/configuration/ui",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**",
/* swagger v3 */
"/v3/api-docs/**",
"/swagger-ui/**").permitAll()
.requestMatchers("/favicon.ico").permitAll()
.anyRequest().authenticated() // 그 외 인증 없이 접근X
)
.oauth2Login(oauth2->oauth2
.clientRegistrationRepository(clientRegistrationRepository))
.exceptionHandling((exceptionHandling)->exceptionHandling
.accessDeniedHandler(jwtAccessDeniedHandler)
.authenticationEntryPoint(jwtAuthenticationEntryPoint))
.apply(new JwtSecurityConfig(tokenProvider)); // JwtFilter를 addFilterBefore로 등록했던 JwtSecurityConfig class 적용
return httpSecurity.build();
}
중간에 oauth2Login관련 config를 추가해주면 아래 그림과 같이 필터가 추가된 것을 확인할 수 있다.
중간에 OAuth 관련 필터가 추가된 것을 확인할 수 있다.