From 0fabcf17ea0ae4b5c916f6ffe31a984deccc0a22 Mon Sep 17 00:00:00 2001 From: itsme-shawn Date: Sat, 27 Jan 2024 13:18:33 +0900 Subject: [PATCH 1/3] =?UTF-8?q?wip:=20google=20login=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reddiserver/config/WebClientConfig.java | 18 +++++++ .../reddiserver/config/WebSecurityConfig.java | 5 -- .../controller/AuthController.java | 41 +++++++++++++--- .../auth/response/GoogleTokenResponseDto.java | 4 ++ .../security/oauth/GoogleOAuth.java | 49 +++++++++++++++++++ .../security/oauth/OAuthService.java | 22 +++++++++ 6 files changed, 127 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/example/reddiserver/config/WebClientConfig.java create mode 100644 src/main/java/com/example/reddiserver/dto/auth/response/GoogleTokenResponseDto.java create mode 100644 src/main/java/com/example/reddiserver/security/oauth/GoogleOAuth.java create mode 100644 src/main/java/com/example/reddiserver/security/oauth/OAuthService.java diff --git a/src/main/java/com/example/reddiserver/config/WebClientConfig.java b/src/main/java/com/example/reddiserver/config/WebClientConfig.java new file mode 100644 index 0000000..006af2d --- /dev/null +++ b/src/main/java/com/example/reddiserver/config/WebClientConfig.java @@ -0,0 +1,18 @@ +package com.example.reddiserver.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +public class WebClientConfig { + @Bean + public WebClient.Builder webClientBuilder() { + return WebClient.builder(); + } + + @Bean + public WebClient webClient(WebClient.Builder webClientBuilder) { + return webClientBuilder.build(); + } +} diff --git a/src/main/java/com/example/reddiserver/config/WebSecurityConfig.java b/src/main/java/com/example/reddiserver/config/WebSecurityConfig.java index 02397a8..ab69e0b 100644 --- a/src/main/java/com/example/reddiserver/config/WebSecurityConfig.java +++ b/src/main/java/com/example/reddiserver/config/WebSecurityConfig.java @@ -45,11 +45,6 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .exceptionHandling(authenticationManager -> authenticationManager .accessDeniedHandler(jwtAccessDeniedHandler) .authenticationEntryPoint(jwtAuthenticationEntryPoint)) - .oauth2Login(oauth2LoginConfigurer -> oauth2LoginConfigurer - .failureHandler(oAuthFailureHandler) - .successHandler(oAuthSuccessHandler) - .userInfoEndpoint() - .userService(customOAuth2UserService)) .authorizeHttpRequests((authorize) -> authorize .requestMatchers("/static/**", "/resources/**", "/css/**", "/js/**", "/images/**", "/**", "/swagger-ui/**", "/v3/api-docs/**").permitAll() .requestMatchers(HttpMethod.GET, "/**").permitAll() diff --git a/src/main/java/com/example/reddiserver/controller/AuthController.java b/src/main/java/com/example/reddiserver/controller/AuthController.java index b542e9b..480a955 100644 --- a/src/main/java/com/example/reddiserver/controller/AuthController.java +++ b/src/main/java/com/example/reddiserver/controller/AuthController.java @@ -4,19 +4,15 @@ import com.example.reddiserver.dto.auth.request.ReissueRequestDto; import com.example.reddiserver.dto.auth.response.UserInfoResponseDto; import com.example.reddiserver.dto.security.response.TokenDto; -import com.example.reddiserver.entity.Member; -import com.example.reddiserver.repository.MemberRepository; import com.example.reddiserver.security.jwt.TokenProvider; +import com.example.reddiserver.security.oauth.GoogleOAuth; +import com.example.reddiserver.security.oauth.OAuthService; import com.example.reddiserver.service.AuthService; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.util.HashMap; @@ -27,7 +23,38 @@ @RequestMapping("/api/auth") public class AuthController { private final AuthService authService; + private final OAuthService oAuthService; private final TokenProvider tokenProvider; + private final GoogleOAuth googleOAuth; + + + @Operation(summary = "구글 로그인 링크") + @GetMapping("/google-auth-url") + public Map getGoogleAuthUrl(@RequestParam(defaultValue = "http://localhost:3000") final String redirectUrl) throws Exception { + + Map urlMap = new HashMap<>(); + urlMap.put("url", googleOAuth.getGOOGLE_LOGIN_URL() + "?redirect_uri=" + redirectUrl + "/&response_type=code&client_id=" + googleOAuth.getCLIENT_ID() + "&scope=profile email"); + return urlMap; + } + + // code 와 redirectUrl 을 받아서 Google 로 부터 access token 을 발급 받고, 이를 이용해 회원가입 및 로그인을 진행 + @GetMapping("/google/login") + public ResponseEntity googleLogin(@RequestParam final String code, @RequestParam(defaultValue = "http://localhost:3000") final String redirectUrl) throws Exception { + oAuthService.login(code, redirectUrl); + + return null; + } + + // 임시엔드포인트 + // 쿼리스트링에 있는 code 값을 추출 + @GetMapping("/google/callback") + public ResponseEntity googleCallback(@RequestParam final String code) throws Exception { + + System.out.println("Received code: " + code); + + return ResponseEntity.ok("Received code: " + code); + } + @SecurityRequirement(name = "Authorization") // 인증 필요한 엔드포인트에 설정 @PostMapping("/reissue") diff --git a/src/main/java/com/example/reddiserver/dto/auth/response/GoogleTokenResponseDto.java b/src/main/java/com/example/reddiserver/dto/auth/response/GoogleTokenResponseDto.java new file mode 100644 index 0000000..ed656f0 --- /dev/null +++ b/src/main/java/com/example/reddiserver/dto/auth/response/GoogleTokenResponseDto.java @@ -0,0 +1,4 @@ +package com.example.reddiserver.dto.auth.response; + +public record GoogleTokenResponseDto(String access_token, Integer expires_in, String scope, String token_type, String id_token) { +} diff --git a/src/main/java/com/example/reddiserver/security/oauth/GoogleOAuth.java b/src/main/java/com/example/reddiserver/security/oauth/GoogleOAuth.java new file mode 100644 index 0000000..7a27d4b --- /dev/null +++ b/src/main/java/com/example/reddiserver/security/oauth/GoogleOAuth.java @@ -0,0 +1,49 @@ +package com.example.reddiserver.security.oauth; + +import com.example.reddiserver.dto.auth.response.GoogleTokenResponseDto; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.Map; + +@Component +@RequiredArgsConstructor +@Getter +public class GoogleOAuth { + + private final String GOOGLE_LOGIN_URL = "https://accounts.google.com/o/oauth2/v2/auth"; + private final String GOOGLE_TOKEN_REQUEST_URL = "https://oauth2.googleapis.com/token"; + private final String GOOGLE_USERINFO_REQUEST_Url = "https://www.googleapis.com/oauth2/v3/userinfo"; + + @Value("${spring.security.oauth2.client.registration.google.client-id}") + private String CLIENT_ID; + + @Value("${spring.security.oauth2.client.registration.google.client-secret}") + private String CLIENT_SECRET; + + private final WebClient webClient; + + public GoogleTokenResponseDto requestToken(String code, String redirectUri) { + Map params = Map.of( + "code", code, + "client_id", CLIENT_ID, + "client_secret", CLIENT_SECRET, + "redirect_uri", redirectUri, + "grant_type", "authorization_code" + ); + + GoogleTokenResponseDto response = webClient.post() + .uri(GOOGLE_TOKEN_REQUEST_URL) + .bodyValue(params) + .retrieve() + .bodyToMono(GoogleTokenResponseDto.class) + .block(); + + System.out.println("response = " + response); + + return response; + } +} diff --git a/src/main/java/com/example/reddiserver/security/oauth/OAuthService.java b/src/main/java/com/example/reddiserver/security/oauth/OAuthService.java new file mode 100644 index 0000000..7769cc8 --- /dev/null +++ b/src/main/java/com/example/reddiserver/security/oauth/OAuthService.java @@ -0,0 +1,22 @@ +package com.example.reddiserver.security.oauth; + +import com.example.reddiserver.dto.auth.response.GoogleTokenResponseDto; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class OAuthService { + + private final GoogleOAuth googleOAuth; + + @Transactional + public void login(String code, String redirectUri) { + GoogleTokenResponseDto googleToken = googleOAuth.requestToken(code, redirectUri); + System.out.println("googleToken = " + googleToken); + + + } +} From 40115be91e304137373379e4833e412f7ce47e7f Mon Sep 17 00:00:00 2001 From: itsme-shawn Date: Tue, 30 Jan 2024 09:18:41 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20google=20login=20rest=20api=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filter/CustomAuthenticationDetails.java | 21 +++ .../auth/filter/JwtRequestFilter.java | 116 +++++++++++++ .../{security => auth}/oauth/GoogleOAuth.java | 33 +++- .../oauth/provider/GoogleOAuth2User.java | 2 +- .../oauth/provider/OAuth2UserInfo.java | 2 +- .../auth/service/JwtTokenProvider.java | 115 +++++++++++++ .../auth/service/OAuthService.java | 90 ++++++++++ .../reddiserver/config/WebSecurityConfig.java | 26 +-- .../controller/AuthController.java | 64 +++---- .../controller/HomeController.java | 21 +++ .../auth/request/GoogleLoginRequestDto.java | 10 ++ .../auth/response/GoogleTokenResponseDto.java | 14 +- .../auth/response/GoogleUserResponseDto.java | 19 +++ .../dto/auth/response/LoginResponseDto.java | 11 ++ .../auth/response/UserInfoResponseDto.java | 22 --- .../dto/member/MemberInfoResponseDto.java | 23 +++ .../reddiserver/entity/RefreshToken.java | 18 +- .../security/jwt/JwtAuthenticationFilter.java | 34 ---- .../jwt/JwtExceptionHandlerFilter.java | 33 ---- .../security/jwt/TokenProvider.java | 159 ------------------ .../jwt/exception/JwtAccessDeniedHandler.java | 21 --- .../JwtAuthenticationEntryPoint.java | 22 --- .../security/oauth/OAuth2UserInfoFactory.java | 16 -- .../security/oauth/OAuthService.java | 22 --- .../oauth/PrincipalOAuth2Details.java | 49 ------ .../oauth/PrincipalOAuth2DetailsService.java | 52 ------ .../oauth/handler/OAuthFailureHandler.java | 22 --- .../oauth/handler/OAuthSuccessHandler.java | 42 ----- .../reddiserver/service/AuthService.java | 61 ------- .../reddiserver/service/MemberService.java | 18 ++ src/main/resources/application.yml | 5 +- 31 files changed, 522 insertions(+), 641 deletions(-) create mode 100644 src/main/java/com/example/reddiserver/auth/filter/CustomAuthenticationDetails.java create mode 100644 src/main/java/com/example/reddiserver/auth/filter/JwtRequestFilter.java rename src/main/java/com/example/reddiserver/{security => auth}/oauth/GoogleOAuth.java (53%) rename src/main/java/com/example/reddiserver/{security => auth}/oauth/provider/GoogleOAuth2User.java (92%) rename src/main/java/com/example/reddiserver/{security => auth}/oauth/provider/OAuth2UserInfo.java (89%) create mode 100644 src/main/java/com/example/reddiserver/auth/service/JwtTokenProvider.java create mode 100644 src/main/java/com/example/reddiserver/auth/service/OAuthService.java create mode 100644 src/main/java/com/example/reddiserver/controller/HomeController.java create mode 100644 src/main/java/com/example/reddiserver/dto/auth/request/GoogleLoginRequestDto.java create mode 100644 src/main/java/com/example/reddiserver/dto/auth/response/GoogleUserResponseDto.java create mode 100644 src/main/java/com/example/reddiserver/dto/auth/response/LoginResponseDto.java delete mode 100644 src/main/java/com/example/reddiserver/dto/auth/response/UserInfoResponseDto.java create mode 100644 src/main/java/com/example/reddiserver/dto/member/MemberInfoResponseDto.java delete mode 100644 src/main/java/com/example/reddiserver/security/jwt/JwtAuthenticationFilter.java delete mode 100644 src/main/java/com/example/reddiserver/security/jwt/JwtExceptionHandlerFilter.java delete mode 100644 src/main/java/com/example/reddiserver/security/jwt/TokenProvider.java delete mode 100644 src/main/java/com/example/reddiserver/security/jwt/exception/JwtAccessDeniedHandler.java delete mode 100644 src/main/java/com/example/reddiserver/security/jwt/exception/JwtAuthenticationEntryPoint.java delete mode 100644 src/main/java/com/example/reddiserver/security/oauth/OAuth2UserInfoFactory.java delete mode 100644 src/main/java/com/example/reddiserver/security/oauth/OAuthService.java delete mode 100644 src/main/java/com/example/reddiserver/security/oauth/PrincipalOAuth2Details.java delete mode 100644 src/main/java/com/example/reddiserver/security/oauth/PrincipalOAuth2DetailsService.java delete mode 100644 src/main/java/com/example/reddiserver/security/oauth/handler/OAuthFailureHandler.java delete mode 100644 src/main/java/com/example/reddiserver/security/oauth/handler/OAuthSuccessHandler.java delete mode 100644 src/main/java/com/example/reddiserver/service/AuthService.java create mode 100644 src/main/java/com/example/reddiserver/service/MemberService.java diff --git a/src/main/java/com/example/reddiserver/auth/filter/CustomAuthenticationDetails.java b/src/main/java/com/example/reddiserver/auth/filter/CustomAuthenticationDetails.java new file mode 100644 index 0000000..47cf006 --- /dev/null +++ b/src/main/java/com/example/reddiserver/auth/filter/CustomAuthenticationDetails.java @@ -0,0 +1,21 @@ +package com.example.reddiserver.auth.filter; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.Getter; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetails; + +@Getter +public class CustomAuthenticationDetails extends WebAuthenticationDetails { + + private final Long userId; + + public CustomAuthenticationDetails(Long userId, HttpServletRequest request) { + super(request); + this.userId = userId; + } + + + +} \ No newline at end of file diff --git a/src/main/java/com/example/reddiserver/auth/filter/JwtRequestFilter.java b/src/main/java/com/example/reddiserver/auth/filter/JwtRequestFilter.java new file mode 100644 index 0000000..25f4e9e --- /dev/null +++ b/src/main/java/com/example/reddiserver/auth/filter/JwtRequestFilter.java @@ -0,0 +1,116 @@ +package com.example.reddiserver.auth.filter; + +import com.example.reddiserver.auth.service.JwtTokenProvider; +import com.example.reddiserver.entity.enums.Authority; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.MalformedJwtException; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.h2.engine.Role; +import org.springframework.http.MediaType; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Component +@Slf4j +@RequiredArgsConstructor +public class JwtRequestFilter extends OncePerRequestFilter { + + private final JwtTokenProvider jwtTokenProvider; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + String accessTokenHeader = request.getHeader("Authorization"); + String refreshTokenHeader = request.getHeader("RefreshToken"); + + // 헤더에 토큰 안 담기는 경우는 인가 안하고 그대로 필터 종료 + if (accessTokenHeader == null) { + filterChain.doFilter(request, response); + return; + } + + // 헤더에 토큰 담기는 경우 + if (accessTokenHeader.startsWith("Bearer ")) { + String token = accessTokenHeader.substring(7); + + try { + // 토큰이 유효한 경우에 수행할 작업 + jwtTokenProvider.validateToken(token); + + Map payload = jwtTokenProvider.getPayload(token); + + Long userId = Long.valueOf(payload.get("userId")); + + System.out.println("필터 userId = " + userId); + + + // 권한 부여 + log.info("=====권한 부여====="); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userId, null, List.of(new SimpleGrantedAuthority(Authority.ROLE_USER.name()))); + + + // Detail을 넣어줌 + // userId와 uuid를 추가로 넣어줌 + authenticationToken.setDetails(new CustomAuthenticationDetails(userId, request)); + + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + + log.info("[+] Token in SecurityContextHolder"); + filterChain.doFilter(request, response); + + } catch (ExpiredJwtException e) { + // 토큰이 만료된 경우에 수행할 작업 + // refresh 토큰이 있으면 검증하고 access 토큰 재발급 + log.error("=====만료된 토큰입니다=====", e); + throw e; + +// errorResponse(response, "jwt필터 - 만료된 토큰입니다", HttpServletResponse.SC_UNAUTHORIZED); + + } catch (MalformedJwtException e) { + // 토큰 형식이 잘못된 경우에 수행할 작업 + log.error("=====잘못된 형식의 토큰=====", e); + throw e; +// errorResponse(response, "jwt필터 - 잘못된 형식의 토큰입니다", HttpServletResponse.SC_BAD_REQUEST); + + } catch (JwtException e) { + // 기타 예외 처리 + log.error("=====유효하지 않은 토큰입니다=====", e); + throw e; +// errorResponse(response, "jwt필터 - 유효하지 않은 토큰입니다", HttpServletResponse.SC_FORBIDDEN); + } + + + } + + } + + + // private boolean userHasPermission(String userId) { + // // 여기에서 해당 사용자의 권한을 확인하는 로직 구현 + // // userId를 기반으로 데이터베이스 등에서 해당 사용자의 권한 정보를 가져와서 확인 + // // 권한이 있다면 true를 반환, 권한이 없다면 false를 반환 + // return true; // 또는 false + // } + //} + + + private void errorResponse(HttpServletResponse response, String errMsg, int httpStatus) throws IOException { + response.setStatus(httpStatus); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding("UTF-8"); + response.getWriter().write("{\"error\": \"" + errMsg + "\"}"); + } +} diff --git a/src/main/java/com/example/reddiserver/security/oauth/GoogleOAuth.java b/src/main/java/com/example/reddiserver/auth/oauth/GoogleOAuth.java similarity index 53% rename from src/main/java/com/example/reddiserver/security/oauth/GoogleOAuth.java rename to src/main/java/com/example/reddiserver/auth/oauth/GoogleOAuth.java index 7a27d4b..daa8f0e 100644 --- a/src/main/java/com/example/reddiserver/security/oauth/GoogleOAuth.java +++ b/src/main/java/com/example/reddiserver/auth/oauth/GoogleOAuth.java @@ -1,9 +1,11 @@ -package com.example.reddiserver.security.oauth; +package com.example.reddiserver.auth.oauth; import com.example.reddiserver.dto.auth.response.GoogleTokenResponseDto; +import com.example.reddiserver.dto.auth.response.GoogleUserResponseDto; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; @@ -16,7 +18,10 @@ public class GoogleOAuth { private final String GOOGLE_LOGIN_URL = "https://accounts.google.com/o/oauth2/v2/auth"; private final String GOOGLE_TOKEN_REQUEST_URL = "https://oauth2.googleapis.com/token"; - private final String GOOGLE_USERINFO_REQUEST_Url = "https://www.googleapis.com/oauth2/v3/userinfo"; + private final String GOOGLE_USERINFO_REQUEST_URL = "https://www.googleapis.com/oauth2/v3/userinfo"; + + @Value("${spring.security.oauth2.client.registration.google.redirectUri}") + private String REDIRECT_URI; @Value("${spring.security.oauth2.client.registration.google.client-id}") private String CLIENT_ID; @@ -26,24 +31,38 @@ public class GoogleOAuth { private final WebClient webClient; - public GoogleTokenResponseDto requestToken(String code, String redirectUri) { + public GoogleTokenResponseDto requestToken(String code) { Map params = Map.of( "code", code, "client_id", CLIENT_ID, "client_secret", CLIENT_SECRET, - "redirect_uri", redirectUri, + "redirect_uri", REDIRECT_URI, "grant_type", "authorization_code" ); - GoogleTokenResponseDto response = webClient.post() + return webClient.post() .uri(GOOGLE_TOKEN_REQUEST_URL) .bodyValue(params) .retrieve() .bodyToMono(GoogleTokenResponseDto.class) .block(); + } + + + public GoogleUserResponseDto requestUserInfo(GoogleTokenResponseDto googleToken) { + + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization", "Bearer " + googleToken.getAccess_token()); + + GoogleUserResponseDto googleUserResponse = webClient.get() + .uri(GOOGLE_USERINFO_REQUEST_URL) + .headers(httpHeaders -> httpHeaders.setBearerAuth(googleToken.getAccess_token())) + .retrieve() + .bodyToMono(GoogleUserResponseDto.class) + .block(); - System.out.println("response = " + response); + System.out.println("requestUserInfo response = " + googleUserResponse); - return response; + return googleUserResponse; } } diff --git a/src/main/java/com/example/reddiserver/security/oauth/provider/GoogleOAuth2User.java b/src/main/java/com/example/reddiserver/auth/oauth/provider/GoogleOAuth2User.java similarity index 92% rename from src/main/java/com/example/reddiserver/security/oauth/provider/GoogleOAuth2User.java rename to src/main/java/com/example/reddiserver/auth/oauth/provider/GoogleOAuth2User.java index 0b7423a..b05b119 100644 --- a/src/main/java/com/example/reddiserver/security/oauth/provider/GoogleOAuth2User.java +++ b/src/main/java/com/example/reddiserver/auth/oauth/provider/GoogleOAuth2User.java @@ -1,4 +1,4 @@ -package com.example.reddiserver.security.oauth.provider; +package com.example.reddiserver.auth.oauth.provider; import com.example.reddiserver.entity.enums.ProviderType; diff --git a/src/main/java/com/example/reddiserver/security/oauth/provider/OAuth2UserInfo.java b/src/main/java/com/example/reddiserver/auth/oauth/provider/OAuth2UserInfo.java similarity index 89% rename from src/main/java/com/example/reddiserver/security/oauth/provider/OAuth2UserInfo.java rename to src/main/java/com/example/reddiserver/auth/oauth/provider/OAuth2UserInfo.java index 92e1089..05c92f1 100644 --- a/src/main/java/com/example/reddiserver/security/oauth/provider/OAuth2UserInfo.java +++ b/src/main/java/com/example/reddiserver/auth/oauth/provider/OAuth2UserInfo.java @@ -1,4 +1,4 @@ -package com.example.reddiserver.security.oauth.provider; +package com.example.reddiserver.auth.oauth.provider; import com.example.reddiserver.entity.enums.ProviderType; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/example/reddiserver/auth/service/JwtTokenProvider.java b/src/main/java/com/example/reddiserver/auth/service/JwtTokenProvider.java new file mode 100644 index 0000000..6bfe34e --- /dev/null +++ b/src/main/java/com/example/reddiserver/auth/service/JwtTokenProvider.java @@ -0,0 +1,115 @@ +package com.example.reddiserver.auth.service; + +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Keys; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.security.Key; +import java.util.Base64; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Component +@Slf4j +@RequiredArgsConstructor +public class JwtTokenProvider implements InitializingBean { + + @Value("${spring.jwt.secret}") + private String JWT_SECRET; + + private Key key; + + private final Long accessTokenExpiredTime = 1000 * 60L * 60L * 12L; // 유효시간 12시간 (임시 변경) + private final Long refreshTokenExpiredTime = 1000 * 60L * 60L * 24L * 14L; // 유효시간 14일 + + private final Long shortAccessTokenExpiredTime = 1000 * 60L * 5; // 유효시간 5분 + + @Override + public void afterPropertiesSet() throws Exception { + Base64.Decoder decoders = Base64.getDecoder(); + byte[] keyBytes = decoders.decode(JWT_SECRET); + this.key = Keys.hmacShaKeyFor(keyBytes); + } + + public String createAccessToken(Map payload) { + return createJwtToken(payload, shortAccessTokenExpiredTime); + } + + public String createRefreshToken(Map payload) { + return createJwtToken(payload, refreshTokenExpiredTime); + } + + public String createJwtToken(Map payload, long expireLength) { + Date now = new Date(); + Date validity = new Date(now.getTime() + expireLength); + + try { + return Jwts.builder() + .setClaims(payload) + .setIssuedAt(now) + .setExpiration(validity) + .signWith(key, SignatureAlgorithm.HS512) + .compact(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + + public Map getPayload(String token) { + try { + Claims claims = Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody(); + + // 원하는 클레임 값 추출하여 Map으로 저장 + Map payload = new HashMap<>(); + payload.put("userId", claims.get("userId", String.class)); + + return payload; + + } catch (JwtException e) { + System.err.println("Error Type: " + e.getClass().getName()); + System.err.println("Error Message: " + e.getMessage()); + throw new JwtException("유효하지 않은 토큰 입니다"); + } + } + + public void validateToken(String token) throws JwtException { + try { + Jws claimsJws = Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token); + + Date expiration = claimsJws.getBody().getExpiration(); + Date now = new Date(); + + if (expiration.before(now)) { + throw new ExpiredJwtException(null, null, "Token expired"); + } + } catch (ExpiredJwtException e) { + // 토큰이 만료된 경우 처리 + log.error("===Token expired: {}===", e.getMessage()); + throw e; + } catch (MalformedJwtException e) { + // 토큰 형식이 잘못된 경우 처리 + log.error("====Malformed token: {}===", e.getMessage()); + throw e; + } catch (JwtException | IllegalArgumentException e) { + // 기타 예외 처리 + log.error("===Invalid token: {}===", e.getMessage()); + throw e; + } + } + + + +} diff --git a/src/main/java/com/example/reddiserver/auth/service/OAuthService.java b/src/main/java/com/example/reddiserver/auth/service/OAuthService.java new file mode 100644 index 0000000..53b8065 --- /dev/null +++ b/src/main/java/com/example/reddiserver/auth/service/OAuthService.java @@ -0,0 +1,90 @@ +package com.example.reddiserver.auth.service; + +import com.example.reddiserver.auth.filter.CustomAuthenticationDetails; +import com.example.reddiserver.auth.oauth.GoogleOAuth; +import com.example.reddiserver.dto.auth.response.GoogleTokenResponseDto; +import com.example.reddiserver.dto.auth.response.GoogleUserResponseDto; +import com.example.reddiserver.dto.auth.response.LoginResponseDto; +import com.example.reddiserver.entity.Member; +import com.example.reddiserver.entity.RefreshToken; +import com.example.reddiserver.repository.MemberRepository; +import com.example.reddiserver.repository.RefreshTokenRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.Map; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class OAuthService { + + private final GoogleOAuth googleOAuth; + private final MemberRepository memberRepository; + private final RefreshTokenRepository refreshTokenRepository; + private final JwtTokenProvider jwtTokenProvider; + + @Transactional + public LoginResponseDto login(String code) { + GoogleTokenResponseDto googleToken = googleOAuth.requestToken(code); + System.out.println("googleToken = " + googleToken); + + // 구글토큰으로 구글 유저 정보 조회 + + GoogleUserResponseDto googleUserResponse = googleOAuth.requestUserInfo(googleToken); + + String providerId = googleUserResponse.getSub(); + String name = googleUserResponse.getName(); + String email = googleUserResponse.getEmail(); + String profileImageUrl = googleUserResponse.getPicture(); + + // providerId로 DB 조회 + // DB에 없으면 회원가입 + Member member = memberRepository.findByProviderId(providerId) + .orElse(null); + + if (member == null) { + member = Member.builder() + .providerId(providerId) + .name(name) + .email(email) + .profileImageUrl(profileImageUrl) + .build(); + memberRepository.save(member); + } + + // accessToken, refreshToken 발급 + + Map payload = new HashMap<>(); + payload.put("userId", String.valueOf(member.getId())); + + String accessToken = jwtTokenProvider.createAccessToken(payload); + String refreshToken = jwtTokenProvider.createRefreshToken(payload); + + // redis에 저장 + RefreshToken refreshTokenEntity = new RefreshToken(); + refreshTokenEntity.setUserId(member.getId()); + refreshTokenEntity.setRefreshToken(refreshToken); + + refreshTokenRepository.save(refreshTokenEntity); + + return LoginResponseDto.builder() + .accessToken(accessToken) + .refreshToken(refreshToken) + .build(); + } + + public Long getUserId() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null) { + CustomAuthenticationDetails customDetails = (CustomAuthenticationDetails) authentication.getDetails(); + return customDetails.getUserId(); + } + + return null; // 인증 정보가 없거나 CustomAuthenticationDetails를 사용하지 않는 경우 + } +} diff --git a/src/main/java/com/example/reddiserver/config/WebSecurityConfig.java b/src/main/java/com/example/reddiserver/config/WebSecurityConfig.java index ab69e0b..d2d1149 100644 --- a/src/main/java/com/example/reddiserver/config/WebSecurityConfig.java +++ b/src/main/java/com/example/reddiserver/config/WebSecurityConfig.java @@ -1,18 +1,12 @@ package com.example.reddiserver.config; -import com.example.reddiserver.security.jwt.JwtAuthenticationFilter; -import com.example.reddiserver.security.jwt.JwtExceptionHandlerFilter; -import com.example.reddiserver.security.jwt.exception.JwtAccessDeniedHandler; -import com.example.reddiserver.security.jwt.exception.JwtAuthenticationEntryPoint; -import com.example.reddiserver.security.oauth.handler.OAuthFailureHandler; -import com.example.reddiserver.security.oauth.handler.OAuthSuccessHandler; -import com.example.reddiserver.security.oauth.PrincipalOAuth2DetailsService; +import com.example.reddiserver.auth.filter.JwtRequestFilter; +import com.example.reddiserver.auth.service.JwtTokenProvider; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; 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.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; @@ -23,14 +17,8 @@ @Configuration @RequiredArgsConstructor public class WebSecurityConfig { - private final JwtExceptionHandlerFilter jwtExceptionHandlerFilter; - private final JwtAuthenticationFilter jwtAuthenticationFilter; private final CorsConfigurationSource corsConfigurationSource; - private final JwtAccessDeniedHandler jwtAccessDeniedHandler; - private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; - private final PrincipalOAuth2DetailsService customOAuth2UserService; - private final OAuthSuccessHandler oAuthSuccessHandler; - private final OAuthFailureHandler oAuthFailureHandler; + private final JwtTokenProvider jwtTokenProvider; @Bean @@ -42,9 +30,6 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .httpBasic(httpBasic -> httpBasic.disable()) .formLogin(formLogin -> formLogin.disable()) - .exceptionHandling(authenticationManager -> authenticationManager - .accessDeniedHandler(jwtAccessDeniedHandler) - .authenticationEntryPoint(jwtAuthenticationEntryPoint)) .authorizeHttpRequests((authorize) -> authorize .requestMatchers("/static/**", "/resources/**", "/css/**", "/js/**", "/images/**", "/**", "/swagger-ui/**", "/v3/api-docs/**").permitAll() .requestMatchers(HttpMethod.GET, "/**").permitAll() @@ -53,8 +38,9 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .anyRequest().authenticated() ); - http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); - http.addFilterBefore(jwtExceptionHandlerFilter, JwtAuthenticationFilter.class); + http.addFilterBefore(new JwtRequestFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class); + + return http.build(); } diff --git a/src/main/java/com/example/reddiserver/controller/AuthController.java b/src/main/java/com/example/reddiserver/controller/AuthController.java index 480a955..e5f9ed0 100644 --- a/src/main/java/com/example/reddiserver/controller/AuthController.java +++ b/src/main/java/com/example/reddiserver/controller/AuthController.java @@ -1,18 +1,17 @@ package com.example.reddiserver.controller; +import com.example.reddiserver.auth.filter.CustomAuthenticationDetails; import com.example.reddiserver.common.ApiResponse; -import com.example.reddiserver.dto.auth.request.ReissueRequestDto; -import com.example.reddiserver.dto.auth.response.UserInfoResponseDto; -import com.example.reddiserver.dto.security.response.TokenDto; -import com.example.reddiserver.security.jwt.TokenProvider; -import com.example.reddiserver.security.oauth.GoogleOAuth; -import com.example.reddiserver.security.oauth.OAuthService; -import com.example.reddiserver.service.AuthService; +import com.example.reddiserver.dto.auth.request.GoogleLoginRequestDto; +import com.example.reddiserver.dto.auth.response.LoginResponseDto; +import com.example.reddiserver.dto.member.MemberInfoResponseDto; +import com.example.reddiserver.auth.oauth.GoogleOAuth; +import com.example.reddiserver.auth.service.OAuthService; +import com.example.reddiserver.service.MemberService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.HashMap; @@ -22,61 +21,48 @@ @RequiredArgsConstructor @RequestMapping("/api/auth") public class AuthController { - private final AuthService authService; private final OAuthService oAuthService; - private final TokenProvider tokenProvider; private final GoogleOAuth googleOAuth; + private final MemberService memberService; @Operation(summary = "구글 로그인 링크") @GetMapping("/google-auth-url") - public Map getGoogleAuthUrl(@RequestParam(defaultValue = "http://localhost:3000") final String redirectUrl) throws Exception { + public Map getGoogleAuthUrl() throws Exception { Map urlMap = new HashMap<>(); - urlMap.put("url", googleOAuth.getGOOGLE_LOGIN_URL() + "?redirect_uri=" + redirectUrl + "/&response_type=code&client_id=" + googleOAuth.getCLIENT_ID() + "&scope=profile email"); + urlMap.put("url", googleOAuth.getGOOGLE_LOGIN_URL() + "?redirect_uri=" + googleOAuth.getREDIRECT_URI() + "&response_type=code&client_id=" + googleOAuth.getCLIENT_ID() + "&scope=profile email"); return urlMap; } - // code 와 redirectUrl 을 받아서 Google 로 부터 access token 을 발급 받고, 이를 이용해 회원가입 및 로그인을 진행 - @GetMapping("/google/login") - public ResponseEntity googleLogin(@RequestParam final String code, @RequestParam(defaultValue = "http://localhost:3000") final String redirectUrl) throws Exception { - oAuthService.login(code, redirectUrl); + // code 를 받아서 Google 로 부터 access token 을 발급 받고, 이를 이용해 회원가입 및 로그인을 진행 + @PostMapping("/google/login") + public ApiResponse googleLogin(@RequestBody GoogleLoginRequestDto googleLoginRequestDto) throws Exception { + String code = googleLoginRequestDto.getCode(); + LoginResponseDto loginResponse = oAuthService.login(code); - return null; + return ApiResponse.successResponse(loginResponse); } - // 임시엔드포인트 - // 쿼리스트링에 있는 code 값을 추출 - @GetMapping("/google/callback") - public ResponseEntity googleCallback(@RequestParam final String code) throws Exception { - System.out.println("Received code: " + code); - return ResponseEntity.ok("Received code: " + code); - } - - @SecurityRequirement(name = "Authorization") // 인증 필요한 엔드포인트에 설정 - @PostMapping("/reissue") - public ApiResponse reissue(@RequestBody ReissueRequestDto reissueRequestDto) { - return ApiResponse.successResponse(authService.reissue(reissueRequestDto), "Access Token 재발급 성공"); - } +// @SecurityRequirement(name = "Authorization") // 인증 필요한 엔드포인트에 설정 +// @PostMapping("/reissue") +// public ApiResponse reissue(@RequestBody ReissueRequestDto reissueRequestDto) { +// return ApiResponse.successResponse(authService.reissue(reissueRequestDto), "Access Token 재발급 성공"); +// } @SecurityRequirement(name = "Authorization") // 인증 필요한 엔드포인트에 설정 @GetMapping("/info") public ApiResponse getUserInfo(HttpServletRequest request) { // Extract Access Token from the request - String accessToken = tokenProvider.resolveToken(request); - - Map userInfo = authService.getUserInfo(accessToken); + Long userId = oAuthService.getUserId(); - if (userInfo != null) { - UserInfoResponseDto userInfoResponseDto = UserInfoResponseDto.from(Long.valueOf(userInfo.get("userId").toString()), - userInfo.get("username").toString(), - userInfo.get("email").toString(), - userInfo.get("profileImageUrl").toString()); + MemberInfoResponseDto memberInfo = memberService.getMemberInfo(userId); - return ApiResponse.successResponse(userInfoResponseDto); + if (memberInfo != null) { + return ApiResponse.successResponse(memberInfo); } return ApiResponse.errorResponse("유효하지 않은 Access Token 입니다."); } diff --git a/src/main/java/com/example/reddiserver/controller/HomeController.java b/src/main/java/com/example/reddiserver/controller/HomeController.java new file mode 100644 index 0000000..d619b0d --- /dev/null +++ b/src/main/java/com/example/reddiserver/controller/HomeController.java @@ -0,0 +1,21 @@ +package com.example.reddiserver.controller; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/") +public class HomeController { + + // 임시 리다이렉션 엔드포인트 + @GetMapping("/auth/google/callback") + public String home(@RequestParam("code") String code) { + return code; + } + +} diff --git a/src/main/java/com/example/reddiserver/dto/auth/request/GoogleLoginRequestDto.java b/src/main/java/com/example/reddiserver/dto/auth/request/GoogleLoginRequestDto.java new file mode 100644 index 0000000..46a6bec --- /dev/null +++ b/src/main/java/com/example/reddiserver/dto/auth/request/GoogleLoginRequestDto.java @@ -0,0 +1,10 @@ +package com.example.reddiserver.dto.auth.request; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class GoogleLoginRequestDto { + private String code; +} diff --git a/src/main/java/com/example/reddiserver/dto/auth/response/GoogleTokenResponseDto.java b/src/main/java/com/example/reddiserver/dto/auth/response/GoogleTokenResponseDto.java index ed656f0..8d22877 100644 --- a/src/main/java/com/example/reddiserver/dto/auth/response/GoogleTokenResponseDto.java +++ b/src/main/java/com/example/reddiserver/dto/auth/response/GoogleTokenResponseDto.java @@ -1,4 +1,16 @@ package com.example.reddiserver.dto.auth.response; -public record GoogleTokenResponseDto(String access_token, Integer expires_in, String scope, String token_type, String id_token) { +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +public class GoogleTokenResponseDto { + public String access_token; + public Integer expires_in; + public String scope; + public String token_type; + public String id_token; } diff --git a/src/main/java/com/example/reddiserver/dto/auth/response/GoogleUserResponseDto.java b/src/main/java/com/example/reddiserver/dto/auth/response/GoogleUserResponseDto.java new file mode 100644 index 0000000..4521fc6 --- /dev/null +++ b/src/main/java/com/example/reddiserver/dto/auth/response/GoogleUserResponseDto.java @@ -0,0 +1,19 @@ +package com.example.reddiserver.dto.auth.response; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +public class GoogleUserResponseDto { + private String sub; + private String name; + private String given_name; + private String family_name; + private String picture; + private String email; + private boolean email_verified; + private String locale; +} diff --git a/src/main/java/com/example/reddiserver/dto/auth/response/LoginResponseDto.java b/src/main/java/com/example/reddiserver/dto/auth/response/LoginResponseDto.java new file mode 100644 index 0000000..69a2b2f --- /dev/null +++ b/src/main/java/com/example/reddiserver/dto/auth/response/LoginResponseDto.java @@ -0,0 +1,11 @@ +package com.example.reddiserver.dto.auth.response; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class LoginResponseDto { + private String accessToken; + private String refreshToken; +} diff --git a/src/main/java/com/example/reddiserver/dto/auth/response/UserInfoResponseDto.java b/src/main/java/com/example/reddiserver/dto/auth/response/UserInfoResponseDto.java deleted file mode 100644 index fffd80a..0000000 --- a/src/main/java/com/example/reddiserver/dto/auth/response/UserInfoResponseDto.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.reddiserver.dto.auth.response; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class UserInfoResponseDto { - private Long userId; - private String name; - private String email; - private String profileImageUrl; - - public static UserInfoResponseDto from(Long userId, String name, String email, String profileImageUrl) { - UserInfoResponseDto userInfoResponseDto = new UserInfoResponseDto(); - userInfoResponseDto.setUserId(userId); - userInfoResponseDto.setName(name); - userInfoResponseDto.setEmail(email); - userInfoResponseDto.setProfileImageUrl(profileImageUrl); - return userInfoResponseDto; - } -} diff --git a/src/main/java/com/example/reddiserver/dto/member/MemberInfoResponseDto.java b/src/main/java/com/example/reddiserver/dto/member/MemberInfoResponseDto.java new file mode 100644 index 0000000..bc6525f --- /dev/null +++ b/src/main/java/com/example/reddiserver/dto/member/MemberInfoResponseDto.java @@ -0,0 +1,23 @@ +package com.example.reddiserver.dto.member; + +import com.example.reddiserver.entity.Member; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class MemberInfoResponseDto { + private Long userId; + private String name; + private String email; + private String profileImageUrl; + + public static MemberInfoResponseDto from(Member member) { + MemberInfoResponseDto userInfoResponseDto = new MemberInfoResponseDto(); + userInfoResponseDto.setUserId(member.getId()); + userInfoResponseDto.setName(member.getName()); + userInfoResponseDto.setEmail(member.getEmail()); + userInfoResponseDto.setProfileImageUrl(member.getProfileImageUrl()); + return userInfoResponseDto; + } +} diff --git a/src/main/java/com/example/reddiserver/entity/RefreshToken.java b/src/main/java/com/example/reddiserver/entity/RefreshToken.java index 24da08c..822d29c 100644 --- a/src/main/java/com/example/reddiserver/entity/RefreshToken.java +++ b/src/main/java/com/example/reddiserver/entity/RefreshToken.java @@ -2,29 +2,19 @@ import lombok.Builder; import lombok.Getter; +import lombok.Setter; import org.springframework.data.annotation.Id; import org.springframework.data.redis.core.RedisHash; import org.springframework.data.redis.core.index.Indexed; @Getter +@Setter @RedisHash(value = "refreshToken", timeToLive = 60*60*24*3) public class RefreshToken { @Id - private String refreshToken; - - @Indexed - private String providerId; + private Long userId; + private String refreshToken; - @Builder - public RefreshToken(String providerId, String refreshToken) { - this.providerId = providerId; - this.refreshToken = refreshToken; - } - - public RefreshToken updateToken(String token) { - this.refreshToken = token; - return this; - } } diff --git a/src/main/java/com/example/reddiserver/security/jwt/JwtAuthenticationFilter.java b/src/main/java/com/example/reddiserver/security/jwt/JwtAuthenticationFilter.java deleted file mode 100644 index 64920c9..0000000 --- a/src/main/java/com/example/reddiserver/security/jwt/JwtAuthenticationFilter.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.example.reddiserver.security.jwt; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; -import org.springframework.web.filter.OncePerRequestFilter; - -import java.io.IOException; - -@Component -@RequiredArgsConstructor -public class JwtAuthenticationFilter extends OncePerRequestFilter { - - private final TokenProvider tokenProvider; - - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException, RuntimeException { - String jwt = tokenProvider.resolveToken(request); - - if (StringUtils.hasText(jwt) && tokenProvider.validateAccessToken(jwt)) { - Authentication authentication = tokenProvider.getAuthentication(jwt); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - - filterChain.doFilter(request, response); - } -} diff --git a/src/main/java/com/example/reddiserver/security/jwt/JwtExceptionHandlerFilter.java b/src/main/java/com/example/reddiserver/security/jwt/JwtExceptionHandlerFilter.java deleted file mode 100644 index c52d975..0000000 --- a/src/main/java/com/example/reddiserver/security/jwt/JwtExceptionHandlerFilter.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.example.reddiserver.security.jwt; - -import io.jsonwebtoken.ExpiredJwtException; -import io.jsonwebtoken.JwtException; -import io.jsonwebtoken.MalformedJwtException; -import io.jsonwebtoken.UnsupportedJwtException; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; - -import java.io.IOException; - -@Component -public class JwtExceptionHandlerFilter extends OncePerRequestFilter { - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - try { - filterChain.doFilter(request, response); - } catch (io.jsonwebtoken.security.SignatureException | MalformedJwtException e) { - throw new JwtException("잘못된 JWT 서명입니다.", e); - } catch (ExpiredJwtException e) { - throw new JwtException("만료된 JWT 토큰입니다.", e); - } catch (UnsupportedJwtException e) { - throw new JwtException("지원되지 않는 JWT 토큰입니다.", e); - } catch (IllegalArgumentException e) { - throw new JwtException("Jwt 토큰이 잘못되었습니다.", e); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/example/reddiserver/security/jwt/TokenProvider.java b/src/main/java/com/example/reddiserver/security/jwt/TokenProvider.java deleted file mode 100644 index 3d9861a..0000000 --- a/src/main/java/com/example/reddiserver/security/jwt/TokenProvider.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.example.reddiserver.security.jwt; - -import com.example.reddiserver.dto.security.response.TokenDto; -import com.example.reddiserver.entity.RefreshToken; -import com.example.reddiserver.repository.RefreshTokenRepository; -import io.jsonwebtoken.*; -import io.jsonwebtoken.security.Keys; -import jakarta.servlet.http.HttpServletRequest; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; - -import java.security.Key; -import java.util.*; -import java.util.stream.Collectors; - -@Slf4j -@Component -@RequiredArgsConstructor -public class TokenProvider implements InitializingBean { - - private static final String AUTHORIZATION_HEADER = "Authorization"; - private static final String BEARER_PREFIX = "Bearer"; - private static final String AUTHORITIES_KEY = "auth"; - private static final long ACCESS_TOKEN_EXPIRE_TIME = 1000 * 60 * 30L; - private static final long REFRESH_TOKEN_EXPIRE_TIME = 60 * 60 * 24 * 3L; - - @Value("${spring.jwt.secret}") - private String secret; - private Key key; - - private final RefreshTokenRepository refreshTokenRepository; - - @Override - public void afterPropertiesSet() { - Base64.Decoder decoders = Base64.getDecoder(); - byte[] keyBytes = decoders.decode(secret); - this.key = Keys.hmacShaKeyFor(keyBytes); - } - - private String createToken(String name, String authorities, String type) { - long now = (new Date()).getTime(); - long time = type.equals("access") ? ACCESS_TOKEN_EXPIRE_TIME : REFRESH_TOKEN_EXPIRE_TIME; - Date tokenExpiredIn = new Date(now + time); - - String token = Jwts.builder() - .setSubject(name) - .claim(AUTHORITIES_KEY, authorities) - .setExpiration(tokenExpiredIn) - .signWith(key, SignatureAlgorithm.HS512) - .compact(); - - return token; - } - - public TokenDto createAccessToken(Authentication authentication) { - String authorities = authentication.getAuthorities().stream() - .map(GrantedAuthority::getAuthority) - .collect(Collectors.joining(",")); - - String accessToken = createToken(authentication.getName(), authorities, "access"); - String newRefreshToken = createToken(authentication.getName(), authorities, "refresh"); - - Optional oldRefreshToken = refreshTokenRepository.findByProviderId(authentication.getName()); - - if (oldRefreshToken.isPresent()) { - refreshTokenRepository.save(oldRefreshToken.get().updateToken(newRefreshToken)); - } else { - RefreshToken refreshToken = RefreshToken.builder() - .providerId(authentication.getName()) - .refreshToken(newRefreshToken) - .build(); - - refreshTokenRepository.save(refreshToken); - } - - return TokenDto.builder() - .accessToken(accessToken) - .refreshToken(newRefreshToken) - .build(); - } - - private Claims parseClaims(String accessToken) { - try { - return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(accessToken).getBody(); - } catch (ExpiredJwtException e) { - log.error("Expried JWT Token"); - return e.getClaims(); - } - } - - public Authentication getAuthentication(String accessToken) { - Claims claims = parseClaims(accessToken); - - if (claims.get(AUTHORITIES_KEY) == null){ - throw new RuntimeException("권한 정보가 없는 토큰"); - } - - Collection authorities = - Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) - .map(SimpleGrantedAuthority::new) - .collect(Collectors.toList()); - - UserDetails userDetails = new User(claims.getSubject(), "", authorities); - - return new UsernamePasswordAuthenticationToken(userDetails, "", authorities); - } - - public String resolveToken(HttpServletRequest request) { - String bearerToken = request.getHeader(AUTHORIZATION_HEADER); - - if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(BEARER_PREFIX)) { - return bearerToken.substring(7); - } - - return null; - } - - public boolean validateAccessToken(String accessToken){ - try { - Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(accessToken); - return true; - } catch (io.jsonwebtoken.security.SignatureException | MalformedJwtException e) { - String msg = "잘못된 JWT 서명입니다"; - log.error(msg); - } catch (ExpiredJwtException e) { - String msg = "만료된 JWT 토큰입니다"; - log.error(msg); - } catch (UnsupportedJwtException e) { - String msg = "지원되지 않는 JWT 토큰입니다"; - log.error(msg); - } catch (IllegalArgumentException e) { - String msg = "JWT 토큰이 잘못되었습니다"; - log.error(msg); - } - return false; - } - - public boolean refreshTokenValidation(String token) { - if (!validateAccessToken(token)) return false; - - Optional refreshToken = refreshTokenRepository.findByProviderId(getEmailFromToken(token)); - - return refreshToken.isPresent() && token.equals(refreshToken.get().getRefreshToken()); - } - - public String getEmailFromToken(String token) { - return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody().getSubject(); - } -} diff --git a/src/main/java/com/example/reddiserver/security/jwt/exception/JwtAccessDeniedHandler.java b/src/main/java/com/example/reddiserver/security/jwt/exception/JwtAccessDeniedHandler.java deleted file mode 100644 index 18f9581..0000000 --- a/src/main/java/com/example/reddiserver/security/jwt/exception/JwtAccessDeniedHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.example.reddiserver.security.jwt.exception; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -@Component -@Slf4j -public class JwtAccessDeniedHandler implements AccessDeniedHandler { - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException { - // 필요한 권한이 없는 경우 403 - log.error("필요한 권한이 없는 경우 : JwtAccessDeniedHandler"); - response.sendError(HttpServletResponse.SC_FORBIDDEN); - } -} diff --git a/src/main/java/com/example/reddiserver/security/jwt/exception/JwtAuthenticationEntryPoint.java b/src/main/java/com/example/reddiserver/security/jwt/exception/JwtAuthenticationEntryPoint.java deleted file mode 100644 index ca6bcd0..0000000 --- a/src/main/java/com/example/reddiserver/security/jwt/exception/JwtAuthenticationEntryPoint.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.reddiserver.security.jwt.exception; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -@Component -@Slf4j -public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { - // 유효한 자격증명을 제공하지 않고 접근하려 할 때, 401 - log.error("유효하지 않은 자격증명 : JwtAuthenticationEntryPoint", authException.getMessage()); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); - } -} diff --git a/src/main/java/com/example/reddiserver/security/oauth/OAuth2UserInfoFactory.java b/src/main/java/com/example/reddiserver/security/oauth/OAuth2UserInfoFactory.java deleted file mode 100644 index da135c4..0000000 --- a/src/main/java/com/example/reddiserver/security/oauth/OAuth2UserInfoFactory.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.example.reddiserver.security.oauth; - -import com.example.reddiserver.security.oauth.provider.GoogleOAuth2User; -import com.example.reddiserver.security.oauth.provider.OAuth2UserInfo; - -import java.util.Map; - -public class OAuth2UserInfoFactory { - public static OAuth2UserInfo getOAuth2UserInfo(String registrationId, Map attributes) { - switch (registrationId) { - case "GOOGLE": return new GoogleOAuth2User(attributes); - - default: throw new IllegalArgumentException("지원하지 않는 OAuth 플랫폼 입니다. \n지원하는 플랫폼 : Google"); - } - } -} diff --git a/src/main/java/com/example/reddiserver/security/oauth/OAuthService.java b/src/main/java/com/example/reddiserver/security/oauth/OAuthService.java deleted file mode 100644 index 7769cc8..0000000 --- a/src/main/java/com/example/reddiserver/security/oauth/OAuthService.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.reddiserver.security.oauth; - -import com.example.reddiserver.dto.auth.response.GoogleTokenResponseDto; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class OAuthService { - - private final GoogleOAuth googleOAuth; - - @Transactional - public void login(String code, String redirectUri) { - GoogleTokenResponseDto googleToken = googleOAuth.requestToken(code, redirectUri); - System.out.println("googleToken = " + googleToken); - - - } -} diff --git a/src/main/java/com/example/reddiserver/security/oauth/PrincipalOAuth2Details.java b/src/main/java/com/example/reddiserver/security/oauth/PrincipalOAuth2Details.java deleted file mode 100644 index 231aed2..0000000 --- a/src/main/java/com/example/reddiserver/security/oauth/PrincipalOAuth2Details.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.example.reddiserver.security.oauth; - -import com.example.reddiserver.entity.Member; -import lombok.Getter; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.core.user.OAuth2User; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -@Getter -public class PrincipalOAuth2Details implements OAuth2User { - - private Member member; - private Map attributes; - - public PrincipalOAuth2Details(Member member) { - this.member = member; - } - - public PrincipalOAuth2Details(Member member, Map attributes) { - this.member = member; - this.attributes = attributes; - } - - @Override - public Map getAttributes() { - return null; - } - - @Override - public Collection getAuthorities() { - Collection collect = new ArrayList<>(); - collect.add(new GrantedAuthority() { - @Override - public String getAuthority() { - return member.getAuthority().toString(); - } - }); - - return collect; - } - - @Override - public String getName() { // principal.getName() 에서 getName() 은 providerId 를 의미 - return member.getProviderId(); - } -} diff --git a/src/main/java/com/example/reddiserver/security/oauth/PrincipalOAuth2DetailsService.java b/src/main/java/com/example/reddiserver/security/oauth/PrincipalOAuth2DetailsService.java deleted file mode 100644 index e1a4e7b..0000000 --- a/src/main/java/com/example/reddiserver/security/oauth/PrincipalOAuth2DetailsService.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.example.reddiserver.security.oauth; - -import com.example.reddiserver.entity.Member; -import com.example.reddiserver.entity.enums.Authority; -import com.example.reddiserver.repository.MemberRepository; -import com.example.reddiserver.security.oauth.provider.OAuth2UserInfo; -import lombok.RequiredArgsConstructor; -import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Transactional -public class PrincipalOAuth2DetailsService extends DefaultOAuth2UserService { - private final MemberRepository memberRepository; - - @Override - public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { - return processOAuth2User(userRequest, super.loadUser(userRequest)); - } - - protected OAuth2User processOAuth2User(OAuth2UserRequest userRequest, OAuth2User oAuth2User) { - String registrationId = userRequest.getClientRegistration().getRegistrationId().toUpperCase(); - OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(registrationId, oAuth2User.getAttributes()); - - System.out.println("oAuth2User.getAttributes() = " + oAuth2User.getAttributes()); - - Member member = memberRepository.findByProviderId(oAuth2UserInfo.getProviderId()).orElse(null); - if (member == null) { - member = signup(oAuth2UserInfo); - } - - return new PrincipalOAuth2Details(member, oAuth2UserInfo.getAttributes()); - } - - private Member signup(OAuth2UserInfo oAuth2UserInfo) { - Member member = Member.builder() - .providerId(oAuth2UserInfo.getProviderId()) - .name(oAuth2UserInfo.getName()) - .email(oAuth2UserInfo.getEmail()) - .profileImageUrl(oAuth2UserInfo.getProfileImage()) - .providerType(oAuth2UserInfo.getProviderType()) - .authority(Authority.ROLE_USER) - .build(); - - return memberRepository.save(member); - } -} diff --git a/src/main/java/com/example/reddiserver/security/oauth/handler/OAuthFailureHandler.java b/src/main/java/com/example/reddiserver/security/oauth/handler/OAuthFailureHandler.java deleted file mode 100644 index c9fb8c4..0000000 --- a/src/main/java/com/example/reddiserver/security/oauth/handler/OAuthFailureHandler.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.reddiserver.security.oauth.handler; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -@Component -@RequiredArgsConstructor -public class OAuthFailureHandler extends SimpleUrlAuthenticationFailureHandler { - - @Override - public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { - System.out.println("test"); - super.onAuthenticationFailure(request, response, exception); - } -} diff --git a/src/main/java/com/example/reddiserver/security/oauth/handler/OAuthSuccessHandler.java b/src/main/java/com/example/reddiserver/security/oauth/handler/OAuthSuccessHandler.java deleted file mode 100644 index 000f0e1..0000000 --- a/src/main/java/com/example/reddiserver/security/oauth/handler/OAuthSuccessHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.example.reddiserver.security.oauth.handler; - -import com.example.reddiserver.dto.security.response.TokenDto; -import com.example.reddiserver.security.jwt.TokenProvider; -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; -import org.springframework.stereotype.Component; -import org.springframework.web.util.UriComponentsBuilder; - -import java.io.IOException; - -@RequiredArgsConstructor -@Component -@Slf4j -public class OAuthSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { - - private final TokenProvider tokenProvider; - private static final ObjectMapper mapper = new ObjectMapper(); - - // 구글 설정과 상관없이 프론트 주소로 직접 리다이렉트 - @Value("${front-redirection-url}") - private String frontRedirectionUrl; - - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { - TokenDto tokenDto = tokenProvider.createAccessToken(authentication); - - String targetUrl = UriComponentsBuilder.fromUriString(frontRedirectionUrl) - .queryParam("access", tokenDto.getAccessToken()) - .queryParam("refresh", tokenDto.getRefreshToken()) - .build().toUriString(); - - getRedirectStrategy().sendRedirect(request, response, targetUrl); - } -} diff --git a/src/main/java/com/example/reddiserver/service/AuthService.java b/src/main/java/com/example/reddiserver/service/AuthService.java deleted file mode 100644 index e8f1ddf..0000000 --- a/src/main/java/com/example/reddiserver/service/AuthService.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.example.reddiserver.service; - -import com.example.reddiserver.common.ApiResponse; -import com.example.reddiserver.dto.auth.request.ReissueRequestDto; -import com.example.reddiserver.dto.security.response.TokenDto; -import com.example.reddiserver.entity.Member; -import com.example.reddiserver.repository.MemberRepository; -import com.example.reddiserver.security.jwt.TokenProvider; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; - -import java.util.HashMap; -import java.util.Map; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class AuthService { - private final TokenProvider tokenProvider; - private final MemberRepository memberRepository; - - @Transactional - public TokenDto reissue(ReissueRequestDto reissueRequestDto) { - if (!tokenProvider.refreshTokenValidation(reissueRequestDto.getRefreshToken())) { - throw new RuntimeException("유효하지 않은 Refresh Token 입니다."); - } - - Authentication authentication = tokenProvider.getAuthentication(reissueRequestDto.getAccessToken()); - - return tokenProvider.createAccessToken(authentication); - } - - // user info 조회 서비스 - public Map getUserInfo(String accessToken) { - - // Validate the Access Token - if (StringUtils.hasText(accessToken) && tokenProvider.validateAccessToken(accessToken)) { - // Retrieve user information from the token - Authentication authentication = tokenProvider.getAuthentication(accessToken); - UserDetails userDetails = (UserDetails) authentication.getPrincipal(); - - String providerId = userDetails.getUsername(); - - Member member = memberRepository.findByProviderId(providerId) - .orElseThrow(() -> new RuntimeException("User not found")); - - Map userInfo = new HashMap<>(); - userInfo.put("userId", member.getId()); - userInfo.put("username", member.getName()); - userInfo.put("email", member.getEmail()); - userInfo.put("profileImageUrl", member.getProfileImageUrl()); - return userInfo; - } - return null; - } - -} diff --git a/src/main/java/com/example/reddiserver/service/MemberService.java b/src/main/java/com/example/reddiserver/service/MemberService.java new file mode 100644 index 0000000..17d86ee --- /dev/null +++ b/src/main/java/com/example/reddiserver/service/MemberService.java @@ -0,0 +1,18 @@ +package com.example.reddiserver.service; + +import com.example.reddiserver.dto.member.MemberInfoResponseDto; +import com.example.reddiserver.repository.MemberRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MemberService { + private final MemberRepository memberRepository; + + public MemberInfoResponseDto getMemberInfo(Long id) { + return MemberInfoResponseDto.from(memberRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("해당 유저가 없습니다. id=" + id))); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 97f4db7..993299a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -14,7 +14,7 @@ spring: google: client-id: ${CLIENT_ID} client-secret: ${CLIENT_SECRET} - redirectUri: http://localhost:8080/login/oauth2/code/google + redirectUri: ${GOOGLE_REDIRECT_URL_LOCAL} # 나중에 수정 scope: profile, email front-redirection-url: ${FRONT_LOCAL_REDIRECTION_URL} @@ -34,9 +34,8 @@ spring: google: client-id: ${CLIENT_ID} client-secret: ${CLIENT_SECRET} - redirectUri: ${SERVER_PROD_API_URL}/login/oauth2/code/google + redirectUri: ${GOOGLE_REDIRECT_URL_PROD} scope: profile, email -front-redirection-url: ${FRONT_PROD_REDIRECTION_URL} --- # default 공통 설정 From f1fc6ec8f15e91a80a7779b0b8c44d661b327781 Mon Sep 17 00:00:00 2001 From: itsme-shawn Date: Tue, 30 Jan 2024 10:19:23 +0900 Subject: [PATCH 3/3] =?UTF-8?q?hotfix:=20=EB=A0=88=EB=94=94=EC=8A=A4=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EB=A1=9C=EC=A7=81=20=EC=9D=BC=EB=8B=A8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20(=EC=B6=94=ED=9B=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=EC=98=88=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reddiserver/auth/service/JwtTokenProvider.java | 4 ++-- .../example/reddiserver/auth/service/OAuthService.java | 10 +++++----- src/main/resources/application.yml | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/example/reddiserver/auth/service/JwtTokenProvider.java b/src/main/java/com/example/reddiserver/auth/service/JwtTokenProvider.java index 6bfe34e..c5c8ded 100644 --- a/src/main/java/com/example/reddiserver/auth/service/JwtTokenProvider.java +++ b/src/main/java/com/example/reddiserver/auth/service/JwtTokenProvider.java @@ -24,7 +24,7 @@ public class JwtTokenProvider implements InitializingBean { private Key key; - private final Long accessTokenExpiredTime = 1000 * 60L * 60L * 12L; // 유효시간 12시간 (임시 변경) + private final Long accessTokenExpiredTime = 1000 * 60L * 60L * 24L; // 유효시간 24시간 (임시 변경) private final Long refreshTokenExpiredTime = 1000 * 60L * 60L * 24L * 14L; // 유효시간 14일 private final Long shortAccessTokenExpiredTime = 1000 * 60L * 5; // 유효시간 5분 @@ -37,7 +37,7 @@ public void afterPropertiesSet() throws Exception { } public String createAccessToken(Map payload) { - return createJwtToken(payload, shortAccessTokenExpiredTime); + return createJwtToken(payload, accessTokenExpiredTime); } public String createRefreshToken(Map payload) { diff --git a/src/main/java/com/example/reddiserver/auth/service/OAuthService.java b/src/main/java/com/example/reddiserver/auth/service/OAuthService.java index 53b8065..a0e2462 100644 --- a/src/main/java/com/example/reddiserver/auth/service/OAuthService.java +++ b/src/main/java/com/example/reddiserver/auth/service/OAuthService.java @@ -66,11 +66,11 @@ public LoginResponseDto login(String code) { String refreshToken = jwtTokenProvider.createRefreshToken(payload); // redis에 저장 - RefreshToken refreshTokenEntity = new RefreshToken(); - refreshTokenEntity.setUserId(member.getId()); - refreshTokenEntity.setRefreshToken(refreshToken); - - refreshTokenRepository.save(refreshTokenEntity); +// RefreshToken refreshTokenEntity = new RefreshToken(); +// refreshTokenEntity.setUserId(member.getId()); +// refreshTokenEntity.setRefreshToken(refreshToken); +// +// refreshTokenRepository.save(refreshTokenEntity); return LoginResponseDto.builder() .accessToken(accessToken) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 993299a..13d0472 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -16,7 +16,6 @@ spring: client-secret: ${CLIENT_SECRET} redirectUri: ${GOOGLE_REDIRECT_URL_LOCAL} # 나중에 수정 scope: profile, email -front-redirection-url: ${FRONT_LOCAL_REDIRECTION_URL} --- spring: