Skip to content

Commit

Permalink
Merge pull request #36 from Troth-Cam/feat/google-login
Browse files Browse the repository at this point in the history
Feat/google login
  • Loading branch information
hojeong2747 authored Jul 12, 2023
2 parents c5d0692 + b479bb7 commit 2ab58e1
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public String getEmailFromToken(String identityToken) {

Claims claims = appleJwtParser.parsePublicKeyAndGetClaims(identityToken, publicKey);
log.info("claims : " + claims.toString());
validateClaims(claims);
// validateClaims(claims);
return claims.get("email", String.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,14 @@ public BaseResponse<LoginResDto> regenerateAccessToken(@RequestBody @Validated R
}

// 구글 로그인
// 사용자 로그인 페이지 제공 단계 - url
@GetMapping(value="/auth/{socialLoginType}")
public void socialLoginType(@PathVariable(name="socialLoginType") String socialLoginType) throws IOException {
oauthService.request(socialLoginType);
}

// code -> accessToken 받아오기
// accessToken -> 사용자 정보 받아오기
@GetMapping(value="/auth/{socialLoginType}/callback")
public void callback(
@PathVariable(name="socialLoginType") String socialLoginType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
@NoArgsConstructor
@Getter
public class GoogleOauthToken {
// 응답 객체가 JSON 형식으로 되어 있으므로, 이를 deserialization 해서 자바 객체에 담음
// -> 여기서 자바 객체에 해당하는 클래스
private String access_token;
private int expires_in;
private String scope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
@NoArgsConstructor
@Getter
public class GoogleUser {
// 다시 JSON 형식의 응답 객체를 deserialization 해서 자바 객체에 담음
// -> 여기서 자바 객체에 해당하는 클래스
private String id;
private String email;
private Boolean verified_email;
Expand Down
41 changes: 21 additions & 20 deletions src/main/java/trothly/trothcam/service/JwtService.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,27 +94,28 @@ public Boolean validateToken(String token) {
}
}

// public Boolean validateRefreshToken(String token) {
// try {
// Jws<Claims> claims = Jwts.parser()
// .setSigningKey(Base64.getEncoder().encodeToString(("" + JWT_SECRET).getBytes(
// StandardCharsets.UTF_8))).parseClaimsJws(token);
// if (claims.getBody().getExpiration().before(new Date())) {
// throw new UnauthorizedException("만료된 토큰입니다.");
// }
//
// // 유저 리프레쉬 토큰 확인
// Long memberId = getMemberIdFromJwtToken(token);
public Boolean validateRefreshToken(String token) {
try {
Jws<Claims> claims = Jwts.parser()
.setSigningKey(Base64.getEncoder().encodeToString(("" + JWT_SECRET).getBytes(
StandardCharsets.UTF_8))).parseClaimsJws(token);
if (claims.getBody().getExpiration().before(new Date())) {
throw new UnauthorizedException("만료된 토큰입니다.");
}

// 유저 리프레쉬 토큰 확인
Long memberId = getMemberIdFromJwtToken(token);
String redisRefreshToken = memberRepository.findById(memberId).get().getRefreshToken();
// String redisRefreshToken = redisTemplate.opsForValue().get(memberId.toString());
//
// if(redisRefreshToken.equals(token)){
// return true;
// }
// return false;
// } catch (Exception e) {
// throw new UnauthorizedException("만료된 토큰입니다.");
// }
// }

if(redisRefreshToken.equals(token)){
return true;
}
return false;
} catch (Exception e) {
throw new UnauthorizedException("만료된 토큰입니다.");
}
}

// Header X-ACCESS-TOKEN으로 JWT 추출
public String getToken(HttpServletRequest request) {
Expand Down
17 changes: 11 additions & 6 deletions src/main/java/trothly/trothcam/service/auth/GoogleOauth.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,17 @@ public class GoogleOauth {

private final ObjectMapper objectMapper;


// 사용자 로그인 페이지 제공 단계 - url 생성
public String getOauthRedirectURL() {
String reqUrl = GOOGLE_LOGIN_URL + "?client_id=" + GOOGLE_SNS_CLIENT_ID + "&redirect_uri=" + GOOGLE_SNS_CALLBACK_URL
+ "&response_type=code&scope=email%20profile%20openid&access_type=offline";
return reqUrl;
}


// 구글로 일회성 코드를 보내 액세스 토큰이 담긴 응답객체를 받아옴
public ResponseEntity<String> requestAccessToken(String code) {

// RestTemplate : 스프링에서 제공하는 http 통신에 유용하게 쓸 수 있는 템플릿
RestTemplate restTemplate = new RestTemplate();

Map<String, Object> params = new HashMap<>();
Expand All @@ -58,6 +59,7 @@ public ResponseEntity<String> requestAccessToken(String code) {
params.put("redirect_uri", GOOGLE_SNS_CALLBACK_URL);
params.put("grant_type", "authorization_code");

// RestTemplate 주요 메서드 postForEntity : POST 요청을 보내고 결과로 ResponseEntity 로 반환
ResponseEntity<String> responseEntity =
restTemplate.postForEntity(GOOGLE_SNS_TOKEN_BASE_URL, params, String.class);

Expand All @@ -67,20 +69,22 @@ public ResponseEntity<String> requestAccessToken(String code) {
return null;
}

// 응답 객체가 JSON 형식으로 되어 있으므로, 이를 deserialization 해서 자바 객체에 담음
public GoogleOauthToken getAccessToken(ResponseEntity<String> response) throws JsonProcessingException {
log.info("response.getBody() = " + response.getBody());
GoogleOauthToken googleOauthToken= objectMapper.readValue(response.getBody(),GoogleOauthToken.class);
GoogleOauthToken googleOauthToken = objectMapper.readValue(response.getBody(), GoogleOauthToken.class);
return googleOauthToken;
}

// 액세스 토큰을 다시 구글로 보내 구글에 저장된 사용자 정보가 담긴 응답 객체를 받아옴
public ResponseEntity<String> requestUserInfo(GoogleOauthToken oAuthToken) {

RestTemplate restTemplate = new RestTemplate();
//header에 accessToken을 담는다.
// header 에 accessToken 을 담는다.
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization","Bearer "+oAuthToken.getAccess_token());

//HttpEntity를 하나 생성해 헤더를 담아서 restTemplate으로 구글과 통신하게 된다.
// HttpEntity 를 하나 생성해, 헤더를 담아서 restTemplate 으로 구글과 통신하게 된다.
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity(headers);
ResponseEntity<String> response = restTemplate.exchange(GOOGLE_SNS_USERINFO_URL, HttpMethod.GET,request,String.class);
log.info("response.getHeaders() = " + response.getHeaders());
Expand All @@ -89,9 +93,10 @@ public ResponseEntity<String> requestUserInfo(GoogleOauthToken oAuthToken) {
return response;
}

// 다시 JSON 형식의 응답 객체를 deserialization 해서 자바 객체에 담음
public GoogleUser getUserInfo(ResponseEntity<String> userInfoResponse) throws JsonProcessingException {
log.info("response.getBody() = "+userInfoResponse.getBody());
GoogleUser googleUser =objectMapper.readValue(userInfoResponse.getBody(), GoogleUser.class);
GoogleUser googleUser = objectMapper.readValue(userInfoResponse.getBody(), GoogleUser.class);
return googleUser;
}
}
15 changes: 9 additions & 6 deletions src/main/java/trothly/trothcam/service/auth/OAuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class OAuthService {
public LoginResDto appleLogin(LoginReqDto loginReqDto) throws BaseException {
// identity token으로 email값 얻어오기
String email = appleOAuthUserProvider.getEmailFromToken(loginReqDto.getIdToken());
log.info(email);

// email이 null인 경우 : email 동의 안한 경우
if(email == null)
Expand Down Expand Up @@ -105,24 +106,26 @@ public LoginResDto regenerateAccessToken(RefreshTokenReqDto refreshTokenReqDto)
}

// 구글 로그인
//1. request
// 사용자 로그인 페이지 제공 단계 - url 반환
public void request(String socialLoginType) throws IOException {
String redirectURL = googleOauth.getOauthRedirectURL();

response.sendRedirect(redirectURL);
}

// code -> accessToken 받아오기
// accessToken -> 사용자 정보 받아오기
public void oauthLogin(String socialLoginType, String code) throws JsonProcessingException {
//(1)구글로 일회성 코드를 보내 액세스 토큰이 담긴 응답객체를 받아옴
// 구글로 일회성 코드를 보내 액세스 토큰이 담긴 응답객체를 받아옴
ResponseEntity<String> accessTokenResponse = googleOauth.requestAccessToken(code);

//응답 객체가 JSON형식으로 되어 있으므로, 이를 deserialization해서 자바 객체에 담을 것이다.
// 응답 객체가 JSON 형식으로 되어 있으므로, 이를 deserialization 해서 자바 객체에 담음 (+ 로그 출력됨)
GoogleOauthToken oAuthToken = googleOauth.getAccessToken(accessTokenResponse);

//액세스 토큰을 다시 구글로 보내 구글에 저장된 사용자 정보가 담긴 응답 객체를 받아온다.
// 액세스 토큰을 다시 구글로 보내 구글에 저장된 사용자 정보가 담긴 응답 객체를 받아옴
ResponseEntity<String> userInfoResponse = googleOauth.requestUserInfo(oAuthToken);
//다시 JSON 형식의 응답 객체를 자바 객체로 역직렬화한다.
GoogleUser googleUser = googleOauth.getUserInfo(userInfoResponse);

// 다시 JSON 형식의 응답 객체를 deserialization 해서 자바 객체에 담음
GoogleUser googleUser = googleOauth.getUserInfo(userInfoResponse);
}
}

0 comments on commit 2ab58e1

Please sign in to comment.