Rest API 서버에서 OAuth2.0을 사용하여 소셜 로그인을 구현해야 했습니다.
프론트는 리액트를 사용했기에 SPA방식을 고려해야 했습니다.
보통 아래와 같은 흐름으로 구현이 됩니다.
그림상으로는 1~3번 까지는 SPA에서 처리한다음 4번에서 code와 redirect_url을 반환합니다.
현재 진행하는 프로젝트에서는 5번의 access_token과 id_token값까지 프론트에서 받은 다음,
access_token을 백엔드 서버에 제공하여 소셜 정보를 받는 과정으로 변경하였습니다.
구글 소셜 로그인 API를 구현하는 방식은 아래 블로그에 잘 설명되어 있습니다. (accessToken 값을 제공받는 과정까지 있습니다.)
💡 API GET 요청으로 구글 유저 정보 얻는 방법
제공받은 토큰값을 이용하여 아래와 같은 URL 형식으로 제공하면 손쉽게 유저정보를 얻을 수 있습니다.
https://www.googleapis.com/oauth2/v2/userinfo/?access_token="{소셜에서 제공받은 토큰값}"
하지만 API 요청을 하지않는 방법을 찾아서 적용한다면, 속도가 올라가지 않을까란 생각에 다른 방법을 찾게 되었습니다. 하지만... (아래에서 계속)
※ API GET요청을 쓴다해도 속도차이가 나지않는 구성 방법이 있다고 합니다. 자세한건, 아래 링크의 위에서 두번째 답변을 참고하시면 될 것 같습니다. (저는 초짜로 봐도 잘 모르겠습니다.. ㅋㅋ)
https://stackoverflow.com/questions/39061310/validate-google-id-token
구글링 중 Google API 클라이언트 라이브러리에 있는 GoogleIdTokenVerifier를 사용하면 제공받은 토큰값을 이용해 유저정보를 얻을 수 있습니다. 아래 공식 문서를 베이스로 구글링하여 따라해보았습니다.
developers.google.com/identity/sign-in/android/backend-auth#calling-the-tokeninfo-endpoint
1. gradle에서 필요한 라이브러리를 가져옵니다.
dependencies {
implementation group: 'com.google.api-client', name: 'google-api-client-jackson2', version: '1.30.10'
...
compile 'com.google.api-client:google-api-client:1.31.2'
}
2. 코드를 작성합니다. (코드가 안전하지 않고 더럽습니다 ㅠㅠ 추후 보완하고 수정본을 올리도록 하겠습니다.)
@Override
public AuthDto.GoogleProfileRes userInfoGoogle(AccessTokenReq dto) {
HttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
.setAudience(Collections.singletonList(GOOGLE_SNS_CLIENT_ID))
//.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
.build();
String userId = null;
String email = null;
try {
GoogleIdToken idToken = verifier.verify(dto.getAccessToken());
GoogleIdToken.Payload payload = idToken.getPayload();
userId = payload.getSubject();
email = payload.getEmail();
} catch (GeneralSecurityException e) {
log.warn(e.getLocalizedMessage());
} catch (IOException e) {
log.warn(e.getLocalizedMessage());
}
return GoogleProfileRes.builder().id(userId).email(email).build();
}
- 처음에 GoogleIdTokenVerifier.Builder의 인자에 어떤값을 넣어야 되나 많은 고민을 했습니다.
- 아래 스택오버플로우에 저랑 똑같은 궁금증을 가진 개발자가 질문을 올린것이 있습니다.
- 이 답변에 따르면 사용자가 제공 한 전송으로 tokeninfo 엔드 포인트에 요청하고 JSONFactory를 사용하여 응답을 파싱 할 파서를 만드는 GoogleIdTokenVerifier를 반환한다고 합니다.
- HttpTransPort를 찾아보니 "HTTP 서버와의 통신을 위한 전송을 제공" 한다고 합니다. 결국 서버랑 통신은 하나봅니다. (저는 안하는줄 알았는데, 이런 바보같은 생각을 하다니...)
- 즉, 토큰값을 이용하여 서버에 요청을 한 다음, JSONFactory를 사용하여 건네받은 정보를 JSON 형식으로 파싱하는 것 같습니다.
3. 건네주는 페이로드의 키값은 아래와 같습니다. 필요한 정보들만 빼오면 됩니다. (고유한 id값은 위 코드의 getSubject()로 얻으 실 수 있습니다.)
적용한 프로젝트는 깃허브를 확인 해주세요.
참조
www.javatips.net/api/ASSISTmentsDirect-master/src/org/assistments/direct/SignInWithGoogle.java
www.javatips.net/api/com.google.api.client.googleapis.auth.oauth2.googleidtokenverifier
'Tech > Spring' 카테고리의 다른 글
Springboot + GCP Cloud Storage 연동(파일 업로드, 다운로드) (0) | 2021.03.22 |
---|---|
Spring Boot에서 Actuator 및 Spring Actuator Admin 설정 방법 (0) | 2021.03.21 |
Spring Boot Validation 순서 정하기 & 테스트 코드 (4) | 2021.03.15 |
SpringBoot에서 HttpOnly 쿠키방식을 이용한 refreshToken 발급 (0) | 2021.02.27 |
@Controller와 @RestController의 차이점 (2) | 2021.02.12 |