diff --git a/src/main/java/com/xit/biz/cmm/controller/CmmCodeMgtController.java b/src/main/java/com/xit/biz/cmm/controller/CmmCodeMgtController.java index 1f5e335..7c7055d 100644 --- a/src/main/java/com/xit/biz/cmm/controller/CmmCodeMgtController.java +++ b/src/main/java/com/xit/biz/cmm/controller/CmmCodeMgtController.java @@ -22,7 +22,7 @@ import javax.annotation.Nonnull; @Tag(name = "CmmCodeMgtController", description = "코드 관리") @RestController @RequiredArgsConstructor -@RequestMapping("/api/biz/cmm/code") +@RequestMapping("/api/biz/cmm/callback") public class CmmCodeMgtController { private final ICmmCodeService cmmCodeService; diff --git a/src/main/java/com/xit/core/config/SecurityConfig.java b/src/main/java/com/xit/core/config/SecurityConfig.java index c82cd1d..1b3e95f 100644 --- a/src/main/java/com/xit/core/config/SecurityConfig.java +++ b/src/main/java/com/xit/core/config/SecurityConfig.java @@ -19,8 +19,10 @@ import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.BeanIds; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -66,6 +68,12 @@ import java.util.Arrays; * */ @Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity( + securedEnabled = true, + jsr250Enabled = true, + prePostEnabled = true +) @RequiredArgsConstructor public class SecurityConfig extends WebSecurityConfigurerAdapter { @@ -152,28 +160,43 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http - // Rest API이므로 기본설정 안함 - 기본 설정은 비인증시 로그인 폼으로 direct - .httpBasic().disable() - // Rest API 이므로 csrf 보안 불필요 - .csrf().disable() - // jwt token 인증 - 세션은 필요 없어 생성 안함 - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) - + .cors() + .and() + // jwt token 인증 - 세션은 필요 없어 생성 안함 + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() - .cors() + // Rest API 이므로 csrf 보안 불필요 + .csrf() + .disable() + .formLogin() + .disable() + // Rest API이므로 기본설정 안함 - 기본 설정은 비인증시 로그인 폼으로 direct + .httpBasic() + .disable() + .exceptionHandling() + .authenticationEntryPoint(new RestAuthenticationEntryPoint()) + .accessDeniedHandler(tokenAccessDeniedHandler) .and() - .authorizeRequests() + .authorizeRequests() // GET, POST 요청시 : OPTIONS preflight 요청 - 실제 서버가 살아있는지를 사전에 확인하는 요청 // Spring에서 OPTIONS에 대한 요청을 막고 있어 OPTIONS 요청이 왔을 때도 오류를 리턴하지 않도록 설정 .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() - .antMatchers("/**/signup", "/**/login", "/**/swagger-ui.html").permitAll() - .antMatchers(HttpMethod.GET, "/**/users/**").permitAll() - .anyRequest().permitAll() //.hasRole(RoleType.USER.getCode()) - + .antMatchers( + "/", + "/favicon.ico", + "/**/*.png", + "/**/*.gif", + "/**/*.svg", + "/**/*.jpg", + "/**/*.html", + "/**/*.css", + "/**/*.js").permitAll() + .antMatchers("/auth/**", "/oauth2/**", "/**/users/**").permitAll() + .anyRequest().authenticated() .and() - .exceptionHandling() - .authenticationEntryPoint(new RestAuthenticationEntryPoint()) - .accessDeniedHandler(tokenAccessDeniedHandler) + //.anyRequest().permitAll() //.hasRole(RoleType.USER.getCode()) + // .and() // .logout() @@ -182,27 +205,21 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { // .invalidateHttpSession(true) - .and() - .oauth2Login() + + .oauth2Login() .authorizationEndpoint() .baseUri("/oauth2/authorization") .authorizationRequestRepository(oAuth2AuthorizationRequestBasedOnCookieRepository()) .and() .userInfoEndpoint() - .userService(customOAuth2UserService) - - .and() - .redirectionEndpoint() - .baseUri("/*/oauth2/code/*") - - .and() + .userService(customOAuth2UserService) + .and() .successHandler(oAuth2AuthenticationSuccessHandler()) .failureHandler(oAuth2AuthenticationFailureHandler()) - .and() - // jwt token filter를 id / password 인증 필터 전에 넣는다 - .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); + // jwt token filter를 id / password 인증 필터 전에 넣는다 + .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); http.headers().frameOptions().disable(); } diff --git a/src/main/java/com/xit/core/config/WebCommonConfig.java b/src/main/java/com/xit/core/config/WebCommonConfig.java index 5278524..7f2a12e 100644 --- a/src/main/java/com/xit/core/config/WebCommonConfig.java +++ b/src/main/java/com/xit/core/config/WebCommonConfig.java @@ -25,6 +25,7 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.client.RestTemplate; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -162,6 +163,23 @@ public class WebCommonConfig extends AsyncConfigurerSupport implements WebMvcCon //--------------------------------------------------------------------------- +// /** +// * CORS 설정 +// * TODO :: SecurityConfig#corsConfigurationSource 설정이 안돼는 경우 적용 +// * @param registry CorsRegistry +// * +// * @see SecurityConfig#corsConfigurationSource() +// */ +// @Override +// public void addCorsMappings(CorsRegistry registry) { +// registry.addMapping("/**") +// .allowedOrigins("") +// .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") +// .allowedHeaders("*") +// .allowCredentials(true) +// .maxAge(3600); +// } + //--------------------------------------------------------------------------- // yaml type Message loading //--------------------------------------------------------------------------- diff --git a/src/main/java/com/xit/core/oauth2/api/service/impl/AuthService.java b/src/main/java/com/xit/core/oauth2/api/service/impl/AuthService.java index 2454eb1..3eae122 100644 --- a/src/main/java/com/xit/core/oauth2/api/service/impl/AuthService.java +++ b/src/main/java/com/xit/core/oauth2/api/service/impl/AuthService.java @@ -104,7 +104,7 @@ public class AuthService implements IAuthService { .orElse(null); // 저장된 refresh token not exists - if (Checks.isNull(savedRefreshToken)) { + if (Checks.isNull(savedRefreshToken) || Checks.isNull(savedRefreshToken.getValue())) { // 없는 경우 새로 등록 tokenDto = jwtTokenProvider.generateTokenDto(authentication, infoMap); refreshTokenRepository.saveAndFlush( diff --git a/src/main/java/com/xit/core/oauth2/oauth/repository/OAuth2AuthorizationRequestBasedOnCookieRepository.java b/src/main/java/com/xit/core/oauth2/oauth/repository/OAuth2AuthorizationRequestBasedOnCookieRepository.java index a407253..e27e86a 100644 --- a/src/main/java/com/xit/core/oauth2/oauth/repository/OAuth2AuthorizationRequestBasedOnCookieRepository.java +++ b/src/main/java/com/xit/core/oauth2/oauth/repository/OAuth2AuthorizationRequestBasedOnCookieRepository.java @@ -43,10 +43,10 @@ public class OAuth2AuthorizationRequestBasedOnCookieRepository implements Author return this.loadAuthorizationRequest(request); } - @Override - public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) { - return this.loadAuthorizationRequest(request); - } +// @Override +// public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) { +// return this.loadAuthorizationRequest(request); +// } public void removeAuthorizationRequestCookies(HttpServletRequest request, HttpServletResponse response) { CookieUtil.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); diff --git a/src/main/resources/config/application-oauth.yml b/src/main/resources/config/application-oauth.yml index 587b273..82367f3 100644 --- a/src/main/resources/config/application-oauth.yml +++ b/src/main/resources/config/application-oauth.yml @@ -4,23 +4,29 @@ spring: client: registration: google: - client-id: 259821403087-talgepagvnahurp0bfnk55pujrdaec7q - client-secret: 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 + clientId: 259821403087-talgepagvnahurp0bfnk55pujrdaec7q + clientSecret: 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 + #clientId: 5014057553-8gm9um6vnli3cle5rgigcdjpdrid14m9.apps.googleusercontent.com + #clientSecret: tWZKVLxaD_ARWsriiiUFYoIk + redirectUri: "{baseUrl}/oauth2/callback/{registrationId}" scope: - profile - email facebook: - clientId: 652436969254286 - clientSecret: 822069e9cd00654574d16a88cf3a4be9 + #clientId: 652436969254286 + #clientSecret: 822069e9cd00654574d16a88cf3a4be9 + clientId: 121189305185277 + clientSecret: 42ffe5aa7379e8326387e0fe16f34132 + redirectUri: "{baseUrl}/oauth2/callback/{registrationId}" scope: - email - public_profile kakao: clientId: 1d0012ecc1e9d454a69b3a850c546879 clientSecret: bfctm9QldllT81f2UK7L0Cc5QDcDfsYb + redirectUri: "{baseUrl}/oauth2/callback/{registrationId}" clientAuthenticationMethod: post authorizationGrantType: authorization_code - redirectUri: http://localhost:8090/oauth2/code/kakao scope: - profile_nickname - profile_image @@ -29,14 +35,21 @@ spring: naver: clientId: '{네이버 client-id}' clientSecret: '{네이버 client-secret}' + redirectUri: "{baseUrl}/oauth2/callback/{registrationId}" clientAuthenticationMethod: post authorizationGrantType: authorization_code - redirectUri: http://localhost:8090/oauth2/code/naver scope: - nickname - email - profile_image clientName: Naver + github: + clientId: d3e47fc2ddd966fa4352 + clientSecret: 3bc0f6b8332f93076354c2a5bada2f5a05aea60d + redirectUri: "{baseUrl}/oauth2/callback/{registrationId}" + scope: + - user:email + - read:user provider: kakao: authorizationUri: https://kauth.kakao.com/oauth/authorize @@ -48,10 +61,14 @@ spring: tokenUri: https://nid.naver.com/oauth2.0/token userInfoUri: https://openapi.naver.com/v1/nid/me userNameAttribute: response + facebook: + authorizationUri: https://www.facebook.com/v3.0/dialog/oauth + tokenUri: https://graph.facebook.com/v3.0/oauth/access_token + userInfoUri: https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture.width(250).height(250) # Spring Security cors 설정 :: CorsConfiguration 설정 값 cors: - allowed-origins: 'http://localhost:3000' + allowed-origins: http://localhost:3000,http://localhost:8090 allowed-methods: GET,POST,PUT,DELETE,OPTIONS allowed-headers: '*' max-age: 3600 @@ -89,5 +106,11 @@ xit: # day refreshTokenExpiry: 7 oauth2: + # After successfully authenticating with the OAuth2 Provider, + # we'll be generating an auth token for the user and sending the token to the + # redirectUri mentioned by the client in the /oauth2/authorize request. + # We're not using cookies because they won't work well in mobile clients. authorizedRedirectUris: - - http://localhost:3000/oauth/redirect \ No newline at end of file + - http://localhost:3000/oauth2/redirect + - myandroidapp://oauth2/redirect + - myiosapp://oauth2/redirect \ No newline at end of file diff --git a/src/main/resources/templates/thymeleaf/sample/greeting.html b/src/main/resources/templates/thymeleaf/sample/greeting.html index de6f71b..be4f042 100644 --- a/src/main/resources/templates/thymeleaf/sample/greeting.html +++ b/src/main/resources/templates/thymeleaf/sample/greeting.html @@ -12,7 +12,7 @@ - +