Skip to content

Commit

Permalink
feat: 엑세스 토큰으로 로그인하는 api 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
yujung7768903 committed Jan 3, 2024
1 parent 1a904f4 commit 540f969
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ public CustomResponseEntity<UserLoginResponse> loginByOAuth(
return CustomResponseEntity.success(userService.loginByOAuth(code, platform));
}

// 소셜 로그인 API
@GetMapping("/signin/token")
public CustomResponseEntity<UserLoginResponse> socialLoginByAccessToken(
@RequestParam(name = "token") String token, @RequestParam Platform platform
) {
return CustomResponseEntity.success(userService.loginByAccessToken(token, platform));
}

// 엑세스 토큰 재발급
@GetMapping("/refresh")
public CustomResponseEntity<UserReissueResponse> refreshAccessToken(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ public Users toEntityUser(String code, Platform platform) {
.build();
}

@Override
public Users toEntityUserByToken(String accessToken) {
GoogleUserResponse profile = getGoogleUser(accessToken);

return Users.builder()
.email(profile.getEmail())
.name(profile.getName())
.build();
}

// Google AccessToken 반환
private String getGoogleAccessToken(String decodedCode) {
return toRequestGoogleToken(decodedCode).getAccessToken();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ public Users toEntityUser(String code, Platform platform) {
.build();
}

@Override
public Users toEntityUserByToken(String accessToken) {
KakaoUserResponse profile = getKakaoUser(accessToken);

return Users.builder()
.email(profile.getKakaoAccount().getEmail())
.name(profile.getProperties().getNickname())
.build();
}

// Kakao AccessToken 응답
private String getKakaoAccessToken(String code) {
HttpEntity<?> httpEntity = createHttpEntityWithCode(code);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ public Users toEntityUser(String code, Platform platform) {
.build();
}

@Override
public Users toEntityUserByToken(String accessToken) {
NaverUserResponse.NaverUserDetail profile = getNaverUser(accessToken);

return Users.builder()
.email(profile.getEmail())
.name(profile.getName())
.build();
}

// Naver AccessToken 응답
private String getNaverAccessToken(String code) {
NaverTokenResponse response = toRequestTokenNaverAccessToken(code);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ public interface OAuth2LoginService {
Platform supports();

Users toEntityUser(String code, Platform platform);

Users toEntityUserByToken(String accessToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,22 @@ public UserLoginResponse loginByOAuth(String code, Platform platform) {
return UserLoginResponse.response(user, accessToken, refreshToken);
}

// 소셜 로그인
@Transactional
public UserLoginResponse loginByAccessToken(String token, Platform platform) {
// 요청된 로그인 플랫폼 확인 후 소셜 로그인 진행
Users userEntity = oauthLoginProcessByToken(token, platform);

// 현재 서비스 내 회원인지 검증 및 save
Users user = saveOrUpdate(userEntity);

// 서비스 JWT 토큰 발급
String accessToken = jwtService.createAccessToken(user.getEmail());
String refreshToken = jwtService.createRefreshToken(user.getEmail());

return UserLoginResponse.response(user, accessToken, refreshToken);
}

public UserReissueResponse reissueAccessToken(String refreshToken) {
return UserReissueResponse.toResponse(jwtService.reissueAccessToken(refreshToken));
}
Expand All @@ -61,6 +77,12 @@ private Users oauthLoginProcess(String code, Platform platform) {
.orElseThrow(() -> new CustomException(FAIL_SOCIAL_LOGIN));
}

// method
private Users oauthLoginProcessByToken(String token, Platform platform) {
return getOptionalSocialUserEntityByToken(token, platform)
.orElseThrow(() -> new CustomException(FAIL_SOCIAL_LOGIN));
}

private Optional<Users> getOptionalSocialUserEntity(String code, Platform platform) {
for (OAuth2LoginService oAuth2LoginService : oAuth2LoginServices) {
if (oAuth2LoginService.supports().equals(platform)) {
Expand All @@ -70,6 +92,15 @@ private Optional<Users> getOptionalSocialUserEntity(String code, Platform platfo
return Optional.empty();
}

private Optional<Users> getOptionalSocialUserEntityByToken(String accessToken, Platform platform) {
for (OAuth2LoginService oAuth2LoginService : oAuth2LoginServices) {
if (oAuth2LoginService.supports().equals(platform)) {
return Optional.of(oAuth2LoginService.toEntityUserByToken(accessToken));
}
}
return Optional.empty();
}

private Users saveOrUpdate(Users userEntity) {
Users user = userRepository.findByEmail(userEntity.getEmail())
.map(entity -> entity.update(userEntity.getName()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
public class UserControllerDocsTest extends RestDocsSupport {

private final UserService userService = mock(UserService.class);
private final String code = "Hx-PXmWuFaGakYCEy8hkUIVOWUSXIOtD7cosKDSIKsiwodR1g35KXQQWX9H4hXlcpZ45eSgo3dGkWWWOSX-z9iQ";
private final String accessToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ5dS1qdW5nMzE0NzZAbmF2ZXIuY29tIiwiZXhwIjoxNjg5MjYwODM2fQ.cgZ8eFDU_Gz7Z3EghXxoa3v-iXUeQmBZ1AfKCBQZnnqFJ6mqMqGdiTS5uVCF1lIKBarXeD6nEmRZj9Ng94pnHw";
private final String refreshToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ5dS1qdW5nMzE0NzZAbmF2ZXIuY29tIiwiZXhwIjoxNjg5MjYwODM2fQ.cgZ8eFDU_Gz7Z3EghXxoa3v-iXUeQmBZ1AfKCBQZnnqFJ6mqMqGdiTS5uVCF1lIKBarXeD6nEmRZj9Ng94pnHw";

Expand All @@ -40,7 +41,7 @@ protected Object initController() {
@Test
void loginByOAuth() throws Exception {
// given
given(userService.loginByOAuth("Hx-PXmWuFaGakYCEy8hkUIVOWUSXIOtD7cosKDSIKsiwodR1g35KXQQWX9H4hXlcpZ45eSgo3dGkWWWOSX-z9iQ", NAVER))
given(userService.loginByOAuth(code, NAVER))
.willReturn(
UserLoginResponse.builder()
.userId(1L)
Expand Down Expand Up @@ -81,6 +82,51 @@ void loginByOAuth() throws Exception {
.andDo(document);
}

@DisplayName("소셜 로그인 API")
@Test
void socialLoginByAccessToken() throws Exception {
// given
given(userService.loginByAccessToken(accessToken, NAVER))
.willReturn(
UserLoginResponse.builder()
.userId(1L)
.email("[email protected]")
.name("모이닷")
.accessToken(accessToken)
.refreshToken(refreshToken)
.build()
);

MockHttpServletRequestBuilder httpRequest = RestDocumentationRequestBuilders.get("/auth/signin/token")
.param("token", accessToken)
.param("platform", "NAVER");

ResourceSnippetParameters parameters = ResourceSnippetParameters.builder()
.tag("유저 API")
.summary("소셜 로그인 API")
.queryParameters(
parameterWithName("token").description("소셜 로그인 redirect 엑세스 코드"),
parameterWithName("platform").description("플랫폼 : 'NAVER' / 'KAKAO' / 'GOOGLE' "))
.responseFields(
fieldWithPath("code").type(NUMBER).description("상태 코드"),
fieldWithPath("message").type(STRING).description("상태 메세지"),
fieldWithPath("data.userId").type(NUMBER).description("유저 아이디"),
fieldWithPath("data.email").type(STRING).description("유저 이메일"),
fieldWithPath("data.name").type(STRING).description("유저 이름"),
fieldWithPath("data.accessToken").type(STRING).description("엑세스 토큰"),
fieldWithPath("data.refreshToken").type(STRING).description("리프레쉬 토큰"))
.build();

RestDocumentationResultHandler document =
documentHandler("social-login-by-access-token", prettyPrint(), parameters);

// when // then
mockMvc.perform(httpRequest)
.andDo(print())
.andExpect(status().isOk())
.andDo(document);
}

@DisplayName("엑세스 토큰 재발급")
@Test
void reissueAccessToken() throws Exception {
Expand Down

0 comments on commit 540f969

Please sign in to comment.