Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7ef9de0
Merge pull request #4 from 2025-DetectEP/develop
yerim123456 Mar 3, 2025
dffb387
Merge pull request #5 from 2025-DetectEP/PRBE-15/hotfix/cors-error
yerim123456 Mar 3, 2025
49b021b
Merge pull request #6 from 2025-DetectEP/develop
yerim123456 Mar 3, 2025
cbfd43e
hotfix: cors 설정 정의한 부분 적용되도록 설정 [PRBE-15]
Mar 3, 2025
4b0a3e2
Merge pull request #7 from 2025-DetectEP/PRBE-15/hotfix/cors-error
yerim123456 Mar 3, 2025
965d222
hotfix: oauth2의 경우 cors 에 적용되지 않도록 설정 [PRBE-15]
Mar 3, 2025
044406b
Merge pull request #8 from 2025-DetectEP/PRBE-15/hotfix/cors-error
yerim123456 Mar 3, 2025
98f1178
hotfix: 설정한 cors security에 설정하지 않도록 추가 [PRBE-15]
Mar 3, 2025
a8fa434
Merge pull request #9 from 2025-DetectEP/PRBE-15/hotfix/cors-error
yerim123456 Mar 3, 2025
17e4194
remove: security oauth 관련 파일 삭제 [PRBE-15]
Mar 5, 2025
65f3f75
fix: oauth 설정 제거 및 cors 설정 추가 [PRBE-15]
Mar 5, 2025
4b493c8
refactor: jwt 키워드 final 설정 추가 [PRBE-15]
Mar 5, 2025
907875a
fix: email null 값일 수 있는 상황 고려하여 null 설정 추가 [PRBE-15]
Mar 5, 2025
f48d8bb
chore: web client 의존성 추가 [PRBE-15]
Mar 5, 2025
63789a6
feat: web client 설정 추가 [PRBE-15]
Mar 5, 2025
77b9e71
feat: facebook accessToken api 응답 dto 추가 [PRBE-15]
Mar 5, 2025
5044685
feat: facebook user info api 응답 dto 추가 [PRBE-15]
Mar 5, 2025
eb0cc75
feat: facebook api 요청을 통해 받을 최종 응답 dto 설정 [PRBE-15]
Mar 5, 2025
c374b9c
feat: facebook api(accessToken, long-term accessToken, userInfo) Wecl…
Mar 5, 2025
0606e6e
feat: facebook code 를 통해 jwt 발급 로직 추가 [PRBE-15]
Mar 5, 2025
26ebb84
fix: 로그인 요청 경로 수정에 따른 jwt 인증 안하는 url 수정 [PRBE-15]
Mar 5, 2025
4017bce
feat: facebook code 유효성 에러 코드 추가 [PRBE-15]
Mar 5, 2025
325179e
feat: facebook code 유효성 검사 로직 추가 [PRBE-15]
Mar 5, 2025
590c7e7
feat: facebook code 를 통해 jwt 발급 api 추가 [PRBE-15]
Mar 5, 2025
fbd0f3e
docs: facebook code 를 통해 jwt 발급 api 문서화 추가 [PRBE-15]
Mar 5, 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
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'

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

// Spring Security & OAuth2
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse

// accessToken 이 필요없는 경우 필터링 없이 처리
if (requestURI.startsWith("/api/auth/token") ||
requestURI.startsWith("/oauth2")) { // oauth2/authorization/facebook
requestURI.startsWith("/api/auth/login/facebook")) {
chain.doFilter(request, response);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
public class OpenApiConfig {

private static final String BEARER_TOKEN_PREFIX = "bearer";
private static String securityJwtName = "JWT";
private static final String securityJwtName = "JWT";

@Bean
public OpenAPI customOpenAPI() {
Expand Down
36 changes: 16 additions & 20 deletions src/main/java/com/olive/pribee/global/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
Expand All @@ -15,9 +16,6 @@
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import com.olive.pribee.global.common.filter.JwtAuthenticationFilter;
import com.olive.pribee.module.auth.handler.OAuth2AuthenticationFailureHandler;
import com.olive.pribee.module.auth.handler.OAuth2AuthenticationSuccessHandler;
import com.olive.pribee.module.auth.service.CustomOAuth2UserService;

import lombok.RequiredArgsConstructor;

Expand All @@ -26,36 +24,34 @@
@RequiredArgsConstructor
public class SecurityConfig {

@Value("${front.url}")
@Value("${url.test}")
private String TEST_URL;

@Value("${url.front}")
private String FRONT_URL;

@Value("${url.domain}")
private String DOMAIN_URL;

private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final CustomOAuth2UserService customOAuth2UserService;
private final OAuth2AuthenticationSuccessHandler successHandler;
private final OAuth2AuthenticationFailureHandler failureHandler;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers(
"/api/auth/token",
"/oauth2/**",
"/api/auth/login/facebook",
"/swagger-ui/**",
"/webjars/**",
"/swagger-ui.html",
"/v3/api-docs/**").permitAll()
"/v3/api-docs/**"
).permitAll()
.anyRequest().authenticated()
)

// OAuth2 로그인 설정
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo.userService(customOAuth2UserService))
.successHandler(successHandler)
.failureHandler(failureHandler)
)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

