-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[✨feat] 회원가입 구현
- Loading branch information
Showing
72 changed files
with
1,894 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package org.noostak.auth.api; | ||
|
||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.noostak.auth.application.OauthService; | ||
import org.noostak.auth.application.OauthServiceFactory; | ||
import org.noostak.auth.application.jwt.JwtToken; | ||
import org.noostak.auth.common.exception.AuthErrorCode; | ||
import org.noostak.auth.common.exception.AuthException; | ||
import org.noostak.auth.common.success.AuthSuccessCode; | ||
import org.noostak.auth.domain.vo.AuthId; | ||
import org.noostak.auth.dto.SignUpResponse; | ||
import org.noostak.global.success.SuccessResponse; | ||
import org.noostak.auth.application.AuthInfoService; | ||
import org.noostak.auth.dto.SignUpRequest; | ||
import org.noostak.member.application.MemberService; | ||
import org.noostak.member.domain.Member; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
@RequestMapping("/api/v1/auth") | ||
public class OauthController { | ||
|
||
private final OauthServiceFactory oauthServiceFactory; | ||
private final AuthInfoService authInfoService; | ||
private final MemberService memberService; | ||
|
||
@PostMapping("/sign-up") | ||
public ResponseEntity<?> signUp(HttpServletRequest request, @ModelAttribute SignUpRequest requestDto){ | ||
String code = request.getHeader("Authorization"); | ||
|
||
// authType 을 기준으로 OauthService 선택하기 | ||
String authType = requestDto.getAuthType().toUpperCase(); | ||
OauthService oauthService = oauthServiceFactory.getService(authType); | ||
|
||
// code를 통해서 AccessToken 및 RefreshToken 가져오기 | ||
JwtToken jwtToken = oauthService.requestToken(code); | ||
String accessToken = jwtToken.getAccessToken(); | ||
log.info("jwtToken : {}", jwtToken); | ||
|
||
// 소셜 로그인 진행하기 | ||
AuthId authId = oauthService.login(accessToken); | ||
|
||
|
||
// 동일 소셜 계정으로 가입이 되어있는지 확인하기 | ||
if(authInfoService.hasAuthInfo(authId)){ | ||
throw new AuthException(AuthErrorCode.AUTHID_ALREADY_EXISTS,authId.value()); | ||
} | ||
|
||
// 멤버 생성하기 | ||
Member member = memberService.createMember(requestDto); | ||
|
||
// 멤버와 연관된 AuthInfo 생성하기 | ||
SignUpResponse response = | ||
authInfoService.createAuthInfo(authType, authId, jwtToken, member); | ||
|
||
return ResponseEntity.ok((SuccessResponse.of(AuthSuccessCode.SIGNUP_COMPLETED,response))); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/org/noostak/auth/application/AuthInfoService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.noostak.auth.application; | ||
|
||
import org.noostak.auth.application.jwt.JwtToken; | ||
import org.noostak.auth.domain.vo.AuthId; | ||
import org.noostak.auth.dto.SignUpResponse; | ||
import org.noostak.member.domain.Member; | ||
|
||
public interface AuthInfoService { | ||
SignUpResponse createAuthInfo(String authType, AuthId authId, JwtToken jwtToken, Member member); | ||
|
||
boolean hasAuthInfo(String authId); | ||
|
||
boolean hasAuthInfo(AuthId authId); | ||
} |
63 changes: 63 additions & 0 deletions
63
src/main/java/org/noostak/auth/application/AuthInfoServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package org.noostak.auth.application; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.noostak.auth.application.jwt.JwtToken; | ||
import org.noostak.auth.domain.AuthInfo; | ||
import org.noostak.auth.domain.AuthInfoRepository; | ||
import org.noostak.auth.domain.vo.AuthId; | ||
import org.noostak.auth.domain.vo.AuthType; | ||
import org.noostak.auth.domain.vo.RefreshToken; | ||
import org.noostak.auth.dto.SignUpResponse; | ||
import org.noostak.member.domain.Member; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class AuthInfoServiceImpl implements AuthInfoService{ | ||
|
||
private final AuthInfoRepository authInfoRepository; | ||
@Override | ||
@Transactional | ||
public SignUpResponse createAuthInfo(String authType, AuthId authId, JwtToken jwtToken, Member member) { | ||
AuthInfo newAuthInfo = createAuthInfo( | ||
AuthType.from(authType), | ||
authId, | ||
RefreshToken.from(jwtToken.getRefreshToken()), | ||
member | ||
); | ||
|
||
saveAuthInfo(newAuthInfo); | ||
|
||
return SignUpResponse.of( | ||
jwtToken.getAccessToken(), | ||
jwtToken.getRefreshToken(), | ||
member.getId(), | ||
authType | ||
); | ||
} | ||
|
||
private AuthInfo createAuthInfo(AuthType authType, AuthId authId, RefreshToken refreshToken, Member member) { | ||
return AuthInfo.of( | ||
authType, | ||
authId, | ||
refreshToken, | ||
member | ||
); | ||
} | ||
|
||
private AuthInfo saveAuthInfo(AuthInfo authInfo){ | ||
return authInfoRepository.save(authInfo); | ||
} | ||
|
||
@Override | ||
public boolean hasAuthInfo(String authId){ | ||
return authInfoRepository.hasAuthInfoByAuthId(AuthId.from(authId)); | ||
} | ||
|
||
@Override | ||
public boolean hasAuthInfo(AuthId authId) { | ||
return authInfoRepository.hasAuthInfoByAuthId(authId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package org.noostak.auth.application; | ||
|
||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public enum GoogleApi { | ||
TOKEN_REQUEST("https://oauth2.googleapis.com/token"), | ||
USER_INFO("https://www.googleapis.com/oauth2/v2/userinfo") | ||
; | ||
|
||
private final String url; | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/org/noostak/auth/application/GoogleService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package org.noostak.auth.application; | ||
|
||
public interface GoogleService extends OauthService { | ||
|
||
} |
77 changes: 77 additions & 0 deletions
77
src/main/java/org/noostak/auth/application/GoogleServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package org.noostak.auth.application; | ||
|
||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.noostak.auth.application.jwt.JwtToken; | ||
import org.noostak.auth.application.jwt.JwtTokenProvider; | ||
import org.noostak.auth.common.exception.AuthErrorCode; | ||
import org.noostak.auth.common.exception.AuthException; | ||
import org.noostak.auth.domain.vo.AuthId; | ||
import org.noostak.auth.dto.*; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class GoogleServiceImpl implements GoogleService{ | ||
|
||
private final GoogleTokenRequestFactory googleTokenRequestFactory; | ||
private final RestClient restClient; | ||
|
||
@Override | ||
public void requestAccessToken(String refreshToken) { | ||
|
||
} | ||
|
||
|
||
@Override | ||
public TokenInfo fetchTokenInfo(String accessToken) { | ||
return null; | ||
} | ||
|
||
|
||
@Override | ||
public JwtToken requestToken(String code) { | ||
String url = GoogleApi.TOKEN_REQUEST.getUrl(); | ||
|
||
GoogleTokenRequest request = googleTokenRequestFactory.createRequest(code); | ||
|
||
GoogleTokenResponse response = | ||
restClient.postRequest(url, | ||
request.getUrlEncodedParams(), | ||
GoogleTokenResponse.class); | ||
|
||
log.info("googleTokenResponse: {}",response); | ||
response.validate(); | ||
|
||
return JwtTokenProvider.createToken(response.getAccessToken(),response.getRefreshToken()); | ||
} | ||
|
||
@Override | ||
public AuthId login(String accessToken) { | ||
String url = GoogleApi.USER_INFO.getUrl(); | ||
|
||
HttpHeaders headers = makeAuthorizationBearerTokenHeader(accessToken); | ||
|
||
GoogleUserInfoResponse response = | ||
restClient.getRequest(url, headers, GoogleUserInfoResponse.class); | ||
|
||
response.validate(); | ||
|
||
return AuthId.from(response.getId()); | ||
} | ||
|
||
public HttpHeaders makeAuthorizationBearerTokenHeader(String token){ | ||
HttpHeaders headers = new HttpHeaders(); | ||
|
||
if(token == null || token.isEmpty() || token.isBlank()){ | ||
throw new AuthException(AuthErrorCode.INVALID_TOKEN); | ||
} | ||
|
||
headers.set("Authorization", "Bearer " + token); | ||
|
||
return headers; | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
src/main/java/org/noostak/auth/application/GoogleTokenRequestFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package org.noostak.auth.application; | ||
|
||
import org.noostak.auth.dto.GoogleTokenRequest; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Component; | ||
|
||
|
||
@Component | ||
public class GoogleTokenRequestFactory { | ||
|
||
@Value("${oauth-property.google.client_id}") | ||
private final String clientId; | ||
|
||
@Value("${oauth-property.google.redirect_uri}") | ||
private final String redirectUri; | ||
|
||
@Value("${oauth-property.google.client_secret}") | ||
private final String clientSecret; | ||
|
||
public GoogleTokenRequestFactory(String clientId, String redirectUri, String clientSecret) { | ||
this.clientId = clientId; | ||
this.redirectUri = redirectUri; | ||
this.clientSecret = clientSecret; | ||
} | ||
|
||
public GoogleTokenRequest createRequest(String code) { | ||
return GoogleTokenRequest.of(clientId, redirectUri, code, clientSecret); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.noostak.auth.application; | ||
|
||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public enum KaKaoApi { | ||
TOKEN_REQUEST("https://kauth.kakao.com/oauth/token"), | ||
FETCH_TOKEN("https://kapi.kakao.com/v1/user/access_token_info"), | ||
USER_INFO("https://kapi.kakao.com/v2/user/me") | ||
; | ||
|
||
private final String url; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package org.noostak.auth.application; | ||
|
||
public interface KakaoService extends OauthService { | ||
|
||
} |
80 changes: 80 additions & 0 deletions
80
src/main/java/org/noostak/auth/application/KakaoServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package org.noostak.auth.application; | ||
|
||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.noostak.auth.application.jwt.JwtToken; | ||
import org.noostak.auth.application.jwt.JwtTokenProvider; | ||
import org.noostak.auth.common.exception.AuthErrorCode; | ||
import org.noostak.auth.common.exception.AuthException; | ||
import org.noostak.auth.domain.vo.AuthId; | ||
import org.noostak.auth.dto.*; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class KakaoServiceImpl implements KakaoService{ | ||
|
||
private final KakaoTokenRequestFactory kakaoTokenRequestFactory; | ||
private final RestClient restClient; | ||
@Override | ||
public void requestAccessToken(String refreshToken) { | ||
|
||
} | ||
|
||
@Override | ||
public TokenInfo fetchTokenInfo(String accessToken) { | ||
String url = KaKaoApi.FETCH_TOKEN.getUrl(); | ||
HttpHeaders headers = makeAuthorizationBearerTokenHeader(accessToken); | ||
|
||
KakaoTokenInfoResponse response = | ||
restClient.postRequest(url, headers, KakaoTokenInfoResponse.class); | ||
|
||
response.validate(); | ||
|
||
return TokenInfo.of(response.getId()); | ||
} | ||
|
||
|
||
@Override | ||
public JwtToken requestToken(String code) { | ||
String url = KaKaoApi.TOKEN_REQUEST.getUrl(); | ||
|
||
KakaoTokenRequest request = kakaoTokenRequestFactory.createRequest(code); | ||
|
||
KakaoTokenResponse response = | ||
restClient.postRequest(url, | ||
request.getUrlEncodedParams(), | ||
KakaoTokenResponse.class); | ||
|
||
response.validate(); | ||
|
||
return JwtTokenProvider.createToken(response.getAccessToken(),response.getRefreshToken()); | ||
} | ||
|
||
@Override | ||
public AuthId login(String accessToken) { | ||
String url = KaKaoApi.USER_INFO.getUrl(); | ||
|
||
HttpHeaders headers = makeAuthorizationBearerTokenHeader(accessToken); | ||
|
||
KakaoUserInfoResponse response = | ||
restClient.postRequest(url, headers, KakaoUserInfoResponse.class); | ||
|
||
response.validate(); | ||
|
||
return AuthId.from(response.getId()); | ||
} | ||
|
||
public HttpHeaders makeAuthorizationBearerTokenHeader(String token){ | ||
HttpHeaders headers = new HttpHeaders(); | ||
|
||
if(token == null || token.isEmpty() || token.isBlank()){ | ||
throw new AuthException(AuthErrorCode.INVALID_TOKEN); | ||
} | ||
|
||
headers.set("Authorization", "Bearer " + token); | ||
|
||
return headers; | ||
} | ||
} |
Oops, something went wrong.