Skip to content

Commit

Permalink
[#91] Feat: 네이버 재갱신 & 탈퇴하기
Browse files Browse the repository at this point in the history
  • Loading branch information
mmihye committed Sep 21, 2024
1 parent ca3563c commit 9c6cc13
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,28 @@
import Journey.Together.global.common.CustomMultipartFile;
import Journey.Together.global.exception.ApplicationException;
import Journey.Together.global.exception.ErrorCode;
import Journey.Together.global.exception.ErrorResponse;
import Journey.Together.global.security.kakao.KakaoClient;
import Journey.Together.global.security.kakao.dto.KakaoProfile;
import Journey.Together.global.security.jwt.TokenProvider;
import Journey.Together.global.security.jwt.dto.TokenDto;
import Journey.Together.global.security.naver.dto.NaverDeleteResponse;
import Journey.Together.global.security.naver.dto.NaverProperties;
import Journey.Together.global.security.naver.dto.NaverTokenResponse;
import Journey.Together.global.security.naver.dto.NaverUserResponse;
import Journey.Together.global.util.S3Client;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand All @@ -42,6 +46,7 @@ public class AuthService {
private final TokenProvider tokenProvider;
private final MemberRepository memberRepository;
private final InterestRepository interestRepository;
private final NaverProperties naverProperties;
private final S3Client s3Client;

private final RestTemplate restTemplate = new RestTemplate();
Expand Down Expand Up @@ -95,7 +100,7 @@ public LoginRes signIn(String token, String type) throws IOException {
if (member == null) {
MultipartFile imageFile = convertUrlToMultipartFile(naverProfile.getProfile_image() != null ? naverProfile.getProfile_image() : null);
String uuid = s3Client.createFolder();
s3Client.upload(imageFile,uuid,"profile_"+uuid);
s3Client.upload(imageFile, uuid, "profile_" + uuid);

Member newMember = Member.builder()
.email(naverProfile.getEmail() != null ? naverProfile.getEmail() : "Unknown")
Expand All @@ -119,22 +124,10 @@ public LoginRes signIn(String token, String type) throws IOException {
}

tokenDto = tokenProvider.createToken(member);
member.setRefreshToken(tokenDto.refreshToken());

// member.setRefreshToken(tokenDto.refreshToken());
}
return LoginRes.of(member, tokenDto);
}
private NaverUserResponse.NaverUserDetail toRequestProfile(String accessToken) {
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(headers);

ResponseEntity<NaverUserResponse> response =
restTemplate.exchange("https://openapi.naver.com/v1/nid/me", HttpMethod.GET, request, NaverUserResponse.class);

return response.getBody().getNaverUserDetail();
}

@Transactional
public void signOut(String token, Member member) {
// Validation
Expand All @@ -153,9 +146,21 @@ public void withdrawal(Member member) {
// Validation

// Business Logic - 회원 논리적 삭제 진행
if(member.getLoginType().equals(LoginType.NAVER)) {
NaverTokenResponse tokenResponse = toRequestToken(member.getRefreshToken());
if(tokenResponse.getError() != null){
throw new ApplicationException(ErrorCode.NAVER_REFRESH_ERROR);
}
NaverDeleteResponse naverDeleteResponse = toRequestDelete(tokenResponse.getAccessToken());
if(naverDeleteResponse.getError() != null){
throw new ApplicationException(ErrorCode.NAVER_DELETE_ERROR);
}
}

memberRepository.delete(member);

// Response

}
@Transactional
public TokenDto reissue(String token, Member member) {
Expand All @@ -179,6 +184,54 @@ public TokenDto reissue(String token, Member member) {
return tokenDto;
}

private NaverUserResponse.NaverUserDetail toRequestProfile(String accessToken) {
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(headers);

ResponseEntity<NaverUserResponse> response =
restTemplate.exchange("https://openapi.naver.com/v1/nid/me", HttpMethod.GET, request, NaverUserResponse.class);

return response.getBody().getNaverUserDetail();
}

public NaverTokenResponse toRequestToken(String refreshToken) {
// URI 생성 (쿼리 파라미터 포함)
String tokenRequestUri = naverProperties.refreshTokenUri(refreshToken);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<String> request = new HttpEntity<>(headers);

// POST 요청 보내기
ResponseEntity<NaverTokenResponse> response = restTemplate.postForEntity(
tokenRequestUri,
request,
NaverTokenResponse.class
);

return response.getBody();
}

public NaverDeleteResponse toRequestDelete(String accessToken) {
// URI 생성 (쿼리 파라미터 포함)
String tokenRequestUri = naverProperties.delete(accessToken);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<String> request = new HttpEntity<>(headers);

// POST 요청 보내기
ResponseEntity<NaverDeleteResponse> response = restTemplate.postForEntity(
tokenRequestUri,
request,
NaverDeleteResponse.class
);

return response.getBody();
}



//url->multipartFile로 변환
private MultipartFile convertUrlToMultipartFile(String imageUrl) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ public enum ErrorCode {
ILLEGAL_POST_EXCEPTION(HttpStatus.BAD_REQUEST, 5004, "파트별 인원수가 전체 인원수와 일치하지 않습니다."),
NOT_ADD_IMAGE_EXCEPTION(HttpStatus.BAD_REQUEST,5005,"예상치 못한 에러가 발생하여 이미지 추가가 되지 않습니다."),
REVIEW_TYPE_EXCEPTION(HttpStatus.BAD_REQUEST,5006,"올바르지 않은 리뷰 타입입니다."),
NOT_FOUND_DESCRIPTION_EXCEPTION(HttpStatus.BAD_REQUEST,5007,"기타 사유 선택 시, 상세한 신고 사유는 필수입니다.");
NOT_FOUND_DESCRIPTION_EXCEPTION(HttpStatus.BAD_REQUEST,5007,"기타 사유 선택 시, 상세한 신고 사유는 필수입니다."),
NAVER_REFRESH_ERROR(HttpStatus.INTERNAL_SERVER_ERROR,5008,"네이버 토큰 재발급 에러."),
NAVER_DELETE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR,5009,"네이버 탈퇴 에러");

private final HttpStatus httpStatus;
private final Integer code;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package Journey.Together.global.security.naver.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class NaverDeleteResponse {
@JsonProperty("access_token")
private String accessToken;
@JsonProperty("result")
private String result;
@JsonProperty("error")
private String error;
@JsonProperty("error_description")
private String errorDescription;

}
Original file line number Diff line number Diff line change
@@ -1,24 +1,52 @@
package Journey.Together.global.security.naver.dto;

import lombok.Data;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.util.UriComponentsBuilder;

@Data
@Configuration
@Getter
@ConfigurationProperties(prefix = "naver")
public class NaverProperties {
private String requestTokenUri;
private String clientId;
private String clientSecret;

public String getRequestURL(String code) {
return UriComponentsBuilder.fromHttpUrl(requestTokenUri)
.queryParam("grant_type", "authorization_code")
.queryParam("client_id", clientId)
.queryParam("client_secret", clientSecret)
.queryParam("code", code)
@Value("${spring.security.oauth2.client.registration.naver.client-id}")
private String naverClientId;

@Value("${spring.security.oauth2.client.registration.naver.client-secret}")
private String naverClientSecret;

@Value("${spring.security.oauth2.client.registration.naver.authorization-grant-type}")
private String naverGrantType;

@Value("${spring.security.oauth2.client.registration.naver.redirect-uri}")
private String naverRedirectUri;

@Value("${spring.security.oauth2.client.provider.naver.token-uri}")
private String naverTokenUri;

@Value("${spring.security.oauth2.client.provider.naver.user-info-uri}")
private String naverUserInfoUri;

// 새로운 액세스 토큰을 요청하기 위한 URI 생성
public String refreshTokenUri(String refreshToken) {
return UriComponentsBuilder.fromHttpUrl("https://nid.naver.com/oauth2.0/token")
.queryParam("grant_type", "refresh_token")
.queryParam("client_id", naverClientId)
.queryParam("client_secret", naverClientSecret)
.queryParam("refresh_token", refreshToken)
.toUriString();
}
}

public String delete(String accessToken) {
return UriComponentsBuilder.fromHttpUrl("https://nid.naver.com/oauth2.0/token")
.queryParam("grant_type", "delete")
.queryParam("client_id", naverClientId)
.queryParam("client_secret", naverClientSecret)
.queryParam("access_token", accessToken)
.queryParam("service_provider", "NAVER")
.toUriString();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ public class NaverTokenResponse {
private String error;
@JsonProperty("error_description")
private String errorDescription;

}

0 comments on commit 9c6cc13

Please sign in to comment.