▤ 목차
이전글
2024.07.31 - [Backend/Spring] - Spring boot 3.x OAuth2(Google, Kakao) 로그인/회원가입 구현 - Flutter
로그인/회원가입 API
이번 글에서는 Flutter에서 호출하는 로그인 / 회원가입 API
를 살펴보겠습니다.
이전글을 보셨다면 아시겠지만 사용한 API는 한 개입니다!
API의 프로세스는 다음과 같습니다.
- Flutter에서 provider에 따라 로그인을 진행하고 accessToken을 spring 서버로 전달
- 서버에서 accessToken으로 사용자 정보 요청
- 여기에서 만약 accessToken이 변형되었다면 사용자 정보를 못가져오고 실패하게 됨
- 사용자 정보가 성공적으로 조회되면 해당 사용자 데이터가 DB에 저장되어있는지 확인
- DB에 없을 경우 사용자 생성
- 토큰 발급 후 응답 보냄
위와 같은 로직으로 구성 되어있습니다. 그러면 하나하나 살펴 보겠습니다
Controller
...
private final OAuthClient oAuthClient;
private final TokenCreate tokenCreate;
@PostMapping("/login/{provider}")
public ResponseEntity<TokenResponse> login(
@PathVariable("provider") SocialType type,
@RequestBody TokenRequest request
) {
OAuth2UserInfo oAuth2UserInfo = oAuthClient.getOAuth2UserInfo(type, request.code());
TokenResponse response = tokenCreate.getOAuthAccessTokenByUserInfo(type,
oAuth2UserInfo);
return ResponseEntity.ok().body(response);
}
...
API의 전체적인 구조 입니다. TokenRequest
에는 accessToken이 들어가 있고 oAuthClient.getAuth2UserInfo
메소드로 소셜 타입별 사용자 정보를 가져오게 됩니다.
OAuthClient
는 소셜 로그인에서 다른 서버와의 연동을 위한 컴포넌트입니다.
TokenCreate
는 토큰을 생성하는 기능이 담긴 컴포넌트입니다.
accessToken으로 사용자 정보 요청
@Component
@RequiredArgsConstructor
public class OAuthClient {
private final WebClient webClient;
@Value("${spring.security.oauth2.client.provider.google.user-info-uri}")
private String googleUserUrl;
@Value("${spring.security.oauth2.client.provider.kakao.user-info-uri}")
private String KAKAO_USER_URL;
}
OAuthClient
에서 사용자 정보를 가져오는건 WebClient
를 사용했고 각 provider별 document에 있는 사용자 조회 API를 사용해야합니다.
- google은 spring boot에 기본값으로 들어가 있습니다.
...
private JsonNode getUserInfo(String url, String token) {
Mono<JsonNode> response = webClient.get()
.uri(url)
.header("Authorization", "Bearer " + token)
.retrieve()
.bodyToMono(JsonNode.class);
return response.block();
}
...
token에 accessToken을 넣어서 요청하면 유효할 경우 사용자 정보를 가져올 수 있습니다. 가져온 사용자정보는 각 API 응답에따라 파싱해서 사용하면 됩니다.
DB 데이터 확인 & 토큰 발급
tokenCreate.getOAuthAccessTokenByUserInfo
메소드를 사용하면 토큰을 발급 할 수 있다.
...
// 사용자 조회
Optional<User> oUser = userManager.findByEmailAndSocialType(userInfo.getEmail(), type);
User user = oUser.orElseGet(() -> addUser(type, userInfo));
// refreshToken 초기화
String refreshToken = this.createRefreshToken();
this.updateRefreshToken(user,refreshToken);
// 토큰 발급
return new TokenResponse(
this.createAccessToken(user),
refreshToken,
user.getUserKey()
);
...
- accessToken으로 가져온 사용자 정보에 email을 기준으로 사용자 존재 유무를 판단합니다. 일단 이부분은 전화번호로도 바꿀수 있을 것 같아요. 그 후 사용자가 존재하지 않으면 새로 DB에 저장을 합니다.
- refreshToken도 초기화를 해주고 기존에 존재하던 refreshToken을 업데이트 합니다.
(로그아웃 후 다시 로그인을 하면 refreshToken 유효 기간이 늘어납니다) - 그 후 해당 사용자로 토큰을 만들고 응답으로 내보냅니다.
처음 로그인 및 회원가입 기능을 개발해 봤는데 로그인 방식이나 회원가입 방식이 다양해서 그 방법을 고민하느라 시간이 좀 더 걸린거같네요ㅠㅠ...
이 방식이 맞는지는 모르겠지만 진행하면서 만약 취약점같은게 보이면 계속 적용해봐야할것 같습니다!
'Backend > Spring' 카테고리의 다른 글
Spring JPA Custom Id Generator 만들기 (0) | 2024.11.06 |
---|---|
Spring boot 3.x OAuth2(Google, Kakao) 로그인/회원가입 구현 1 - Flutter (1) | 2024.07.31 |
이커머스 서비스에서 동시성 문제 처리해보기 (0) | 2024.05.08 |
Spring Transactional Isolation (0) | 2023.01.04 |
Spring Transactional Propagation (0) | 2022.12.28 |