|
1 | 1 | package com.example.travelbag.domain.member.controller.api.auth.status; |
2 | 2 |
|
| 3 | +import org.springframework.beans.factory.annotation.Autowired; |
| 4 | +import org.springframework.http.HttpStatus; |
3 | 5 | import org.springframework.http.ResponseEntity; |
4 | 6 | import org.springframework.security.core.Authentication; |
| 7 | +import org.springframework.security.core.context.SecurityContextHolder; |
| 8 | +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; |
| 9 | +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; |
| 10 | +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; |
5 | 11 | import org.springframework.security.oauth2.core.user.OAuth2User; |
6 | 12 | import org.springframework.web.bind.annotation.*; |
| 13 | +import org.springframework.web.client.HttpStatusCodeException; |
7 | 14 | import org.springframework.web.client.RestTemplate; |
8 | | - |
| 15 | +import org.springframework.web.bind.annotation.GetMapping; |
| 16 | +import org.springframework.web.bind.annotation.RequestMapping; |
| 17 | +import org.springframework.web.bind.annotation.RestController; |
9 | 18 | import java.util.Map; |
| 19 | + |
| 20 | + |
10 | 21 | @RestController |
11 | 22 | @RequestMapping("/api/auth") |
12 | 23 | public class AuthController { |
@@ -52,30 +63,77 @@ public ResponseEntity<Map<String, Object>> getAuthStatus(Authentication authenti |
52 | 63 | } |
53 | 64 | } |
54 | 65 |
|
55 | | - // 새로운 로그아웃 API |
| 66 | + @GetMapping("/token") |
| 67 | + public ResponseEntity<Map<String, String>> getAccessToken(Authentication authentication, |
| 68 | + @Autowired OAuth2AuthorizedClientService authorizedClientService) { |
| 69 | + if (authentication == null) { |
| 70 | + return ResponseEntity.status(401).body(Map.of("error", "User not authenticated")); |
| 71 | + } |
| 72 | + |
| 73 | + OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication; |
| 74 | + String clientRegistrationId = oauthToken.getAuthorizedClientRegistrationId(); |
| 75 | + |
| 76 | + OAuth2AuthorizedClient authorizedClient = |
| 77 | + authorizedClientService.loadAuthorizedClient(clientRegistrationId, oauthToken.getName()); |
| 78 | + |
| 79 | + if (authorizedClient == null || authorizedClient.getAccessToken() == null) { |
| 80 | + return ResponseEntity.status(500).body(Map.of("error", "Access token not available")); |
| 81 | + } |
| 82 | + |
| 83 | + String kakaoAccessToken = authorizedClient.getAccessToken().getTokenValue(); |
| 84 | + return ResponseEntity.ok(Map.of("accessToken", kakaoAccessToken)); |
| 85 | + } |
| 86 | + |
56 | 87 | @PostMapping("/logout") |
57 | | - public ResponseEntity<Map<String, Object>> logout(@RequestHeader("Authorization") String accessToken) { |
| 88 | + public ResponseEntity<Map<String, Object>> logout(@RequestHeader("Authorization") String authorizationHeader) { |
| 89 | + if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) { |
| 90 | + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of( |
| 91 | + "error", "Authorization header is missing or invalid" |
| 92 | + )); |
| 93 | + } |
| 94 | + |
| 95 | + // Bearer 접두어 제거 후 Access Token 추출 |
| 96 | + String accessToken = authorizationHeader.replace("Bearer ", "").trim(); |
58 | 97 | String kakaoLogoutUrl = "https://kapi.kakao.com/v1/user/logout"; |
59 | 98 |
|
60 | 99 | try { |
61 | 100 | // 카카오 로그아웃 API 호출 |
62 | 101 | RestTemplate restTemplate = new RestTemplate(); |
63 | 102 | var headers = new org.springframework.http.HttpHeaders(); |
64 | 103 | headers.set("Authorization", "Bearer " + accessToken); |
| 104 | + |
65 | 105 | var request = new org.springframework.http.HttpEntity<>(headers); |
| 106 | + var response = restTemplate.postForEntity(kakaoLogoutUrl, request, String.class); |
66 | 107 |
|
67 | | - restTemplate.postForEntity(kakaoLogoutUrl, request, String.class); |
| 108 | + // 로그아웃 성공 여부 확인 |
| 109 | + if (response.getStatusCode().is2xxSuccessful()) { |
| 110 | + // Spring Security 세션 초기화 |
| 111 | + SecurityContextHolder.clearContext(); |
| 112 | + System.out.println("Kakao logout successful. Token: " + accessToken); |
68 | 113 |
|
69 | | - // 로그아웃 성공 응답 |
70 | | - return ResponseEntity.ok(Map.of( |
71 | | - "message", "Successfully logged out" |
| 114 | + return ResponseEntity.ok(Map.of( |
| 115 | + "message", "Successfully logged out" |
| 116 | + )); |
| 117 | + } else { |
| 118 | + System.out.println("Kakao logout failed with status: " + response.getStatusCode()); |
| 119 | + return ResponseEntity.status(response.getStatusCode()).body(Map.of( |
| 120 | + "error", "Kakao logout failed" |
| 121 | + )); |
| 122 | + } |
| 123 | + } catch (HttpStatusCodeException ex) { |
| 124 | + // 카카오 API에서 반환된 HTTP 상태 코드와 응답 메시지 처리 |
| 125 | + System.out.println("Error during Kakao logout. Status: " + ex.getStatusCode() + ", Response: " + ex.getResponseBodyAsString()); |
| 126 | + return ResponseEntity.status(ex.getStatusCode()).body(Map.of( |
| 127 | + "error", ex.getResponseBodyAsString() |
72 | 128 | )); |
73 | 129 | } catch (Exception e) { |
74 | | - System.out.println("Error in /api/auth/logout: " + e.getMessage()); |
| 130 | + // 일반 예외 처리 |
| 131 | + System.out.println("Unexpected error during Kakao logout: " + e.getMessage()); |
75 | 132 | e.printStackTrace(); |
76 | | - return ResponseEntity.status(500).body(Map.of( |
77 | | - "error", e.getMessage() |
| 133 | + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of( |
| 134 | + "error", "Unexpected error occurred" |
78 | 135 | )); |
79 | 136 | } |
80 | 137 | } |
| 138 | + |
81 | 139 | } |
0 commit comments