백엔드 서버와 통신하는 앱 또는 사이트에서 Google 로그인을 사용하는 경우 서버에 현재 로그인한 사용자를 식별해야 할 수 있습니다. 이를 위해 사용자가 정상적으로 로그인한 후에 HTTPS를 사용하여 사용자의 ID 토큰을 서버로 전송합니다. 그런 다음 서버에서 ID 토큰의 무결성을 확인하고 토큰에 포함된 사용자 정보를 사용하여 세션을 설정하거나 새 계정을 만듭니다.
서버로 ID 토큰 전송
먼저 사용자가 로그인하면 다음과 같이 ID 토큰을 가져옵니다.
-
Google 로그인을 구성할 때
requestIdToken
메서드를 호출하고 서버의 웹 클라이언트 ID를 전달합니다.// Request only the user's ID token, which can be used to identify the // user securely to your backend. This will contain the user's basic // profile (name, profile picture URL, etc) so you should not need to // make an additional call to personalize your application. GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(getString(R.string.server_client_id)) .requestEmail() .build();
-
앱이 시작되면
silentSignIn
를 호출하여 사용자가 이 기기 또는 다른 기기에서 Google을 통해 이미 앱에 로그인했는지 확인합니다.GoogleSignIn.silentSignIn() .addOnCompleteListener( this, new OnCompleteListener<GoogleSignInAccount>() { @Override public void onComplete(@NonNull Task<GoogleSignInAccount> task) { handleSignInResult(task); } });
-
사용자가 자동으로 로그인할 수 없는 경우 로그아웃 상태의 일반적인 환경을 표시하여 사용자에게 로그인 옵션을 제공합니다. 사용자가 로그인하면 로그인 인텐트의 활동 결과에서 사용자의
GoogleSignInAccount
를 가져옵니다.// This task is always completed immediately, there is no need to attach an // asynchronous listener. Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data); handleSignInResult(task);
-
사용자가 자동 또는 명시적으로 로그인한 후
GoogleSignInAccount
객체에서 ID 토큰을 가져옵니다.private void handleSignInResult(@NonNull Task<GoogleSignInAccount> completedTask) { try { GoogleSignInAccount account = completedTask.getResult(ApiException.class); String idToken = account.getIdToken(); // TODO(developer): send ID Token to server and validate updateUI(account); } catch (ApiException e) { Log.w(TAG, "handleSignInResult:error", e); updateUI(null); } }
그런 다음 HTTPS POST 요청을 사용하여 ID 토큰을 서버로 전송합니다.
HttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost("https://yourbackend.example.com/tokensignin"); try { List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); nameValuePairs.add(new BasicNameValuePair("idToken", idToken)); httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = httpClient.execute(httpPost); int statusCode = response.getStatusLine().getStatusCode(); final String responseBody = EntityUtils.toString(response.getEntity()); Log.i(TAG, "Signed in as: " + responseBody); } catch (ClientProtocolException e) { Log.e(TAG, "Error sending ID token to backend.", e); } catch (IOException e) { Log.e(TAG, "Error sending ID token to backend.", e); }
ID 토큰의 무결성 확인
HTTPS POST로 ID 토큰을 수신한 후에는 토큰의 무결성을 확인해야 합니다.
토큰이 유효한지 확인하려면 다음을 확인하세요. 다음 기준을 충족해야 합니다.
- Google에서 ID 토큰을 올바르게 서명했는지 확인합니다. Google의 공개 키 사용
(제공:
JWK 또는
PEM 형식)
토큰의 서명을 확인합니다 이러한 키는 정기적으로 순환됩니다. 검사하다
응답의
Cache-Control
헤더를 통해 다시 가져와야 합니다 - ID 토큰의
aud
값은 앱의 클라이언트 ID를 찾습니다. 이 검사는 악의적인 행위자에게 발급된 ID 토큰을 앱의 백엔드 서버에서 동일한 사용자에 대한 데이터에 액세스하는 데 사용되는 앱. - ID 토큰의
iss
값은 다음과 같습니다.accounts.google.com
또는https://accounts.google.com
입니다. - ID 토큰의 만료 시간 (
exp
)이 지나지 않았습니다. - ID 토큰이 Google Workspace 또는 Cloud를 나타내는지 확인해야 하는 경우
조직 계정에 대한
hd
클레임을 확인하면 사용자 도메인입니다. 리소스에 대한 액세스 권한을 특정 도메인을 사용하는 경우가 많습니다 이 소유권 주장이 없으면 계정이 다음에 속하지 않음을 나타냅니다. Google이 호스팅하는 도메인입니다.
email
, email_verified
, hd
필드를 사용하면
Google은 이메일 주소를 호스팅하고 이에 대한 권한이 있습니다. Google이 공신력 있는 경우
합법적인 계정 소유자로 알려진 경우 비밀번호나 기타 로그인 정보를 건너뛸 수
챌린지 방법.
Google이 신뢰할 수 있는 케이스:
email
의 접미사는@gmail.com
입니다. 이 계정은 Gmail 계정입니다.email_verified
이(가) true이고hd
이(가) 설정되어 있습니다. 이는 G Suite 계정입니다.
사용자는 Gmail 또는 G Suite를 사용하지 않고도 Google 계정에 등록할 수 있습니다. 날짜
email
에 @gmail.com
서픽스가 포함되어 있지 않고 hd
가 없는 경우 Google은 포함되지 않음
신뢰할 수 있는 비밀번호나 다른 본인 확인 방법을 사용하여
있습니다. Google에서 처음에 확인했으므로 email_verified
도 true일 수 있습니다.
사용자에게 양도할 수 있지만 제3자의 소유권은
이메일 계정이 변경되었을 수 있습니다.
이러한 확인 단계를 수행하기 위해 직접 코드를 작성하는 대신 Google에서는
플랫폼에 Google API 클라이언트 라이브러리를 사용하거나
JWT 라이브러리도 있습니다. 개발 및 디버깅을 위해 tokeninfo
를 호출할 수 있습니다.
엔드포인트가 있습니다
Google API 클라이언트 라이브러리 사용
Google API 클라이언트 라이브러리 중 하나 (예: 자바, Node.js PHP Python) 프로덕션 환경에서 Google ID 토큰의 유효성을 검사하는 데 권장되는 방법입니다.
<ph type="x-smartling-placeholder">Java에서 ID 토큰의 유효성을 검사하려면 GoogleIdTokenVerifier 객체에 대한 호출을 확인할 수 있습니다. 예를 들면 다음과 같습니다.
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; ... GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) // Specify the CLIENT_ID of the app that accesses the backend: .setAudience(Collections.singletonList(CLIENT_ID)) // Or, if multiple clients access the backend: //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3)) .build(); // (Receive idTokenString by HTTPS POST) GoogleIdToken idToken = verifier.verify(idTokenString); if (idToken != null) { Payload payload = idToken.getPayload(); // Print user identifier String userId = payload.getSubject(); System.out.println("User ID: " + userId); // Get profile information from payload 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"); // Use or store profile information // ... } else { System.out.println("Invalid ID token."); }
GoogleIdTokenVerifier.verify()
메서드가 JWT를 확인합니다.
서명, aud
클레임, iss
클레임 및
exp
소유권 주장.
ID 토큰이 Google Workspace 또는 Cloud를 나타내는지 확인해야 하는 경우
조직 계정의 경우 도메인 이름을 확인하여 hd
소유권 주장을 확인할 수 있습니다.
Payload.getHostedDomain()
메서드에서 반환됩니다.
소유권 주장 email
건이 계정을 도메인에서 관리하기에 충분하지 않습니다.
또는 조직이나 그 안에서 활용할 수 있습니다.
Node.js에서 ID 토큰을 검증하려면 Node.js용 Google 인증 라이브러리를 사용하세요. 라이브러리를 설치합니다.
npm install google-auth-library --save그런 다음
verifyIdToken()
함수를 호출합니다. 예를 들면 다음과 같습니다.
const {OAuth2Client} = require('google-auth-library'); const client = new OAuth2Client(); async function verify() { const ticket = await client.verifyIdToken({ idToken: token, audience: CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend // Or, if multiple clients access the backend: //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3] }); const payload = ticket.getPayload(); const userid = payload['sub']; // If the request specified a Google Workspace domain: // const domain = payload['hd']; } verify().catch(console.error);
verifyIdToken
함수는
JWT 서명, aud
클레임, exp
클레임
및 iss
클레임.
ID 토큰이 Google Workspace 또는 Cloud를 나타내는지 확인해야 하는 경우
조직 계정에 대한 hd
클레임을 확인하면
사용자 도메인입니다. 리소스에 대한 액세스 권한을 구성원으로만 제한할 때 사용해야 합니다.
특정 도메인의 사용자를
관리할 수 있습니다 이 소유권 주장이 없으면 계정이 다음 항목에 속하지 않음을 나타냅니다.
Google에서 호스팅하는
도메인일 수 있습니다
PHP에서 ID 토큰의 유효성을 검사하려면 PHP용 Google API 클라이언트 라이브러리를 사용합니다. 라이브러리를 설치합니다 (예: Composer 사용).
composer require google/apiclient그런 다음
verifyIdToken()
함수를 호출합니다. 예를 들면 다음과 같습니다.
require_once 'vendor/autoload.php'; // Get $id_token via HTTPS POST. $client = new Google_Client(['client_id' => $CLIENT_ID]); // Specify the CLIENT_ID of the app that accesses the backend $payload = $client->verifyIdToken($id_token); if ($payload) { $userid = $payload['sub']; // If the request specified a Google Workspace domain //$domain = $payload['hd']; } else { // Invalid ID token }
verifyIdToken
함수는
JWT 서명, aud
클레임, exp
클레임
및 iss
클레임.
ID 토큰이 Google Workspace 또는 Cloud를 나타내는지 확인해야 하는 경우
조직 계정에 대한 hd
클레임을 확인하면
사용자 도메인입니다. 리소스에 대한 액세스 권한을 구성원으로만 제한할 때 사용해야 합니다.
특정 도메인의 사용자를
관리할 수 있습니다 이 소유권 주장이 없으면 계정이 다음 항목에 속하지 않음을 나타냅니다.
Google에서 호스팅하는
도메인일 수 있습니다
Python에서 ID 토큰의 유효성을 검사하려면 verify_oauth2_token 함수를 사용하세요. 예를 들면 다음과 같습니다.
from google.oauth2 import id_token from google.auth.transport import requests # (Receive token by HTTPS POST) # ... try: # Specify the CLIENT_ID of the app that accesses the backend: idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID) # Or, if multiple clients access the backend server: # idinfo = id_token.verify_oauth2_token(token, requests.Request()) # if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]: # raise ValueError('Could not verify audience.') # If the request specified a Google Workspace domain # if idinfo['hd'] != DOMAIN_NAME: # raise ValueError('Wrong domain name.') # ID token is valid. Get the user's Google Account ID from the decoded token. userid = idinfo['sub'] except ValueError: # Invalid token pass
verify_oauth2_token
함수가 JWT 확인
서명, aud
클레임, exp
클레임
hd
도 확인해야 합니다.
배상 청구 (해당되는 경우)를
verify_oauth2_token
가 반환됩니다. 여러 클라이언트가
백엔드 서버에서 aud
클레임을 수동으로 확인합니다.
tokeninfo 엔드포인트 호출
디버깅을 위해 ID 토큰 서명을 검증하는 쉬운 방법은
tokeninfo
엔드포인트를 사용합니다. 이 엔드포인트를 호출할 때는
IP 주소를 제대로 테스트하면서 대부분의 유효성 검사를 자동으로 수행하는
페이로드 추출을 사용할 수 있습니다. 프로덕션에는 사용하기에 적합하지 않습니다.
요청이 제한되거나 간헐적인 오류가 발생할 수 있기 때문입니다.
tokeninfo
엔드포인트를 사용하여 ID 토큰을 검증하려면 HTTPS를 만드세요.
POST 또는 GET 요청을 전송하고
id_token
매개변수
예를 들어 토큰 'XYZ123'의 유효성을 검사하려면 다음 GET 요청을 실행합니다.
https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123
토큰이 올바르게 서명되었고 iss
및 exp
이
클레임이 예상값을 갖는 경우 HTTP 200 응답을 받게 됩니다. 여기서 본문은
에는 JSON 형식의 ID 토큰 클레임이 포함됩니다.
응답 예시는 다음과 같습니다.
{ // These six fields are included in all Google ID Tokens. "iss": "https://accounts.google.com", "sub": "110169484474386276334", "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "iat": "1433978353", "exp": "1433981953", // These seven fields are only included when the user has granted the "profile" and // "email" OAuth scopes to the application. "email": "testuser@gmail.com", "email_verified": "true", "name" : "Test User", "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg", "given_name": "Test", "family_name": "User", "locale": "en" }
ID 토큰이 Google Workspace 계정을 나타내는지 확인해야 하는 경우 다음을 확인할 수 있습니다.
사용자의 호스트 도메인을 나타내는 hd
클레임 다음과 같은 경우에 사용해야 합니다.
리소스에 대한 액세스 권한을 특정 도메인의 구성원으로만 제한 본 클레임의 부재
계정이 Google Workspace 호스팅 도메인에 속하지 않음을 나타냅니다.
계정 또는 세션 만들기
토큰을 확인한 후 사용자가 이미 사용자 데이터베이스에 있는지 확인합니다. 이 경우 사용자를 위해 인증된 세션을 설정합니다. 사용자가 아직 사용자 데이터베이스에 없는 경우 ID 토큰 페이로드의 정보로 새 사용자 레코드를 만들고 사용자를 위한 세션을 설정합니다. 앱에서 새로 생성된 사용자를 감지하면 사용자에게 필요한 추가 프로필 정보를 묻는 메시지를 표시할 수 있습니다.
계정 간 보안으로 사용자 계정 보호하기
Google을 통해 사용자 로그인을 요청하면 Google에서 사용자 데이터를 보호하기 위해 구축한 모든 보안 기능과 인프라를 자동으로 활용할 수 있습니다. 하지만 드물게 사용자의 Google 계정이 도용되거나 다른 중요한 보안 이벤트가 발생하는 경우 앱이 공격에 취약할 수도 있습니다. 주요 보안 이벤트로부터 계정을 더 안전하게 보호하려면 교차 계정 보호를 사용하여 Google에서 보안 알림을 받으세요. 이러한 이벤트를 수신하면 사용자의 Google 계정 보안에 대한 중요 변경사항을 파악할 수 있으므로 서비스에서 계정을 보호하기 위한 조치를 취할 수 있습니다.