return http.build();
Expand All @@ -65,12 +61,12 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
public CorsConfigurationSource corsConfigurationSource() {
// 허용할 출처, HTTP 메서드, 헤더 설정 및 자격 증명 포함 설정
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of(FRONT_URL));
configuration.setAllowedOrigins(List.of(TEST_URL, FRONT_URL, DOMAIN_URL));
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
configuration.setAllowedHeaders(List.of("*"));
configuration.setAllowCredentials(true);

// 특정 API 경로에 대해 CORS 정책을 적용
// 특정 API 경로에 대해 CORS 정책 제외
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", configuration);
source.registerCorsConfiguration("/swagger-ui/**", configuration);
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/com/olive/pribee/global/config/WebClientConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.olive.pribee.global.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class WebClientConfig {

@Bean
public WebClient.Builder webClientBuilder() {
return WebClient.builder()
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

@Getter
public enum GlobalErrorCode implements ErrorCode {
INVALID_FACEBOOK_CODE(HttpStatus.UNAUTHORIZED, "facebook code가 유효하지 않습니다."),
AUTHENTICATION_FAILED(HttpStatus.UNAUTHORIZED, "인증에 실패하였습니다."),
AUTHORIZATION_FAILED(HttpStatus.UNAUTHORIZED, "인가에 실패하였습니다."),
ACCESS_TOKEN_REQUIRED(HttpStatus.UNAUTHORIZED, "Access Token이 필요합니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@
public class MemberController implements MemberControllerDocs {
private final MemberService memberService;

@GetMapping("/login/facebook")
public ResponseEntity<ResponseDto> getLogin(@RequestHeader("facebook-code") String code){
LoginResDto resDto = memberService.getAccessToken(code);
return ResponseEntity.status(201).body(DataResponseDto.of(resDto, 201));
}

@GetMapping("/token")
public ResponseEntity<ResponseDto> getAccessToken(@RequestHeader("Authorization-Refresh") String refreshToken) {
LoginResDto resDto = memberService.getAccessToken(refreshToken);
LoginResDto resDto = memberService.getNewAccessToken(refreshToken);
return ResponseEntity.status(201).body(DataResponseDto.of(resDto, 201));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,29 @@
@Tag(name = "Member", description = "사용자 관련 API")
public interface MemberControllerDocs {

@Operation(summary = "accessToken 발급", description = "리프레시 토큰을 이용해 엑세스 토큰을 발급합니다.")
@Operation(summary = "로그인", description = "facebook code 를 통해 로그인을 발급합니다.")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "Created",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ResponseDto.class),
examples =
@ExampleObject(value = "{ \"code\": 201, \"message\": \"Created\" }")
)
),
@ApiResponse(responseCode = "401", description = "인증에 실패하였습니다.",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ResponseDto.class),
examples =
@ExampleObject(value = "{ \"code\": 401, \"message\": \"facebook code가 유효하지 않습니다.\" }")

)
)
})
ResponseEntity<ResponseDto> getLogin(String code);

@Operation(summary = "accessToken 재발급", description = "리프레시 토큰을 이용해 엑세스 토큰을 발급합니다.")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "Created",
content = @Content(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public class Member extends BaseTime {
@NotNull
private String name;

@NotNull
private String email;

@NotNull
Expand All @@ -51,7 +50,7 @@ public class Member extends BaseTime {
@Enumerated(EnumType.STRING)
private MemberRole role;

public static Member of(@NotNull String facebookId,@NotNull String name, @NotNull String email, @NotNull String profilePictureUrl) {
public static Member of(@NotNull String facebookId,@NotNull String name, String email, @NotNull String profilePictureUrl) {
return Member.builder()
.facebookId(facebookId)
.name(name)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.olive.pribee.module.auth.dto.res;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class FacebookAuthRes {

private String facebookId;
private String longTermToken;

@Builder
public FacebookAuthRes(
@JsonProperty("facebookId") String facebookId,
@JsonProperty("longTermToken") String longTermToken

) {
this.facebookId = facebookId;
this.longTermToken = longTermToken;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.olive.pribee.module.auth.dto.res;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class FacebookTokenRes {
private String accessToken;
private String tokenType;
private long expiresIn;

@Builder
public FacebookTokenRes(
@JsonProperty("access_token") String accessToken,
@JsonProperty("token_type") String tokenType,
@JsonProperty("expires_in") long expiresIn
) {
this.accessToken = accessToken;
this.tokenType = tokenType;
this.expiresIn = expiresIn;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.olive.pribee.module.auth.dto.res;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class FacebookUserInfoPictureRes {

private Data data;

@Builder
public FacebookUserInfoPictureRes(@JsonProperty("data") Data data) {
this.data = data;
}

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public static class Data {
private int height;
private boolean isSilhouette;
private String url;
private int width;

@Builder
public Data(
@JsonProperty("height") int height,
@JsonProperty("is_silhouette") boolean isSilhouette,
@JsonProperty("url") String url,
@JsonProperty("width") int width
) {
this.height = height;
this.isSilhouette = isSilhouette;
this.url = url;
this.width = width;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.olive.pribee.module.auth.dto.res;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class FacebookUserInfoRes {
private String id;
private String name;
private String email;
private FacebookUserInfoPictureRes picture;

@Builder
public FacebookUserInfoRes(
@JsonProperty("id") String id,
@JsonProperty("name") String name,
@JsonProperty("email") String email,
@JsonProperty("picture") FacebookUserInfoPictureRes picture
) {
this.id = id;
this.name = name;
this.email = email;
this.picture = picture;
}

}

This file was deleted.

Loading