ID 토큰을 사용하여 백엔드로 인증

원탭 로그인 클라이언트는 사용자가 Google 계정을 탭합니다. ID 토큰은 사용자 ID에 대한 서명된 어설션으로, 사용자의 기본 프로필 정보(이메일 주소 등) Google에서 확인한 이메일 주소입니다.

ID 토큰을 사용할 수 있는 경우 이를 사용하여 안전하게 인증할 수 있습니다. 자동으로 사용자를 새 계정에 등록시킬 수 있습니다. 이메일 주소를 사용하여 로그인할 수 있습니다.

ID 토큰으로 사용자를 로그인 또는 가입하려면 해당 토큰을 앱의 사용할 수 있습니다 백엔드에서 Google API 클라이언트 중 하나를 사용하여 토큰을 확인합니다. 범용 JWT 라이브러리일 수 있습니다 사용자가 계정에 로그인하지 않은 경우 이전에 이 Google 계정으로 앱을 사용하려면 새 계정을 만드세요.

재전송 공격을 피하기 위해 nonce를 선택적으로 사용하도록 선택한 경우 getNonce 를 사용하여 ID 토큰과 함께 백엔드 서버로 보내고, 있습니다. nonce를 사용하여 사용자 안전 및 보안 개선

사용자 인증 정보 객체에서 ID 토큰 가져오기

사용자 인증 정보를 가져온 후 사용자 인증 정보 객체가 ID 토큰을 포함할 수 없습니다. 지원한다면 백엔드로 전송합니다.

자바

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data);
                  String idToken = credential.getGoogleIdToken();
                  if (idToken !=  null) {
                      // Got an ID token from Google. Use it to authenticate
                      // with your backend.
                      Log.d(TAG, "Got ID token.");
                  }
              } catch (ApiException e) {
                  // ...
              }
              break;
      }
  }
}

Kotlin

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
             REQ_ONE_TAP -> {
                try {
                    val credential = oneTapClient.getSignInCredentialFromIntent(data)
                    val idToken = credential.googleIdToken
                    when {
                        idToken != null -> {
                            // Got an ID token from Google. Use it to authenticate
                            // with your backend.
                            Log.d(TAG, "Got ID token.")
                        }
                        else -> {
                            // Shouldn't happen.
                            Log.d(TAG, "No ID token!")
                        }
                    }
                } catch (e: ApiException) {
                    // ...
            }
        }
    }
    // ...
}

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">
</ph> <ph type="x-smartling-placeholder">
</ph>
자바

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건이 계정을 도메인에서 관리하기에 충분하지 않습니다. 또는 조직이나 그 안에서 활용할 수 있습니다.

를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">
</ph>
Node.js

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에서 호스팅하는 도메인일 수 있습니다

를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">
</ph>
PHP

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에서 호스팅하는 도메인일 수 있습니다

를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">
</ph>
Python

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

토큰이 올바르게 서명되었고 issexp이 클레임이 예상값을 갖는 경우 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 호스팅 도메인에 속하지 않음을 나타냅니다.

계정 또는 세션 만들기

토큰을 확인한 후 사용자가 이미 사용자에게 있는지 확인합니다. 데이터베이스입니다. 설정된 경우 사용자에 대해 인증된 세션을 설정합니다. 사용자가 사용자 데이터베이스에 없는 경우 정보에서 새 사용자 레코드를 만듭니다. 사용자를 위한 세션을 설정합니다. 사용자는 사용자의 개인 정보를 보호할 수 있는 추가 프로필 정보를 앱에 새로 생성된 사용자를 포함합니다.

사용자 보호 교차 계정 보호가 있는 계정

Google을 통해 사용자 로그인을 하면 자동으로 제공되는 모든 이점을 누릴 수 있습니다. Google에서 사용자의 데이터를 보호하기 위해 구축한 보안 기능과 인프라를 제공합니다. 하지만 드물지만 사용자의 Google 계정이 도용되거나 기타 계정이 도용된 경우 앱이 공격에 취약해질 수 있습니다 안전하게 보호하려면 계정을 해지하지 않으려면 교차 계정 Google의 보안 알림을 수신하기 위한 보호 조치입니다. 이러한 이벤트를 수신하면 사용자 Google 계정의 보안에 대한 중요 변경사항을 확인하고 그런 다음 서비스에 조치를 취하여 계정을 보호할 수 있습니다.