Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
9f52155
hotfix(be): stock서버 cors 설정 변경
bo-ram-bo-ram Feb 28, 2025
65c41af
Merge remote-tracking branch 'origin/dev' into dev
bo-ram-bo-ram Apr 17, 2025
7472c1d
#353 feat(be) : webflux 의존성 추가
bo-ram-bo-ram Apr 21, 2025
c6d9835
#353 feat(be) : GlobalExceptionHandler를 webflux 방식으로 변경
bo-ram-bo-ram Apr 22, 2025
f7a614d
#353 feat(be) : 예외 추가에 따른 error code추가
bo-ram-bo-ram Apr 22, 2025
ebd1e65
#353 feat(be) : CustomAccessDeniedHandler를 webflux 방식으로 변경
bo-ram-bo-ram Apr 22, 2025
70647ad
#353 feat(be) : CustomJwtAuthenticationEntryPoint를 webflux 방식으로 변경
bo-ram-bo-ram Apr 22, 2025
73d8354
#353 feat(be) : JwtAuthenticationFilter를 webflux 방식으로 변경
bo-ram-bo-ram Apr 22, 2025
379e17d
#353 feat(be) :webflux 방식으로 변경으로 인한 불필요 클래스 삭제 - ResponseStatusSette…
bo-ram-bo-ram Apr 22, 2025
c4713b2
#353 feat(be) :webflux 방식으로 변경으로 인한 jwt 인증 추가 클래스 구현 - JwtReactiveAu…
bo-ram-bo-ram Apr 22, 2025
a02d7f1
#353 feat(be) :SecurityConfig를 webflux 방식으로 변경
bo-ram-bo-ram Apr 22, 2025
74b35ad
#353 feat(be) :WebConfig를 webflux 방식으로 변경
bo-ram-bo-ram Apr 22, 2025
7ee5e7e
#353 feat(be) :webflux 구조로 변경함에 따라 의존성 변경(db, security, swagger, test)
bo-ram-bo-ram Apr 22, 2025
fa3e104
#353 del(be) :test삭제
bo-ram-bo-ram Apr 22, 2025
ea868c9
#353 feat(be) :token 저장주기 변경
bo-ram-bo-ram Apr 22, 2025
01c692f
#353 feat(be) :user엔티티 webflux 구조로 변경
bo-ram-bo-ram Apr 22, 2025
c00fd9e
#353 feat(be) :userRepository jpa에서 webflux 구조로 변경
bo-ram-bo-ram Apr 22, 2025
b920e0c
#353 feat(be) :userService webflux 구조로 변경 (mono 반환 및 비동기방식 적용)
bo-ram-bo-ram Apr 22, 2025
bb76817
#353 feat(be) :socialService webflux 구조로 변경 (mono 반환 및 비동기방식 적용)
bo-ram-bo-ram Apr 22, 2025
b74939a
#353 feat(be) :userController webflux 구조로 변경 (mono 반환)
bo-ram-bo-ram Apr 22, 2025
7f9acd7
#353 feat(be) :authController webflux 구조로 변경 (mono 반환)
bo-ram-bo-ram Apr 22, 2025
83563d2
#353 feat(be) :application jpa에서 webflux 구조로 변경
bo-ram-bo-ram Apr 22, 2025
304b89a
#353 feat(be) :kakao 연동 webflux 구조를 위한 연동 방식 변경(FeignClient->WebClient)
bo-ram-bo-ram Apr 22, 2025
b7a7f3e
#353 del(be) :TokenRepository 불필요 메소드 삭제
bo-ram-bo-ram Apr 22, 2025
7c01f39
#353 del(be) :TokenService를 webflux 전환을 위한 mono 반환
bo-ram-bo-ram Apr 22, 2025
dade46e
#353 feat(be) :webflux 방식 명시
bo-ram-bo-ram Apr 22, 2025
afa527e
#353 feat(be) :WebClient 파싱을 위한 KakaoTokenResponse구현
bo-ram-bo-ram Apr 22, 2025
e5420ca
#353 feat(be) :kakao로그인 시 인가 코드로 액세스 토큰 요청을 위한 서비스 구현
bo-ram-bo-ram Apr 22, 2025
2f7036a
#353 refactor(auth): refreshToken 메서드를 리액티브 방식으로 리팩토링
bo-ram-bo-ram Apr 22, 2025
f840ae8
#353 fix(be) : 불필요 Import문삭제
bo-ram-bo-ram Apr 22, 2025
d5726f4
#353 feat(be) : @CurrentUser mvc에서 webflux로 전환
bo-ram-bo-ram Apr 24, 2025
5938c41
#353 feat(be) : common-module mvc에서 webflux로 전환
bo-ram-bo-ram Apr 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions src/backend/auth_server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,29 @@ java {

repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}

dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:2023.0.2"
mavenBom "org.springframework.security:spring-security-bom:6.3.0-M2"
}
}

dependencies {
//common-module
implementation project(":common_module")

//webflux
implementation 'org.springframework.boot:spring-boot-starter-webflux'

// Spring
implementation 'org.springframework.boot:spring-boot-starter-web'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
implementation 'org.springframework.boot:spring-boot-starter-actuator'

//db
implementation group: 'org.postgresql', name: 'postgresql', version: '42.7.3'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'
runtimeOnly 'org.postgresql:r2dbc-postgresql'

// Lombok
compileOnly 'org.projectlombok:lombok'
Expand All @@ -43,17 +46,11 @@ dependencies {
// Validation
implementation 'org.springframework.boot:spring-boot-starter-validation'

// Test
testImplementation 'org.springframework.boot:spring-boot-starter-test'

//junit
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// Spring Cloud OpenFeign
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

//Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
implementation 'org.springdoc:springdoc-openapi-starter-webflux-ui:2.1.0'

//JWT
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5'
Expand All @@ -65,7 +62,7 @@ dependencies {

//Security
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.springframework.security:spring-security-config'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,30 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.r2dbc.config.EnableR2dbcAuditing;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;

@EnableJpaAuditing
@EnableR2dbcAuditing
@EnableFeignClients
@ImportAutoConfiguration(FeignAutoConfiguration.class)
@SpringBootApplication(scanBasePackages = {
"com.jootalkpia.auth_server",
"com.jootalkpia.passport",
"com.jootalkpia.config",
})
@EnableR2dbcRepositories(basePackages = "com.jootalkpia.auth_server.user.repository")
@EnableRedisRepositories(basePackages = "com.jootalkpia.auth_server.jwt")
@SpringBootApplication(
scanBasePackages = {
"com.jootalkpia.auth_server",
"com.jootalkpia.passport",
"com.jootalkpia.config",
},
exclude = {
SecurityAutoConfiguration.class,
UserDetailsServiceAutoConfiguration.class
}
)
public class AuthServerApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@


import com.jootalkpia.auth_server.client.kakao.response.KakaoUserResponse;
import org.springframework.cloud.openfeign.FeignClient;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@FeignClient(name = "kakaoApiClient", url = "https://kapi.kakao.com")
public interface KakaoApiClient {
@Service
@RequiredArgsConstructor
public class KakaoApiClient {

@GetMapping(value = "/v2/user/me")
KakaoUserResponse getUserInformation(@RequestHeader(HttpHeaders.AUTHORIZATION) String accessToken);
private final WebClient webClient = WebClient.builder()
.baseUrl("https://kapi.kakao.com")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();

public Mono<KakaoUserResponse> getUserInfo(String accessToken) {
return webClient.get()
.uri("/v2/user/me")
.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)
.retrieve()
.bodyToMono(KakaoUserResponse.class);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.jootalkpia.auth_server.client.kakao;

import com.jootalkpia.auth_server.client.kakao.response.KakaoTokenResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@Service
@RequiredArgsConstructor
public class KakaoAuthWebClientService {

@Value("${kakao.clientId}")
private String clientId;

private final WebClient kakaoWebClient = WebClient.builder()
.baseUrl("https://kauth.kakao.com")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.build();

public Mono<KakaoTokenResponse> getAccessToken(String code, String redirectUri) {
return kakaoWebClient.post()
.uri("/oauth/token")
.body(BodyInserters
.fromFormData("grant_type", "authorization_code")
.with("client_id", clientId)
.with("redirect_uri", redirectUri)
.with("code", code))
.retrieve()
.bodyToMono(KakaoTokenResponse.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,40 @@

import com.jootalkpia.auth_server.client.dto.UserInfoResponse;
import com.jootalkpia.auth_server.client.dto.UserLoginRequest;
import com.jootalkpia.auth_server.client.kakao.response.KakaoAccessTokenResponse;
import com.jootalkpia.auth_server.client.kakao.response.KakaoUserResponse;
import com.jootalkpia.auth_server.client.service.SocialService;
import com.jootalkpia.auth_server.exception.CustomException;
import com.jootalkpia.auth_server.response.ErrorCode;
import com.jootalkpia.auth_server.user.domain.Platform;
import feign.FeignException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Mono;

@Service
@Slf4j
@RequiredArgsConstructor
public class KakaoSocialService implements SocialService {

private static final String AUTH_CODE = "authorization_code";

@Value("${kakao.clientId}")
private String clientId;
private final KakaoApiClient kakaoApiClient;
private final KakaoAuthApiClient kakaoAuthApiClient;
private final KakaoAuthWebClientService kakaoAuthWebClientService;

@Transactional
@Override
public UserInfoResponse login(
public Mono<UserInfoResponse> login(
final String authorizationCode,
final UserLoginRequest loginRequest
) {
String accessToken;
try {
// 인가 코드로 Access Token + Refresh Token 받아오기
accessToken = getOAuth2Authentication(authorizationCode, loginRequest.redirectUri());
} catch (FeignException e) {
throw new CustomException(ErrorCode.AUTHENTICATION_CODE_EXPIRED);
}
// Access Token으로 유저 정보 불러오기
return getLoginDto(loginRequest.platform(), getUserInfo(accessToken));
}

private String getOAuth2Authentication(
final String authorizationCode,
final String redirectUri
) {
KakaoAccessTokenResponse response = kakaoAuthApiClient.getOAuth2AccessToken(
AUTH_CODE,
clientId,
redirectUri,
authorizationCode
);
return response.accessToken();
}

private KakaoUserResponse getUserInfo(
final String accessToken
) {
return kakaoApiClient.getUserInformation("Bearer " + accessToken);
return kakaoAuthWebClientService.getAccessToken(authorizationCode, loginRequest.redirectUri())
.flatMap(tokenResponse ->
kakaoApiClient.getUserInfo(tokenResponse.getAccessToken())
)
.map(userResponse -> getLoginDto(loginRequest.platform(), userResponse))
.onErrorMap(Exception.class, e -> {
log.error("❌ Kakao 로그인 실패: {}", e.getMessage(), e);
return new CustomException(ErrorCode.AUTHENTICATION_CODE_EXPIRED);
});
}

private UserInfoResponse getLoginDto(
Expand All @@ -74,4 +49,4 @@ private UserInfoResponse getLoginDto(
userResponse.kakaoAccount().profile().nickname()
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.jootalkpia.auth_server.client.kakao.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class KakaoTokenResponse {

@JsonProperty("access_token")
private String accessToken;

@JsonProperty("refresh_token")
private String refreshToken;

@JsonProperty("expires_in")
private Long expiresIn;

@JsonProperty("token_type")
private String tokenType;

// 필요에 따라 추가적인 필드들:
@JsonProperty("scope")
private String scope;

@JsonProperty("refresh_token_expires_in")
private Long refreshTokenExpiresIn;

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.jootalkpia.auth_server.client.service;


import com.jootalkpia.auth_server.client.dto.UserInfoResponse;
import com.jootalkpia.auth_server.client.dto.UserLoginRequest;
import reactor.core.publisher.Mono;

public interface SocialService {
UserInfoResponse login(final String authorizationToken, final UserLoginRequest loginRequest);
Mono<UserInfoResponse> login(final String authorizationToken, final UserLoginRequest loginRequest);
}
Loading
Loading