현재 동의화면이 계속 반복됩니다

카카오계정 이 경로에서 동의하고 계속하기를 누르면 다시 카카오계정 이 화면으로 이동되서 동의하고 계속하기를 계속 나타냅니다.

@GetMapping("/auth/loginForm")
public String KakaoOauth(){

    return "logintest/kakaoLogin";
}


@PostMapping("/auth/kakao/callback")
public String kakaoCallback(@RequestParam String code) {
    OAuthLoginParams params = new KakaoLoginParams();
    ((KakaoLoginParams) params).setCode(code); // 이 부분을 추가하여 code 값을 설정

    String accessToken = kakaoApiClient.requestAccessToken(params);
    OAuthInfoResponse userInfo = kakaoApiClient.requestOauthInfo(accessToken);

    return "카카오 로그인 처리 완료";
}

security Config부분
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(customizer → customizer.disable()) // CSRF 보호 비활성화
.authorizeRequests(authorizeRequests → {
authorizeRequests
.requestMatchers(new AntPathRequestMatcher(“/auth/kakao/callback”)).permitAll()
.requestMatchers(“/public/", "/login/”).permitAll() // 특정 경로에 대한 접근 허용
.anyRequest().authenticated(); // 다른 모든 요청은 인증 필요
})
// .formLogin(formLogincustomizer->formLogincustomizer // 로그인 페이지 및 로그인 처리 URL 설정
// .loginPage(“/login”) // 로그인 페이지 경로
// .loginProcessingUrl(“/perform_login”) // 로그인 처리 URL 경로
// .defaultSuccessUrl(“/dashboard”) // 로그인 성공 후 이동할 페이지
// .permitAll()) // 로그인 페이지는 누구나 접근 가능
// .logout(formLogoutcustomizer->formLogoutcustomizer // 로그아웃 설정
// .logoutUrl(“/perform_logout”) // 로그아웃 처리 URL 경로
// .logoutSuccessUrl(“/login”) // 로그아웃 성공 후 이동할 페이지
// .permitAll()); // 로그아웃 페이지는 누구나 접근 가능
.oauth2Login(
oauth2 → oauth2
// .loginPage(“/login”)
.authorizationEndpoint(authorizationEndpoint → {
authorizationEndpoint
.baseUri(“/oauth2/authorization”);
})
// .successHandler(oAuth2SuccessHandler())
.userInfoEndpoint(userInfo → userInfo.userService(oAuth2UserCustomService)
));
return http.build();
}

// .formLogin(formLogincustomizer->formLogincustomizer // 로그인 페이지 및 로그인 처리 URL 설정
// .loginPage(“/login”) // 로그인 페이지 경로
// .loginProcessingUrl(“/perform_login”) // 로그인 처리 URL 경로
// .defaultSuccessUrl(“/dashboard”) // 로그인 성공 후 이동할 페이지
// .permitAll()) // 로그인 페이지는 누구나 접근 가능
// .logout(formLogoutcustomizer->formLogoutcustomizer // 로그아웃 설정
// .logoutUrl(“/perform_logout”) // 로그아웃 처리 URL 경로
// .logoutSuccessUrl(“/login”) // 로그아웃 성공 후 이동할 페이지
// .permitAll()); // 로그아웃 페이지는 누구나 접근 가능

@Bean
public ClientRegistrationRepository clientRegistrationRepository(){
    return new InMemoryClientRegistrationRepository(this.kakaoClientRegistration());
}


@Bean
public OAuth2AuthorizedClientRepository authorizedClientRepository(OAuth2AuthorizedClientService authorizedClientService){
    return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
}

private ClientRegistration kakaoClientRegistration(){
    ClientRegistration.Builder builder=ClientRegistration.withRegistrationId("kakao");
    builder.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE);
    builder.scope(new String[]{"profile_nickname","account_email"});
    builder.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST);
    builder.authorizationUri("https://kauth.kakao.com/oauth/authorize");
    builder.redirectUri("http://localhost:8080/auth/kakao/callback");
    builder.tokenUri("https://kauth.kakao.com/oauth/token");
    builder.userInfoUri("https://kapi.kakao.com/v2/user/me");
    builder.userNameAttributeName("id");
    builder.clientName("Kakao");
    builder.clientId("69445a05dee5a6928649b416c9df1964");
    builder.clientSecret("hxEg8JGhjQm7Np8bMd18vQWZhVOjcPm0");
    return builder.build();
}

SuccesHandler부분 설정입니다

public static final String REFRESH_TOKEN_COOKIE_NAME = "refresh_token";
public static final Duration REFRESH_TOKEN_DURATION = Duration.ofDays(14);
public static final Duration ACCESS_TOKEN_DURATION = Duration.ofDays(1);
public static final String REDIRECT_PATH = "auth/kakao/callback";

private final RefreshTokenRespository refreshTokenRepository;
private final MemberRepository memberRepository;
private final OAuth2AuthorizationRequestBasedOnCookieRepository authorizationRequestRepository;
private final UserService userService;
private final JwtTokenProvider jwtTokenProvider;
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();
    User user = userService.findByEmail((String)oAuth2User.getAttributes().get("email"));

    String subject = user.getMember().getEmail();

    Date refreshTokenExpiry = new Date(System.currentTimeMillis()+REFRESH_TOKEN_DURATION.toMillis());
    Date accessTokenExpiry = new Date(System.currentTimeMillis() + ACCESS_TOKEN_DURATION.toMillis());

    String refreshToken=jwtTokenProvider.generate(subject,refreshTokenExpiry);
    saveRefreshToken(user.getId(),refreshToken);

    String accessToken = jwtTokenProvider.generate(subject,accessTokenExpiry);
    String targetUrl = getTargetUrl(accessToken);
    getRedirectStrategy().sendRedirect(request,response,targetUrl);

}

private void saveRefreshToken(Long memberId,String newRefreshToken){
    Member member = memberRepository.findById(memberId).orElseThrow(()->new EntityNotFoundException("Member not found"));
    RefreshToken refreshToken=refreshTokenRepository.findByMember(member)
            .map(entity->entity.update(newRefreshToken))
            .orElseGet(() -> new RefreshToken(member, newRefreshToken));

    refreshTokenRepository.save(refreshToken);
}


//생성된 리프레시 토큰 쿠키에 저장
private void addRefreshTokneToCookie(HttpServletRequest request, HttpServletResponse response, String refreshToken){
    int cookieMaxAge = (int)REFRESH_TOKEN_DURATION.toSeconds();
    CookieUtil.deleteCookie(request,response,REFRESH_TOKEN_COOKIE_NAME);
    CookieUtil.addCookie(response,REFRESH_TOKEN_COOKIE_NAME,refreshToken,cookieMaxAge);
}

//인증 요청과 관련된 속성 삭제

// private void clearAuthenticationAttributes(HttpServletRequest request,HttpServletResponse response){
// super.clearAuthenticationAttributes(request);
// authorizationRequestRepository.removeAuthorizationRequestCookies(request,response);
//
// }

//리다이렉트할 url 생성
private String getTargetUrl(String token){
    return UriComponentsBuilder.fromUriString(REDIRECT_PATH)
            .queryParam("token",token)
            .build()
            .toUriString();
}

}
현재 yml 설정입니다.
spring:
datasource:
url: jdbc:mysql://localhost:3306/foodtest?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
#spring:

datasource:

url: jdbc:mysql://awt??/db???useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC

username: admin

password: admin1234

driver-class-name: com.mysql.cj.jdbc.Driver

jpa:
hibernate:
ddl-auto: update
# 프로젝트 시작시 create로 두시고 진행중엔 none나 validate로 해주세요
properties:
hibernate:
show_sql: true
format_sql: true
default_batch_fetch_size: 100
# 페이징을 100개씩 해줍니다 해당 설정이 없다면 나중에 여러개 저장되어있는 db정보를 쿼리 1개씩 날림
database-platform: org.hibernate.dialect.MySQLDialect

oauth:
kakao:
client-id: 69445a05dee5a6928649b416c9df1964
client-secret: hxEg8JGhjQm7Np8bMd18vQWZhVOjcPm0
redirect-uri: http://localhost:8080/auth/kakao/callback
oauth-url: https://kauth.kakao.com
api-url: https://kapi.kakao.com

logging:
level:
org.hibernate.SQL: debug
org.hibernate.type: trace
recipeImgLocation: c:/recipe/images

server:
servlet:
encoding:
charset: UTF-8

jwt:
secret_key:

동의화면이 계속되는 것은

동의 후, 리다이렉트 URI에서 액세스 토큰 발급하지 않고
개발하신 시스템에서 다시 로그인 하도록 리다이렉트 하기때문입니다.

아래 내용 참고하셔서 카카오 로그인만 단독 테스트 해보시면 좋을 것같습니다.

Spring에서 카카오 로그인 사용하기 - Spring Security 5, OAuth 2 - deprecated 대응 2023년 6월 27일

