-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[Feature] 구글 소셜 로그인 API 구현
- Loading branch information
Showing
7 changed files
with
251 additions
and
1 deletion.
There are no files selected for viewing
45 changes: 45 additions & 0 deletions
45
src/main/java/com/gdsc/hearo/domain/oauth/controller/OauthController.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,45 @@ | ||
package com.gdsc.hearo.domain.oauth.controller; | ||
|
||
import com.gdsc.hearo.domain.member.dto.LoginResponseDto; | ||
import com.gdsc.hearo.domain.member.entity.Member; | ||
import com.gdsc.hearo.domain.oauth.dto.GoogleProfile; | ||
import com.gdsc.hearo.domain.oauth.service.OauthService; | ||
import com.gdsc.hearo.global.common.BaseException; | ||
import com.gdsc.hearo.global.common.BaseResponse; | ||
import com.gdsc.hearo.global.common.BaseResponseStatus; | ||
import com.gdsc.hearo.global.security.JwtUtil; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
@RestController | ||
@CrossOrigin | ||
@RequiredArgsConstructor | ||
@RequestMapping(value = "/auth") | ||
@Slf4j | ||
public class OauthController { | ||
|
||
private final OauthService oauthService; | ||
private final JwtUtil jwtUtil; | ||
|
||
@GetMapping(value = "/google") | ||
public void socialLoginType() { | ||
oauthService.request(); | ||
} | ||
@GetMapping(value = "/google/callback") | ||
public BaseResponse<?> googleLogin(@RequestParam(name = "code") String code) { | ||
|
||
try { | ||
GoogleProfile googleProfile = oauthService.requestGoogleProfile(code); | ||
Member member = oauthService.googleLogin(googleProfile); | ||
|
||
String accessToken = jwtUtil.createAccessToken(member.getLoginId()); | ||
String refreshToken = jwtUtil.createRefreshToken(member.getLoginId()); | ||
|
||
LoginResponseDto loginResponseDto = new LoginResponseDto(accessToken, refreshToken); | ||
return new BaseResponse<>(BaseResponseStatus.SUCCESS, loginResponseDto); | ||
} catch (BaseException e) { | ||
return new BaseResponse<>(e.getStatus()); | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/com/gdsc/hearo/domain/oauth/dto/GoogleOAuthToken.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,12 @@ | ||
package com.gdsc.hearo.domain.oauth.dto; | ||
|
||
import lombok.Data; | ||
|
||
@Data | ||
public class GoogleOAuthToken { | ||
private String access_token; | ||
private String expires_in; | ||
private String scope; | ||
private String token_type; | ||
private String id_token; | ||
} |
17 changes: 17 additions & 0 deletions
17
src/main/java/com/gdsc/hearo/domain/oauth/dto/GoogleProfile.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,17 @@ | ||
package com.gdsc.hearo.domain.oauth.dto; | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
import lombok.Data; | ||
|
||
@Data | ||
@JsonIgnoreProperties(ignoreUnknown=true) | ||
public class GoogleProfile { | ||
private String id; | ||
private String email; | ||
private String verified_email; | ||
private String name; | ||
private String given_name; | ||
private String family_name; | ||
private String picture; | ||
private String locale; | ||
} |
60 changes: 60 additions & 0 deletions
60
src/main/java/com/gdsc/hearo/domain/oauth/service/OauthService.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,60 @@ | ||
package com.gdsc.hearo.domain.oauth.service; | ||
|
||
import com.gdsc.hearo.domain.member.entity.Member; | ||
import com.gdsc.hearo.domain.member.repository.MemberRepository; | ||
import com.gdsc.hearo.domain.oauth.dto.GoogleOAuthToken; | ||
import com.gdsc.hearo.domain.oauth.dto.GoogleProfile; | ||
import com.gdsc.hearo.domain.oauth.service.social.GoogleOauth; | ||
import com.gdsc.hearo.global.common.BaseException; | ||
import com.gdsc.hearo.global.common.BaseResponseStatus; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.io.IOException; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class OauthService { | ||
|
||
private final GoogleOauth googleOauth; | ||
private final HttpServletResponse response; | ||
private final MemberRepository memberRepository; | ||
|
||
public void request() { | ||
String redirectURL = googleOauth.getOauthRedirectURL(); | ||
try { | ||
response.sendRedirect(redirectURL); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
|
||
|
||
public GoogleProfile requestGoogleProfile(String code) { | ||
GoogleOAuthToken googleOAuthToken = googleOauth.requestAccessToken(code); | ||
return googleOauth.requestGoogleProfile(googleOAuthToken); | ||
} | ||
|
||
public Member googleLogin(GoogleProfile googleProfile) throws BaseException { | ||
String email = googleProfile.getEmail(); | ||
String googleId = googleProfile.getId(); | ||
String username = googleProfile.getName(); | ||
|
||
Member member = memberRepository.findByLoginId(email); | ||
|
||
if (member != null) { | ||
throw new BaseException(BaseResponseStatus.DUPICATE_USER_ID); | ||
} | ||
Member newMember = Member.builder() | ||
.username(username) | ||
.loginId(email) | ||
.GoogleId(googleId) | ||
.loginType(Member.LoginType.GOOGLE) | ||
.build(); | ||
|
||
memberRepository.save(newMember); | ||
|
||
return newMember; | ||
} | ||
} |
106 changes: 106 additions & 0 deletions
106
src/main/java/com/gdsc/hearo/domain/oauth/service/social/GoogleOauth.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,106 @@ | ||
package com.gdsc.hearo.domain.oauth.service.social; | ||
|
||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.JsonMappingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.gdsc.hearo.domain.oauth.dto.GoogleOAuthToken; | ||
import com.gdsc.hearo.domain.oauth.dto.GoogleProfile; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.http.*; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.MultiValueMap; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class GoogleOauth { | ||
|
||
@Value("${spring.google.url}") | ||
private String GOOGLE_SNS_BASE_URL; | ||
@Value("${spring.google.client-id}") | ||
private String GOOGLE_SNS_CLIENT_ID; | ||
@Value("${spring.google.callback}") | ||
private String GOOGLE_SNS_CALLBACK_URL; | ||
@Value("${spring.google.secret}") | ||
private String GOOGLE_SNS_CLIENT_SECRET; | ||
@Value("${spring.google.token}") | ||
private String GOOGLE_SNS_TOKEN_BASE_URL; | ||
|
||
public String getOauthRedirectURL() { | ||
Map<String, Object> params = new HashMap<>(); | ||
params.put("scope", "profile email"); | ||
params.put("response_type", "code"); | ||
params.put("client_id", GOOGLE_SNS_CLIENT_ID); | ||
params.put("redirect_uri", GOOGLE_SNS_CALLBACK_URL); | ||
|
||
String parameterString = params.entrySet().stream() | ||
.map(x -> x.getKey() + "=" + x.getValue()) | ||
.collect(Collectors.joining("&")); | ||
|
||
return GOOGLE_SNS_BASE_URL + "?" + parameterString; | ||
} | ||
|
||
public GoogleOAuthToken requestAccessToken(String code) { | ||
RestTemplate restTemplate = new RestTemplate(); | ||
ObjectMapper objectMapper = new ObjectMapper(); | ||
GoogleOAuthToken oAuthToken = null; | ||
|
||
Map<String, Object> params = new HashMap<>(); | ||
params.put("code", code); | ||
params.put("client_id", GOOGLE_SNS_CLIENT_ID); | ||
params.put("client_secret", GOOGLE_SNS_CLIENT_SECRET); | ||
params.put("redirect_uri", GOOGLE_SNS_CALLBACK_URL); | ||
params.put("grant_type", "authorization_code"); | ||
|
||
ResponseEntity<String> response = | ||
restTemplate.postForEntity(GOOGLE_SNS_TOKEN_BASE_URL, params, String.class); | ||
|
||
try { | ||
oAuthToken = objectMapper.readValue(response.getBody(), GoogleOAuthToken.class); | ||
} catch (JsonMappingException e) { | ||
throw new RuntimeException(e); | ||
} catch (JsonProcessingException e) { | ||
throw new RuntimeException(e); | ||
} | ||
|
||
return oAuthToken; | ||
} | ||
|
||
public GoogleProfile requestGoogleProfile(GoogleOAuthToken oAuthToken) { | ||
|
||
RestTemplate restTemplate = new RestTemplate(); | ||
ObjectMapper objectMapper = new ObjectMapper(); | ||
|
||
HttpHeaders header = new HttpHeaders(); | ||
header.add("Authorization", "Bearer " + oAuthToken.getAccess_token()); | ||
|
||
HttpEntity<MultiValueMap<String, String>> googleProfileRequest = new HttpEntity<>(header); | ||
|
||
ResponseEntity<String> googleProfileResponse = restTemplate.exchange( | ||
"https://www.googleapis.com/oauth2/v2/userinfo", | ||
HttpMethod.GET, | ||
googleProfileRequest, | ||
String.class | ||
); | ||
|
||
GoogleProfile googleProfile = null; | ||
|
||
try { | ||
googleProfile = objectMapper.readValue(googleProfileResponse.getBody(), GoogleProfile.class); | ||
} catch (JsonMappingException e) { | ||
e.printStackTrace(); | ||
} catch (JsonProcessingException e) { | ||
e.printStackTrace(); | ||
} | ||
|
||
return googleProfile; | ||
} | ||
} |
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