지난 시간에 이어서 Goolge OAuth 2.0을 web application에 적용하는 방법을 알아보겠습니다. 전체적인 단계는 아래의
순서로 살펴보겠습니다.
- Create user authorization credentials
- web application에 적용해서 Login / Logout 구현하기
- Token 전송 및 Google API 호출 / 사용하기
현재까지 진행된 단계를 살펴보면, Create user authorization credentials을 수행하였고 web application에서 Google OAuth로 Login 단계를 진행하여 해당 web application에서 개별 사용자의 접근 정보를 사용할 수 있도록 승인하는 부분까지 구현이 되었습니다.
이를 통해서, Google에 개인 profile정보를 바로 받아와서 표출할 수 있었습니다. 이 부분까지 진해이 되었다면 web application의 Back-End의 접근을 위해서 다음 절차를 진행해야 합니다. 우선 전체적인 Google OAuth에 대한 인증 절차에 대해서 간단히 살펴보겠습니다.
그림처럼 동작을 하는데... 하나하나 단계적으로 서술해보면 아래와 같습니다.
- web application에 접속한 사용자가 화면에서 보이는 "Sign in with Google" 버튼을 클릭합니다.
- 해당 버튼은 Google에서 제공하는 child window를 띄우는데, 혹시 Google로그인이 안되어 있다면 로그인 창을 띄워주고... 로그인이 되어있을 경우에서 해당 web application에서 인증권한을 사용하기 위한 OAuth창을 띄워줍니다.
- 사용자는 해당 내용을 확인하여 승인을 합니다.
- Google은 승인의 결과로 해당 사용자의 BasicProfile과 ID Token을 web application에 전송해 줍니다.
- 이제 Front-End단 에서의 인증은 끝났습니다. Google에서부터 전달받은 ID Token으로 Back-End에 서비스 제공을 요청하게 됩니다.
- Back-End에서는 전달받은 ID Token에 대해서 검증을 해야합니다. 이를 위해서, Google에 검증요청을 합니다.
- 검증이 완료되면, Google을 통해서 결과 및 PayLoad... 즉 사용자의 정보를 받아옵니다.
- 이제 완벽하게 검증된 사용자로 인식이 되었고, Back-End에서는 application의 자체 Token을 발행하여 사용자에게 전달합니다.
- 향후, 사용자의 요청은 이 App Token을 통해서 서비스가 진행되게 됩니다.
기존에 1 ~ 4번까지는 구현이 완료되었습니다. 이제 차근차근 이후 순번에 대해서 구현해 보겠습니다.
1. ID Token의 Back-End 전송
SPA로 구현한 web application에서 Google 로그인을 사용하는 경우 서버에서 현재 로그인 한 사용자를 식별해야 할 수 있습니다. 이렇게하려면 사용자가 성공적으로 로그인 한 후 HTTPS를 사용하여 사용자의 ID 토큰을 서버로 보냅니다. 그런 다음 서버에서 ID 토큰의 무결성을 확인하고 토큰에 포함 된 사용자 정보를 사용하여 세션을 설정하거나 새 계정을 만드는 절차로 진행되게 됩니다.
따라서, Google OAuth 2.0 을 통해서 가져온 id token을 Back-End로 보내는 방법에 대해서 알아보겠습니다. 세부적인 방법은 Google Developers에서 가이드 하는 내용을 따라서 구핸해 보겠습니다. 가이드는 https post로 request하는 방식을 권고합니다. 현재는 Back-End가 http이기 때문에 추후에 https를 적용해보도록 하겠습니다. 가이드의 일환으로 Content-Type을 'application/x-www-form-urlencoded'로 하여 id token을 보내겠습니다.
적용을 위한 세부내용은 아래의 이전글을 참조해주세요~
2021.04.08 - [SpringBoot] - [Spring Boot] 28. REST API (4) - POST method 와 Content-Type
실제 적용된 코드는 아래와 같습니다.
[Controller]
@RequestMapping(value = "tokenVerify", method = RequestMethod.POST)
public ResponseEntity<?> tokenVerify(String idToken){
System.out.println("RequestBody value : " + idToken);
return null;
}
[axios]
tokenVerify() {
const url = '/tokenVerify';
const params = new URLSearchParams();
params.append('idToken', this.idToken);
axios.post(url, params).then((res) => {
// eslint-disable-next-line
console.log(res);
}).catch((error) => {
// eslint-disable-next-line
console.log(error);
}).then(() => {
// eslint-disable-next-line
console.log('tokenVerify End!!');
});
},
[결과]
idToken : 14138744xxx.....xxxsbg91fmj3.apps.googleusercontent.com
2. Back-End에서 받은 id token의 무결성 확인
위에서 구현한 Rest API를 통해서 id token을 받아왔다면, 반드시 무결성확인 절차를 거쳐야 합니다. 무결성 확인을 위해서는 아래의 값들을 검사하게 되는데,
- ID Token이 Google을 통해 발행된 것이 맞는지 확인합니다.
- ID Token의 aud 값 : 이 값은 web application의 client ID중 하나의 값과 같습니다. 이를 확인하는 이유는 Back-End 서버에 임의로 발급한 ID Token으로 정상적인 사용자의 데이터에 접근하는 것을 방지하기 위함 입니다.
- ID Token의 iss 값 : accounts.google.com 이나 https://accounts.google.com과 같은지 확인합니다.
- ID Token의 exp 값 : ID Token의 만료시간으로 해당 토큰이 만료되었는지를 확인합니다.
이런 값들의 확인작업을 수행하기 위해서 Google API Client Libraries 를 통한 개발이 가능합니다. Spring Boot에서 id token의 무결성을 확인하려면, GoogleIdTokenVerifier를 사용하면 됩니다. 그럼 세부적인 코드를 알아보도록 하겠습니다.
[pom.xml 추가]
<!-- https://mvnrepository.com/artifact/com.google.api-client/google-api-client -->
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.31.2</version>
</dependency>
이를 사용하기 위한 Library를 Maven Repository를 통해서 확인하여 pom.xml에 dependency를 추가해 줍니다. 이제 실질적인 Service 구성을 진행해 보겠습니다.
[Service 구성]
private final NetHttpTransport transport = new NetHttpTransport();
private final JsonFactory jsonFactory = new GsonFactory();
public int tokenVerify(String idToken) {
System.out.println("idToken : " + clientId);
GoogleIdTokenVerifier gitVerifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
.setIssuers(Arrays.asList("https://accounts.google.com", "accounts.google.com"))
.setAudience(Collections.singletonList(clientId))
.build();
GoogleIdToken git = null;
try {
git = gitVerifier.verify(idToken);
} catch (GeneralSecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (git == null) {
System.out.println("Google ID Token is invalid");
}else {
Payload payload = git.getPayload();
// Print user identifier & Get profile information from payload
String userId = payload.getSubject();
System.out.println("User ID: " + userId);
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
System.out.println("email: " + email);
System.out.println("name: " + name);
System.out.println("locale: " + locale);
}
return 0;
}
GoogleIdTokenVerifier.verify( )를 통해서 Front-End에서 전달받은 ID Token을 parameter에 넣고 수행하면, 위에서 언급한 Google 서명, aud, iss, exp를 모두 확인한 결과를 리턴받고, 해당 결과의 PayLoad( )를 통해서 결과를 get할 수 있습니다.
[결과]
User ID: 1095913456456456569372
email: ayoteralab@gmail.com (가칭입니다.)
name: AyoteraLab
locale: ko
이렇게 5 ~ 7에 대한 구현이 완료되었습니다. 이제 사용자에 대해서 application의 자체 Token 발행 및 사용자 DB등록 후 서비스제공 등에 대한 부분에 대해서 알아보겠습니다.
- Ayotera Lab -
댓글