현재 아이디 값은 ID 1021973 입니다.
주신 내용으로 해 본 결과 Intellij콘솔에선 2024-01-25T19:44:26.343+09:00 INFO 15780 — [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet ‘dispatcherServlet’
2024-01-25T19:44:26.343+09:00 INFO 15780 — [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet ‘dispatcherServlet’
2024-01-25T19:44:26.344+09:00 INFO 15780 — [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
2024-01-25T19:44:26.356+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.session.DisableEncodeUrlFilter@27be1ff1, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@6c7ae08d, org.springframework.security.web.context.SecurityContextHolderFilter@345215df, org.springframework.security.web.header.HeaderWriterFilter@1fb8653, org.springframework.web.filter.CorsFilter@1c47455a, org.springframework.security.web.csrf.CsrfFilter@5640da24, org.springframework.security.web.authentication.logout.LogoutFilter@495892b3, org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@57ddcd97, org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter@2fec9c6f, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@4325670f, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@23dd45f9, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@51e48159, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@29c38709, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@74cb87e4, org.springframework.security.web.access.ExceptionTranslationFilter@5f0e4dd0, org.springframework.security.web.access.intercept.AuthorizationFilter@6b26a13d]] (1/1)
2024-01-25T19:44:26.356+09:00 DEBUG 15780 — [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Securing GET /oauth2/authorization/kakao?code=ROobqzbvsZ-V5QDM2uA7TFz-LzDv1ZZqbVdzCpFoOc7d3B-Zpf9PQy_oJGkKKclfAAABjUA4k2GIenTzhLqDRQ&state=vvCNUF50uMpxdcAmiPpmet4HH3t3dzhRHP-ICM4RiY8%3D
2024-01-25T19:44:26.357+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Invoking DisableEncodeUrlFilter (1/16)
2024-01-25T19:44:26.358+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Invoking WebAsyncManagerIntegrationFilter (2/16)
2024-01-25T19:44:26.359+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Invoking SecurityContextHolderFilter (3/16)
2024-01-25T19:44:26.360+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Invoking HeaderWriterFilter (4/16)
2024-01-25T19:44:26.361+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Invoking CorsFilter (5/16)
2024-01-25T19:44:26.361+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Invoking CsrfFilter (6/16)
2024-01-25T19:44:26.362+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.security.web.csrf.CsrfFilter : Did not protect against CSRF since request did not match CsrfNotRequired [TRACE, HEAD, GET, OPTIONS]
2024-01-25T19:44:26.362+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Invoking LogoutFilter (7/16)
2024-01-25T19:44:26.363+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.s.w.a.logout.LogoutFilter : Did not match request to Ant [pattern=‘/logout’, POST]
2024-01-25T19:44:26.363+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Invoking OAuth2AuthorizationRequestRedirectFilter (8/16)
2024-01-25T19:44:26.374+09:00 DEBUG 15780 — [nio-8080-exec-1] o.s.s.web.DefaultRedirectStrategy : Redirecting to 카카오계정
2024-01-25T19:44:26.374+09:00 TRACE 15780 — [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match request to [Is Secure]
2024-01-25T19:44:47.542+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.session.DisableEncodeUrlFilter@27be1ff1, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@6c7ae08d, org.springframework.security.web.context.SecurityContextHolderFilter@345215df, org.springframework.security.web.header.HeaderWriterFilter@1fb8653, org.springframework.web.filter.CorsFilter@1c47455a, org.springframework.security.web.csrf.CsrfFilter@5640da24, org.springframework.security.web.authentication.logout.LogoutFilter@495892b3, org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@57ddcd97, org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter@2fec9c6f, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@4325670f, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@23dd45f9, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@51e48159, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@29c38709, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@74cb87e4, org.springframework.security.web.access.ExceptionTranslationFilter@5f0e4dd0, org.springframework.security.web.access.intercept.AuthorizationFilter@6b26a13d]] (1/1)
2024-01-25T19:44:47.543+09:00 DEBUG 15780 — [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Securing GET /oauth2/authorization/kakao?code=VpL-HkbMwSvsNXVKHHQ0hlFuSJWJ9YEF7Z_Qd2aO730WD_x-fE9K3g7VScAKKclfAAABjUA45mG2W8wW6V7rJg&state=n4naIKCLwX6gO2LZ7gTSJl2uFQApL-ArBIQD5y7uRQs%3D
2024-01-25T19:44:47.543+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Invoking DisableEncodeUrlFilter (1/16)
2024-01-25T19:44:47.543+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Invoking WebAsyncManagerIntegrationFilter (2/16)
2024-01-25T19:44:47.543+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Invoking SecurityContextHolderFilter (3/16)
2024-01-25T19:44:47.543+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Invoking HeaderWriterFilter (4/16)
2024-01-25T19:44:47.543+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Invoking CorsFilter (5/16)
2024-01-25T19:44:47.543+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Invoking CsrfFilter (6/16)
2024-01-25T19:44:47.543+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.security.web.csrf.CsrfFilter : Did not protect against CSRF since request did not match CsrfNotRequired [TRACE, HEAD, GET, OPTIONS]
2024-01-25T19:44:47.543+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Invoking LogoutFilter (7/16)
2024-01-25T19:44:47.543+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.s.w.a.logout.LogoutFilter : Did not match request to Ant [pattern=‘/logout’, POST]
2024-01-25T19:44:47.543+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Invoking OAuth2AuthorizationRequestRedirectFilter (8/16)
2024-01-25T19:44:47.544+09:00 DEBUG 15780 — [nio-8080-exec-2] o.s.s.web.DefaultRedirectStrategy : Redirecting to 카카오계정
2024-01-25T19:44:47.544+09:00 TRACE 15780 — [nio-8080-exec-2] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match request to [Is Secure] 이렇게 찍히고
개발자 도구의 Query 확인 시 1. code:

VpL-HkbMwSvsNXVKHHQ0hlFuSJWJ9YEF7Z_Qd2aO730WD_x-fE9K3g7VScAKKclfAAABjUA45mG2W8wW6V7rJg

  1. state:

n4naIKCLwX6gO2LZ7gTSJl2uFQApL-ArBIQD5y7uRQs= 이런 식으로 들어오기는 하는데 postman으로 확인하면

405 Not Allowed

405 Not Allowed


nginx 이 에러가 뜨고 access token 값이 나오지 않습니다.