Skip to content

Commit f5cd514

Browse files
Merge pull request #45 from SWUNITZEL/feat/#44-kakao-oauth2
[FEAT] Kakao 소셜로그인 추가
2 parents 613dfb2 + 2b49394 commit f5cd514

27 files changed

Lines changed: 609 additions & 66 deletions

.github/workflows/dev_deploy.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ env:
1313
CONTAINER_NAME: springboot
1414
MONGODB_URL: ${{ secrets.MONGO_DB_URL }}
1515
JWT_SECRET: ${{ secrets.JWT_SECRET_KEY }}
16+
OAUTH_KAKAO_CLIENT_ID: ${{ secrets.OAUTH_KAKAO_CLIENT_ID }}
17+
OAUTH_KAKAO_CLIENT_SECRET: ${{ secrets.OAUTH_KAKAO_CLIENT_SECRET }}
18+
OAUTH_KAKAO_REDIRECT_URI: ${{ secrets.OAUTH_KAKAO_REDIRECT_URI }}
1619

1720
jobs:
1821
build-and-push-docker:

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ dependencies {
3636
implementation 'io.jsonwebtoken:jjwt-impl:0.12.3'
3737
implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3'
3838
implementation 'org.springframework.boot:spring-boot-starter-security'
39+
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
3940

4041
// mongoDB
4142
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'

src/main/java/com/swunitzel/fiterview/apiPayload/code/status/ErrorStatus.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ public enum ErrorStatus implements BaseErrorCode {
2828
// combine 관련 오류
2929
_COMBINE_NOT_FOUND(HttpStatus.BAD_REQUEST, "COMBINE404", "면접 조합을 찾을 수 없습니다"),
3030

31+
// OAuth 관련 오류
32+
_KAKAO_OAUTH_PARSING_ERROR(HttpStatus.BAD_REQUEST, "KAKAO-OAUTH400", "소셜 로그인 응답 파싱에 실패했습니다"),
33+
_KAKAO_OAUTH_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "KAKAO-OAUTH500", "소셜 로그인 인증에 실패했습니다"),
34+
35+
// user 관련 오류
36+
_USER_NOT_FOUND(HttpStatus.BAD_REQUEST, "User404", "해당 유저를 찾을 수 없습니다.")
3137
;
3238

3339
private final HttpStatus httpStatus;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.swunitzel.fiterview.apiPayload.exception.handler;
2+
3+
import com.swunitzel.fiterview.apiPayload.code.BaseErrorCode;
4+
import com.swunitzel.fiterview.apiPayload.exception.GeneralException;
5+
6+
public class AuthHandler extends GeneralException {
7+
public AuthHandler(BaseErrorCode code) {
8+
super(code);
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.swunitzel.fiterview.apiPayload.exception.handler;
2+
3+
import com.swunitzel.fiterview.apiPayload.code.BaseErrorCode;
4+
import com.swunitzel.fiterview.apiPayload.exception.GeneralException;
5+
6+
public class UserHandler extends GeneralException {
7+
public UserHandler(BaseErrorCode code) {
8+
super(code);
9+
}
10+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.swunitzel.fiterview.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
6+
import org.springframework.security.crypto.password.PasswordEncoder;
7+
8+
@Configuration
9+
public class PasswordConfig {
10+
@Bean
11+
public PasswordEncoder passwordEncoder() {
12+
return new BCryptPasswordEncoder();
13+
}
14+
}
15+

src/main/java/com/swunitzel/fiterview/config/SecurityConfig.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
import com.swunitzel.fiterview.jwt.JWTFilter;
44
import com.swunitzel.fiterview.jwt.JWTUtil;
55
import com.swunitzel.fiterview.jwt.LoginFilter;
6+
import com.swunitzel.fiterview.oauth.CustomOAuth2UserService;
7+
import com.swunitzel.fiterview.oauth.OAuth2LoginFailureHandler;
8+
import com.swunitzel.fiterview.oauth.OAuth2SuccessHandler;
69
import com.swunitzel.fiterview.repository.UserRepository;
710
import jakarta.servlet.http.HttpServletRequest;
11+
import lombok.RequiredArgsConstructor;
812
import org.springframework.context.annotation.Bean;
913
import org.springframework.context.annotation.Configuration;
1014
import org.springframework.security.authentication.AuthenticationManager;
@@ -23,17 +27,15 @@
2327

2428
@Configuration
2529
@EnableWebSecurity
30+
@RequiredArgsConstructor
2631
public class SecurityConfig {
2732

2833
private final AuthenticationConfiguration authenticationConfiguration;
2934
private final JWTUtil jwtUtil;
3035
private final UserRepository userRepository;
31-
32-
public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTUtil jwtUtil, UserRepository userRepository) {
33-
this.authenticationConfiguration = authenticationConfiguration;
34-
this.jwtUtil = jwtUtil;
35-
this.userRepository = userRepository;
36-
}
36+
private final CustomOAuth2UserService customOAuth2UserService;
37+
private final OAuth2LoginFailureHandler oAuth2LoginFailureHandler;
38+
private final OAuth2SuccessHandler oAuth2SuccessHandler;
3739

3840
//AuthenticationManager Bean 등록
3941
@Bean
@@ -42,12 +44,6 @@ public AuthenticationManager authenticationManager(AuthenticationConfiguration c
4244
return configuration.getAuthenticationManager();
4345
}
4446

45-
@Bean
46-
public BCryptPasswordEncoder bCryptPasswordEncoder() {
47-
48-
return new BCryptPasswordEncoder();
49-
}
50-
5147

5248
@Bean
5349
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
@@ -91,8 +87,19 @@ public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
9187
//경로별 인가 작업
9288
http
9389
.authorizeHttpRequests((auth) -> auth
94-
.requestMatchers("/api/user/login", "/", "/api/user/join", "/api/user/reissue").permitAll()
95-
.anyRequest().authenticated());
90+
.requestMatchers("/login/**", "/", "/api/user/join", "/api/user/reissue",
91+
"/oauth/login/kakao/**", "/api/user/auth/**"
92+
// , "/oauth2"
93+
).permitAll()
94+
95+
.anyRequest().authenticated())
96+
.oauth2Login(oauth ->
97+
oauth
98+
// .loginPage("/oauth2/authorization/kakao")
99+
.userInfoEndpoint(c -> c.userService(customOAuth2UserService))
100+
.successHandler(oAuth2SuccessHandler)
101+
.failureHandler(oAuth2LoginFailureHandler)
102+
);
96103

97104
// 필터 추가
98105
http

src/main/java/com/swunitzel/fiterview/controller/UserController.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package com.swunitzel.fiterview.controller;
22

3+
import com.swunitzel.fiterview.apiPayload.ApiResponse;
34
import com.swunitzel.fiterview.dto.JoinDto;
4-
import com.swunitzel.fiterview.dto.TokenPairsDto;
5+
import com.swunitzel.fiterview.dto.TokenDto;
56
import com.swunitzel.fiterview.dto.UserDto;
67
import com.swunitzel.fiterview.jwt.CustomUserDetails;
78
import com.swunitzel.fiterview.services.UserService;
@@ -20,15 +21,9 @@ public class UserController {
2021

2122
@PostMapping("/join")
2223
@ResponseBody
23-
public ResponseEntity<String> join(@RequestBody JoinDto joinDto) {
24-
try {
25-
userService.join(joinDto);
26-
return ResponseEntity.ok("ok");
27-
} catch (IllegalArgumentException e) {
28-
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
29-
} catch (Exception e) {
30-
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body( e.getMessage());
31-
}
24+
public ApiResponse<String> join(@RequestBody JoinDto joinDto) {
25+
userService.updateUser(joinDto);
26+
return ApiResponse.onSuccess("ok");
3227
}
3328

3429
@PostMapping("/reissue")
@@ -44,7 +39,7 @@ public ResponseEntity<?> reissue(@RequestHeader("Authorization") String refresh)
4439
try{
4540
if (userService.validateRefreshToken(refresh)) {
4641

47-
TokenPairsDto tokenPairsDto = userService.reissueToken(refresh);
42+
TokenDto.TokenPairsDto tokenPairsDto = userService.reissueToken(refresh);
4843
return ResponseEntity.ok(tokenPairsDto);
4944
} else {
5045
return new ResponseEntity<>("invalid refresh token", HttpStatus.UNAUTHORIZED);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.swunitzel.fiterview.converter;
2+
3+
import com.swunitzel.fiterview.domain.User;
4+
import com.swunitzel.fiterview.domain.enums.Role;
5+
import com.swunitzel.fiterview.dto.UserDto;
6+
import org.springframework.security.crypto.password.PasswordEncoder;
7+
8+
public class UserConverter {
9+
public static User toUser(String email, String name, String password, PasswordEncoder passwordEncoder, Role role) {
10+
User user = new User();
11+
user.setEmail(email);
12+
user.setPassword(passwordEncoder.encode(password));
13+
user.setName(name);
14+
user.setRole(role);
15+
return user;
16+
}
17+
18+
public static UserDto toUserDto(User user) {
19+
return UserDto.builder()
20+
.email(user.getEmail())
21+
.name(user.getName())
22+
.profileImg(user.getProfileImg())
23+
.build();
24+
25+
}
26+
}

src/main/java/com/swunitzel/fiterview/domain/User.java

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package com.swunitzel.fiterview.domain;
22

33
import com.swunitzel.fiterview.domain.enums.Gender;
4+
import com.swunitzel.fiterview.domain.enums.Role;
45
import com.swunitzel.fiterview.dto.JoinDto;
5-
import lombok.Builder;
6-
import lombok.Getter;
7-
import lombok.NoArgsConstructor;
8-
import lombok.Setter;
6+
import lombok.*;
97
import org.springframework.data.annotation.Id;
108
import org.springframework.data.mongodb.core.mapping.Document;
119

@@ -14,6 +12,8 @@
1412
@Document(collection = "user")
1513
@Getter @Setter
1614
@NoArgsConstructor
15+
@AllArgsConstructor
16+
@Builder
1717
public class User extends BaseEntity {
1818
@Id
1919
private String id;
@@ -34,15 +34,35 @@ public class User extends BaseEntity {
3434

3535
private String profileImg;
3636

37-
public User(JoinDto joinDto) {
37+
private Role role;
38+
39+
private String provider;
40+
41+
private String providerId;
42+
43+
public User(JoinDto joinDto, Role role) {
3844
this.email = joinDto.getEmail();
3945
this.password = joinDto.getPassword();
4046
this.name = joinDto.getName();
4147
this.birth = joinDto.getBirth();
4248
this.gender = joinDto.getGender();
49+
this.role = role;
4350
if (joinDto.getPromotion_code() != null){
4451
this.promotion_code = joinDto.getPromotion_code();;
4552
}
4653

4754
}
55+
56+
public void updateRefresh(String token){
57+
this.refresh = token;
58+
}
59+
60+
public void updateUser(JoinDto joinDto, Role role) {
61+
this.gender = joinDto.getGender();
62+
this.promotion_code = joinDto.getPromotion_code();
63+
this.birth = joinDto.getBirth();
64+
this.name = joinDto.getName();
65+
this.role = role;
66+
}
67+
4868
}

0 commit comments

Comments
 (0)