Google ID 서비스로 이전

<ph type="x-smartling-placeholder">

개요

Google API 호출을 위한 사용자별 액세스 토큰을 얻을 수 있도록 Google은 JavaScript 라이브러리:

이 가이드에서는 이러한 라이브러리에서 Google Identity Services 라이브러리를 참조하세요.

이 가이드를 따르면 다음과 같은 이점이 있습니다.

  • 지원 중단된 플랫폼 라이브러리를 Identity Services 라이브러리로 교체합니다. 및
  • API 클라이언트 라이브러리를 사용하는 경우 지원 중단된 gapi.auth2 모듈을 삭제합니다. 메서드와 객체로 대체하여 ID 서비스에 상응하는 항목으로 대체합니다.

ID 서비스 JavaScript로 변경된 사항에 대한 설명 라이브러리에서 개요사용자 인증 작동 방식을 읽고 주요 용어와 개념에 대해 알아보겠습니다.

사용자 가입 및 로그인을 위한 인증을 찾는 경우 다음을 참조하세요. 대신 Google 로그인에서 이전하세요.

승인 흐름 확인

사용 가능한 두 가지 사용자 승인 흐름은 암시적 승인 흐름과 승인 인증입니다. 있습니다.

웹 앱을 검토하여 현재 승인 흐름의 유형을 확인합니다. 있습니다.

웹 앱이 암시적 흐름을 사용하고 있음을 나타냅니다.

웹 앱이 승인 코드 흐름을 사용하고 있음을 나타냅니다.

  • 구현은 다음을 기반으로 합니다.

  • 앱은 사용자의 브라우저와 백엔드 플랫폼 모두에서 실행됩니다.

  • 백엔드 플랫폼은 승인 코드 엔드포인트를 호스팅합니다.

  • 백엔드 플랫폼이 사용자 대신 Google API를 호출하여 오프라인 모드라고도 합니다.

  • 갱신 토큰은 백엔드 플랫폼에서 관리하고 저장합니다.

경우에 따라 코드베이스가 두 흐름을 모두 지원할 수도 있습니다.

승인 흐름 선택

마이그레이션을 시작하기 전에 니즈에 가장 잘 맞는 다른 흐름을 채택할 수 있습니다.

승인 흐름 선택을 검토하여 주요 차이점 이해하기 절충점을 찾아야 합니다

대부분의 경우 승인 코드 플로우는 가장 높은 수준의 사용자 보안을 제공합니다. 이 흐름을 구현하면 업데이트 가져오기와 같은 새로운 오프라인 기능을 보다 쉽게 추가할 수 있는 플랫폼 캘린더, 사진, 구독정보 및 이메일 수신에 대한 중요한 변경사항을 사용자에게 알리기 위해 등등.

아래 선택기를 사용하여 승인 흐름을 선택합니다.

암시적 흐름

사용자가 있는 동안 브라우저에서 사용하기 위한 액세스 토큰을 가져옵니다.

암시적 흐름의 예: Identity Services

승인 코드 흐름

Google에서 발급한 사용자별 승인 코드가 백엔드로 전송됩니다. 액세스 토큰 및 갱신 토큰으로 교환됩니다.

승인 코드 흐름 예: 이전과 이후의 웹 앱을 보여줍니다. Identity Service로 마이그레이션할 때 사용할 수 있습니다

이 가이드에서 굵게 표시된 안내를 따라 추가합니다. 기존 기능을 삭제, 업데이트 또는 교체합니다.

브라우저 내 웹 앱 변경사항

이 섹션에서는 브라우저 내 웹 앱이 변경 사항을 검토할 때 Google ID 서비스 JavaScript 라이브러리로 마이그레이션합니다.

영향을 받은 코드 및 테스트 식별

디버그 쿠키는 영향을 받은 코드를 찾고 지원 중단 후 테스트하는 데 도움이 될 수 있습니다. 있습니다.

크거나 복잡한 앱에서는 코드의 영향을 받는 모든 코드를 찾기 어려울 수 있습니다. gapi.auth2 모듈이 지원 중단되었습니다. 예정된 의 기존 사용 기록 콘솔에 삽입하려면 G_AUTH2_MIGRATION 쿠키를 informational로 전송합니다. 필요한 경우 뒤에 콜론을 추가합니다. 세션 스토리지에도 로깅합니다. 로그인 후 사용자 인증 정보 검토 수신 또는 수집된 로그를 백엔드로 전송 분석 예를 들어 informational:showauth2use는 출발지와 URL을 세션 스토리지 키(showauth2use)입니다.

gapi.auth2 모듈이 더 이상 로드되지 않을 때 앱 동작을 확인하려면 G_AUTH2_MIGRATION 쿠키의 값을 enforced로 전송합니다. 이를 통해 시행일 전에 지원 중단 후 동작을 확인할 수 있습니다.

가능한 G_AUTH2_MIGRATION 쿠키 값은 다음과 같습니다.

  • enforced gapi.auth2 모듈을 로드하지 마세요.
  • informational 지원 중단된 기능의 사용을 JS 콘솔에 로깅합니다. 기록 (선택사항) 키 이름이 설정되면 세션 스토리지에 저장됩니다. informational:key-name

사용자에게 미치는 영향을 최소화하려면 먼저 이 쿠키를 로컬로 설정하는 것이 좋습니다. 프로덕션 환경에서 사용하기 전에 코드를 빌드해야 합니다

라이브러리 및 모듈

gapi.auth2 모듈은 로그인 및 암시적 인증의 사용자 인증을 이 지원 중단된 모듈과 객체를 교체하고 메서드를 사용할 수 있습니다.

다음을 포함하여 Identity Services 라이브러리를 웹 앱에 추가합니다. 문서:

<script src="https://accounts.google.com/gsi/client" async defer></script>

gapi.load('auth2', function)를 사용하여 auth2 모듈을 로드하는 인스턴스를 삭제합니다.

Google ID 서비스 라이브러리는 gapi.auth2 모듈 사용을 대체합니다. Google API에서 gapi.client 모듈을 계속 사용할 수 있습니다. JavaScript용 클라이언트 라이브러리를 찾고 이 라이브러리의 자동 생성을 활용합니다. 검색 문서에서 호출 가능한 JS 메서드 생성, 다중 API 호출 일괄 처리, CORS 관리 기능을 제공합니다

쿠키

사용자 인증에는 쿠키 사용이 필요하지 않습니다.

사용자 인증 방법에 관한 자세한 내용은 Google 로그인에서 이전을 참고하세요. 및 기타 다른 사람이 쿠키를 사용하기 위해 Google이 쿠키를 사용하는 방식 Google 제품 및 서비스

사용자 인증 정보

Google ID 서비스는 사용자 인증 및 승인을 두 개의 서로 다른 작업을 수행하며 사용자 인증 정보는 별개의 것입니다. 사용자 인증 정보는 다음에 사용된 액세스 토큰과 별도로 반환되는 사용자를 식별하는 데 있습니다.

변경사항을 보려면 사용자 인증 정보 예시를 참고하세요.

암시적 흐름

사용자 프로필을 삭제하여 사용자 인증 및 승인을 분리합니다. 처리할 수 있습니다.

다음 Google 로그인 JavaScript 클라이언트 참조삭제합니다.

메서드

  • GoogleUser.getBasicProfile()
  • GoogleUser.getId()

승인 코드 흐름

ID 서비스에서는 브라우저 내 사용자 인증 정보를 ID 토큰과 액세스로 분리 토큰입니다. 이 변경사항은 직접 인증을 통해 획득한 사용자 인증 정보에는 적용되지 않습니다. Google OAuth 2.0 엔드포인트에 대한 호출을 Google API Node.js 클라이언트를 사용합니다.

세션 상태

이전에는 Google 로그인을 통해 다음을 사용하여 사용자 로그인 상태를 관리할 수 있었습니다.

웹에 대한 로그인 상태와 사용자 세션을 관리해야 합니다. 있습니다.

다음 Google 로그인 JavaScript 클라이언트 참조삭제합니다.

객체:

  • gapi.auth2.SignInOptions

메서드

  • GoogleAuth.attachClickHandler()
  • GoogleAuth.isSignedIn()
  • GoogleAuth.isSignedIn.get()
  • GoogleAuth.isSignedIn.listen()
  • GoogleAuth.signIn()
  • GoogleAuth.signOut()
  • GoogleAuth.currentUser.get()
  • GoogleAuth.currentUser.listen()
  • GoogleUser.isSignedIn()

클라이언트 구성

웹 앱을 업데이트하여 암시적 또는 승인 코드 플로우로 이동합니다.

다음 Google 로그인 JavaScript 클라이언트 참조삭제합니다.

객체:

  • gapi.auth2.ClientConfig
  • gapi.auth2.OfflineAccessOptions

메서드

  • gapi.auth2.getAuthInstance()
  • GoogleUser.grant()

암시적 흐름

TokenClientConfig 객체 및 initTokenClient() 호출을 추가합니다. 토큰 초기화의 예에 따라 웹 앱을 클라이언트를 사용합니다.

Google 로그인 JavaScript 클라이언트 참조Google로 대체 ID 서비스:

객체:

  • TokenClientConfig에서 gapi.auth2.AuthorizeConfig

메서드

  • google.accounts.oauth2.initTokenClient()에서 gapi.auth2.init()

매개변수:

  • gapi.auth2.AuthorizeConfig.login_hint, TokenClientConfig.login_hint입니다.
  • TokenClientConfig.hdgapi.auth2.GoogleUser.getHostedDomain() 호출

승인 코드 흐름

구성할 CodeClientConfig 객체 및 initCodeClient() 호출을 추가합니다. 코드 클라이언트 초기화의 예에 따라 웹 앱을 실행합니다.

암시적 코드 흐름에서 승인 코드 흐름으로 전환하는 경우:

Google 로그인 JavaScript 클라이언트 참조 삭제

객체:

  • gapi.auth2.AuthorizeConfig

메서드

  • gapi.auth2.init()

매개변수:

  • gapi.auth2.AuthorizeConfig.login_hint
  • gapi.auth2.GoogleUser.getHostedDomain()

토큰 요청

버튼 클릭과 같은 사용자 동작은 요청을 생성하여 사용자의 브라우저에 직접 반환되는 액세스 토큰이 백엔드 플랫폼으로 푸시하거나 액세스 토큰 및 갱신 토큰의 비용을 확인할 수 있습니다

암시적 흐름

사용자가 액세스 토큰을 수집하는 동안 브라우저에서 로그인한 상태이며 Google과의 활성 세션이 있을 수 있습니다. 암시적 모드에서는 사용자가 이전 요청이 있었더라도 동작 없이 액세스 토큰을 요청해야 합니다. 합니다.

Google 로그인 JavaScript 클라이언트 참조Google로 바꿉니다. ID 서비스:

메서드

  • TokenClient.requestAccessToken()에서 gapi.auth2.authorize()
  • GoogleUser.reloadAuthResponse(), TokenClient.requestAccessToken()

링크 또는 버튼을 추가하여 requestAccessToken()를 호출하여 팝업 UX 흐름을 사용하여 액세스 토큰을 요청하거나 기존 토큰이 만료됩니다

코드베이스를 다음으로 업데이트합니다.

  • requestAccessToken()를 사용하여 OAuth 2.0 토큰 흐름을 트리거합니다.
  • requestAccessTokenOverridableTokenClientConfig: 여러 범위에 대해 하나의 요청 분리 여러 개의 작은 요청으로 나눌 수 있습니다
  • 기존 토큰이 만료되거나 취소되면 새 토큰을 요청합니다.

여러 범위를 사용하여 작업하려면 코드베이스의 구조를 변경해야 할 수 있습니다. 한 번에 모두 액세스하지 않고 필요할 때만 범위에 대한 액세스를 요청하고, 이를 단계적 승인이라고 합니다. 각 요청에는 가능한 한 적은 수의 범위, 이상적으로는 단일 범위를 사용하는 것이 좋습니다. 사용자의 문의에 대응하는 방법 보기 동의하여 단계별 안내를 위해 앱을 업데이트하는 방법을 자세히 알아보세요 있습니다.

액세스 토큰이 만료되면 gapi.auth2 모듈이 자동으로 웹 앱의 새 유효한 액세스 토큰입니다. 사용자 보안을 강화하기 위해 Google ID에서 자동 토큰 갱신 프로세스를 지원하지 않음 서비스 라이브러리로 대체될 수 있습니다. 만료된 액세스를 감지하려면 웹 앱을 업데이트해야 합니다. 새 토큰을 요청합니다. 자세한 내용은 아래의 토큰 처리 섹션을 참고하세요.

승인 코드 흐름

requestCode()를 호출하여 승인을 요청하는 링크 또는 버튼을 추가합니다. 코드를 생성합니다. 예시는 OAuth 2.0 코드 흐름 트리거를 참조하세요.

액세스 토큰이 만료되거나 취소된 경우

토큰 처리

만료되었거나 오류가 발생했을 때 실패한 Google API 호출을 감지하는 오류 처리를 추가합니다. 새 유효한 액세스 토큰을 요청할 수 있습니다.

401 Unauthorizedinvalid_token 오류 메시지의 HTTP 상태 코드는 다음과 같습니다. 만료되거나 취소된 액세스 토큰이 사용되었을 때 Google API에서 반환 예시는 잘못된 토큰 응답을 참조하세요.

만료된 토큰

액세스 토큰은 수명이 짧으며 대개 몇 분 동안만 유효합니다.

토큰 취소

Google 계정 소유자는 언제든지 이전에 받은 동의를 취소할 수 있습니다. 행동 기존 액세스 토큰과 갱신 토큰을 무효화합니다 해지는 revoke()를 사용하거나 Google을 통해 트리거됨 계정.

Google 로그인 JavaScript 클라이언트 참조Google로 바꿉니다. ID 서비스:

메서드

  • google.accounts.oauth2.revoke()에서 getAuthInstance().disconnect()
  • google.accounts.oauth2.revoke()에서 GoogleUser.disconnect()

사용자가 플랫폼에서 계정을 삭제하면 revoke를 호출합니다. 에서 앱과의 데이터 공유 동의를 삭제하고자 합니다.

웹 앱 또는 백엔드가 실행될 때 Google에서 사용자에게 동의 대화상자를 표시합니다. 액세스 토큰을 요청합니다 표시된 동의 대화상자 예시 보기 사용자에게 제공합니다.

앱에 액세스 토큰을 발급하기 전에 기존의 활성 Google 사용자 동의를 요청하고 결과를 기록하려면 세션이 필요합니다. 사용자 기존 세션이 연결되지 않은 경우 Google 계정에 로그인해야 할 수도 있습니다. 확인할 수 있습니다

사용자 로그인

사용자는 별도의 브라우저 탭에서 Google 계정에 로그인하거나 브라우저나 운영체제를 통해 추적할 수 있습니다 다음으로 로그인: Google 계정 간에 활성 세션을 설정합니다. 사용자가 앱을 처음 열 때 브라우저가 포함됩니다. 이렇게 하면 이점:

  • 사용자가 로그인하여 액세스를 요청해야 하는 횟수를 최소화합니다. 활성 세션이 활성화되면 토큰은 Google 계정 로그인 프로세스를 시작함 존재하지 않습니다.
  • JWT ID 토큰 credential email 필드를 CodeClientConfig 또는 TokenClientConfiglogin_hint 매개변수 객체입니다. 이 기능은 플랫폼에서 사용자 계정 관리 시스템입니다.
  • 에서 Google 계정 조회 및 기존 로컬 사용자 계정 연결 중복 계정을 최소화할 수 있습니다.
  • 로컬 계정을 새로 만들면 가입 대화상자와 절차가 사용자 인증 대화상자 및 흐름과 명확하게 분리되어 있으므로 감소율을 개선할 수 있습니다

로그인 후 및 액세스 토큰이 발급되기 전에 사용자가 동의해야 합니다. 할 수 있습니다.

동의 후 승인된 범위 목록과 함께 액세스 토큰이 반환됩니다. 거부될 수 있습니다

세분화된 권한을 통해 사용자는 개별 범위를 승인하거나 거부할 수 있습니다. 날짜 여러 범위에 대한 액세스 요청, 각 범위가 부여되거나 거부됨 다른 범위와 독립적으로 사용할 수 있습니다 사용자의 선택에 따라 선택적으로 앱 개별 범위에 종속된 기능을 사용 설정합니다.

암시적 흐름

Google 로그인 JavaScript 클라이언트 참조Google로 대체 ID 서비스:

객체:

  • TokenClient.TokenResponse에서 gapi.auth2.AuthorizeResponse
  • TokenClient.TokenResponse에서 gapi.auth2.AuthResponse

메서드

  • GoogleUser.hasGrantedScopes(), google.accounts.oauth2.hasGrantedAllScopes()
  • GoogleUser.getGrantedScopes(), google.accounts.oauth2.hasGrantedAllScopes()

Google 로그인 JavaScript 클라이언트 참조를 삭제합니다.

메서드

  • GoogleUser.getAuthResponse()

hasGrantedAllScopes() 및 다음으로 웹 앱 업데이트 hasGrantedAnyScope()세분화된 권한 예시를 따릅니다.

승인 코드 흐름

백엔드에 승인 코드 엔드포인트 업데이트 또는 추가 인증 코드 처리의 안내에 따라 플랫폼에 로그인합니다.

코드 사용에 설명된 단계를 따르도록 플랫폼을 업데이트합니다. 요청을 검증하고 액세스 토큰을 가져와 갱신하기 위한 모델 가이드 토큰입니다.

플랫폼을 업데이트하여 선택적으로 기능을 사용 설정 또는 사용 중지하고 사용자가 승인한 개별 범위에 따른 기능 증분 승인검토 안내문 따름 사용자가 부여한 액세스 범위가 포함됩니다.

암시적 흐름의 예

옛 방식

GAPI 클라이언트 라이브러리

JavaScript용 Google API 클라이언트 라이브러리의 예 사용자 동의를 위한 팝업 대화상자를 사용하여 브라우저에서 실행되도록 하는 것입니다.

gapi.auth2 모듈은 다음에서 자동으로 로드되고 사용됩니다. gapi.client.init() 등이며 숨겨져 있습니다.

<!DOCTYPE html>
  <html>
    <head>
      <script src="https://apis.google.com/js/api.js"></script>
      <script>
        function start() {
          gapi.client.init({
            'apiKey': 'YOUR_API_KEY',
            'clientId': 'YOUR_CLIENT_ID',
            'scope': 'https://www.googleapis.com/auth/cloud-translation',
            'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
          }).then(function() {
            // Execute an API request which is returned as a Promise.
            // The method name language.translations.list comes from the API discovery.
            return gapi.client.language.translations.list({
              q: 'hello world',
              source: 'en',
              target: 'de',
            });
          }).then(function(response) {
            console.log(response.result.data.translations[0].translatedText);
          }, function(reason) {
            console.log('Error: ' + reason.result.error.message);
          });
        };

        // Load the JavaScript client library and invoke start afterwards.
        gapi.load('client', start);
      </script>
    </head>
    <body>
      <div id="results"></div>
    </body>
  </html>

JS 클라이언트 라이브러리

클라이언트 측 웹 애플리케이션용 OAuth 2.0. 사용자 동의를 위한 팝업 대화상자

gapi.auth2 모듈은 수동으로 로드됩니다.

<!DOCTYPE html>
<html><head></head><body>
<script>
  var GoogleAuth;
  var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
  function handleClientLoad() {
    // Load the API's client and auth2 modules.
    // Call the initClient function after the modules load.
    gapi.load('client:auth2', initClient);
  }

  function initClient() {
    // In practice, your app can retrieve one or more discovery documents.
    var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';

    // Initialize the gapi.client object, which app uses to make API requests.
    // Get API key and client ID from API Console.
    // 'scope' field specifies space-delimited list of access scopes.
    gapi.client.init({
        'apiKey': 'YOUR_API_KEY',
        'clientId': 'YOUR_CLIENT_ID',
        'discoveryDocs': [discoveryUrl],
        'scope': SCOPE
    }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);

      // Handle initial sign-in state. (Determine if user is already signed in.)
      var user = GoogleAuth.currentUser.get();
      setSigninStatus();

      // Call handleAuthClick function when user clicks on
      //      "Sign In/Authorize" button.
      $('#sign-in-or-out-button').click(function() {
        handleAuthClick();
      });
      $('#revoke-access-button').click(function() {
        revokeAccess();
      });
    });
  }

  function handleAuthClick() {
    if (GoogleAuth.isSignedIn.get()) {
      // User is authorized and has clicked "Sign out" button.
      GoogleAuth.signOut();
    } else {
      // User is not signed in. Start Google auth flow.
      GoogleAuth.signIn();
    }
  }

  function revokeAccess() {
    GoogleAuth.disconnect();
  }

  function setSigninStatus() {
    var user = GoogleAuth.currentUser.get();
    var isAuthorized = user.hasGrantedScopes(SCOPE);
    if (isAuthorized) {
      $('#sign-in-or-out-button').html('Sign out');
      $('#revoke-access-button').css('display', 'inline-block');
      $('#auth-status').html('You are currently signed in and have granted ' +
          'access to this app.');
    } else {
      $('#sign-in-or-out-button').html('Sign In/Authorize');
      $('#revoke-access-button').css('display', 'none');
      $('#auth-status').html('You have not authorized this app or you are ' +
          'signed out.');
    }
  }

  function updateSigninStatus() {
    setSigninStatus();
  }
</script>

<button id="sign-in-or-out-button"
        style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
        style="display: none; margin-left: 25px">Revoke access</button>

<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>

OAuth 2.0 엔드포인트

다음을 사용하여 브라우저에서 실행되는 클라이언트 측 웹 애플리케이션용 OAuth 2.0. 사용자 동의를 위해 Google로 리디렉션됩니다.

이 예에서는 사용자의 브라우저를 사용하고 gapi.auth2 모듈이나 JavaScript를 사용하지 않음 있습니다.

<!DOCTYPE html>
<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*

    *   Create form to request access token from Google's OAuth 2.0 server.
 */
function oauth2SignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                  'state': 'try_sample_request',
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

새로운 방식

GIS 전용

이 예에서는 Google Identity Service JavaScript 라이브러리만 보여줍니다. 토큰 모델 사용 및 사용자 동의를 위한 팝업 대화상자 그것은 Google 게시자 태그를 구성하는 데 필요한 최소한의 단계를 Google API를 호출할 수 있습니다.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      var access_token;

      function initClient() {
        client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/contacts.readonly',
          callback: (tokenResponse) => {
            access_token = tokenResponse.access_token;
          },
        });
      }
      function getToken() {
        client.requestAccessToken();
      }
      function revokeToken() {
        google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
      }
      function loadCalendar() {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
        xhr.send();
      }
    </script>
    <h1>Google Identity Services Authorization Token model</h1>
    <button onclick="getToken();">Get access token</button><br><br>
    <button onclick="loadCalendar();">Load Calendar</button><br><br>
    <button onclick="revokeToken();">Revoke token</button>
  </body>
</html>

GAPI 비동기/대기

이 예에서는 토큰 모델을 사용하여 gapi.auth2 모듈을 삭제하고, JavaScript용 Google API 클라이언트 라이브러리.

프로미스, async, await는 라이브러리 로드 순서를 적용하고 포착하고 다시 시도합니다. 유효한 액세스 토큰을 사용할 수 있습니다.

사용자는 '캘린더 표시'를 눌러야 합니다. 버튼을 클릭하면 페이지가 처음 로드될 때 또는 액세스 토큰 이후에 누락된 경우 만료되었습니다.

<!DOCTYPE html>
<html>
<head></head>
<body>
  <h1>GAPI with GIS async/await</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>

  <script>

    const gapiLoadPromise = new Promise((resolve, reject) => {
      gapiLoadOkay = resolve;
      gapiLoadFail = reject;
    });
    const gisLoadPromise = new Promise((resolve, reject) => {
      gisLoadOkay = resolve;
      gisLoadFail = reject;
    });

    var tokenClient;

    (async () => {
      document.getElementById("showEventsBtn").style.visibility="hidden";
      document.getElementById("revokeBtn").style.visibility="hidden";

      // First, load and initialize the gapi.client
      await gapiLoadPromise;
      await new Promise((resolve, reject) => {
        // NOTE: the 'auth2' module is no longer loaded.
        gapi.load('client', {callback: resolve, onerror: reject});
      });
      await gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
      });

      // Now load the GIS client
      await gisLoadPromise;
      await new Promise((resolve, reject) => {
        try {
          tokenClient = google.accounts.oauth2.initTokenClient({
              client_id: 'YOUR_CLIENT_ID',
              scope: 'https://www.googleapis.com/auth/calendar.readonly',
              prompt: 'consent',
              callback: '',  // defined at request time in await/promise scope.
          });
          resolve();
        } catch (err) {
          reject(err);
        }
      });

      document.getElementById("showEventsBtn").style.visibility="visible";
      document.getElementById("revokeBtn").style.visibility="visible";
    })();

    async function getToken(err) {

      if (err.result.error.code == 401 || (err.result.error.code == 403) &&
          (err.result.error.status == "PERMISSION_DENIED")) {

        // The access token is missing, invalid, or expired, prompt for user consent to obtain one.
        await new Promise((resolve, reject) => {
          try {
            // Settle this promise in the response callback for requestAccessToken()
            tokenClient.callback = (resp) => {
              if (resp.error !== undefined) {
                reject(resp);
              }
              // GIS has automatically updated gapi.client with the newly issued access token.
              console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
              resolve(resp);
            };
            tokenClient.requestAccessToken();
          } catch (err) {
            console.log(err)
          }
        });
      } else {
        // Errors unrelated to authorization: server errors, exceeding quota, bad requests, and so on.
        throw new Error(err);
      }
    }

    function showEvents() {

      // Try to fetch a list of Calendar events. If a valid access token is needed,
      // prompt to obtain one and then retry the original request.
      gapi.client.calendar.events.list({ 'calendarId': 'primary' })
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => getToken(err))  // for authorization errors obtain an access token
      .then(retry => gapi.client.calendar.events.list({ 'calendarId': 'primary' }))
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => console.log(err)); // cancelled by user, timeout, etc.
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
      }
    }

  </script>

  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoadOkay()" onerror="gapiLoadFail(event)"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoadOkay()" onerror="gisLoadFail(event)"></script>

</body>
</html>

GAPI 콜백

이 예에서는 토큰 모델을 사용하여 gapi.auth2 모듈을 삭제하고, JavaScript용 Google API 클라이언트 라이브러리.

변수는 라이브러리 로드 순서를 적용하는 데 사용됩니다. GAPI는 를 삭제합니다.

페이지가 처음 열릴 때 사용자는 캘린더 표시 버튼을 눌러야 합니다. 캘린더 정보를 새로고침하려고 할 때 다시 로드됩니다.

<!DOCTYPE html>
<html>
<head>
  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script>
</head>
<body>
  <h1>GAPI with GIS callbacks</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
  <script>
    let tokenClient;
    let gapiInited;
    let gisInited;

    document.getElementById("showEventsBtn").style.visibility="hidden";
    document.getElementById("revokeBtn").style.visibility="hidden";

    function checkBeforeStart() {
       if (gapiInited && gisInited){
          // Start only when both gapi and gis are initialized.
          document.getElementById("showEventsBtn").style.visibility="visible";
          document.getElementById("revokeBtn").style.visibility="visible";
       }
    }

    function gapiInit() {
      gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
        gapiInited = true;
        checkBeforeStart();
      });
    }

    function gapiLoad() {
        gapi.load('client', gapiInit)
    }

    function gisInit() {
     tokenClient = google.accounts.oauth2.initTokenClient({
                client_id: 'YOUR_CLIENT_ID',
                scope: 'https://www.googleapis.com/auth/calendar.readonly',
                callback: '',  // defined at request time
            });
      gisInited = true;
      checkBeforeStart();
    }

    function showEvents() {

      tokenClient.callback = (resp) => {
        if (resp.error !== undefined) {
          throw(resp);
        }
        // GIS has automatically updated gapi.client with the newly issued access token.
        console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));

        gapi.client.calendar.events.list({ 'calendarId': 'primary' })
        .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
        .catch(err => console.log(err));

        document.getElementById("showEventsBtn").innerText = "Refresh Calendar";
      }

      // Conditionally ask users to select the Google Account they'd like to use,
      // and explicitly obtain their consent to fetch their Calendar.
      // NOTE: To request an access token a user gesture is necessary.
      if (gapi.client.getToken() === null) {
        // Prompt the user to select a Google Account and asked for consent to share their data
        // when establishing a new session.
        tokenClient.requestAccessToken({prompt: 'consent'});
      } else {
        // Skip display of account chooser and consent dialog for an existing session.
        tokenClient.requestAccessToken({prompt: ''});
      }
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
        document.getElementById("showEventsBtn").innerText = "Show Calendar";
      }
    }
  </script>
</body>
</html>

승인 코드 흐름의 예

Google Identity Service 라이브러리 팝업 UX는 백엔드 토큰 엔드포인트로 직접 승인 코드를 반환하거나 사용자의 브라우저에서 실행되어 필요한 조치를 취할 수 있습니다 어떤 경우든 백엔드 플랫폼은 OAuth 2.0 흐름을 사용하여 유효한 갱신 및 액세스 토큰을 얻어야 합니다.

옛 방식

서버 측 웹 앱

백엔드 플랫폼에서 실행되는 서버 측 앱용 Google 로그인 사용자 동의를 얻기 위해 Google로 리디렉션하는 행위

<!DOCTYPE html>
<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script>
    <script>
      function start() {
        gapi.load('auth2', function() {
          auth2 = gapi.auth2.init({
            client_id: 'YOUR_CLIENT_ID',
            api_key: 'YOUR_API_KEY',
            discovery_docs: ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
            // Scopes to request in addition to 'profile' and 'email'
            scope: 'https://www.googleapis.com/auth/cloud-translation',
          });
        });
      }
      function signInCallback(authResult) {
        if (authResult['code']) {
          console.log("sending AJAX request");
          // Send authorization code obtained from Google to backend platform
          $.ajax({
            type: 'POST',
            url: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
            // Always include an X-Requested-With header to protect against CSRF attacks.
            headers: {
              'X-Requested-With': 'XMLHttpRequest'
            },
            contentType: 'application/octet-stream; charset=utf-8',
            success: function(result) {
              console.log(result);
            },
            processData: false,
            data: authResult['code']
          });
        } else {
          console.log('error: failed to obtain authorization code')
        }
      }
    </script>
  </head>
  <body>
    <button id="signinButton">Sign In With Google</button>
    <script>
      $('#signinButton').click(function() {
        // Obtain an authorization code from Google
        auth2.grantOfflineAccess().then(signInCallback);
      });
    </script>
  </body>
</html>

리디렉션을 사용한 HTTP/REST

웹 서버 애플리케이션용 OAuth 2.0을 사용하여 승인 코드 보내기 백엔드 플랫폼으로 이동하는 경로를 확인할 수 있습니다 사용자 동의 처리: 사용자의 브라우저를 Google로 리디렉션합니다.

/\*
 \* Create form to request access token from Google's OAuth 2.0 server.
 \*/
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
  // Create &lt;form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);
  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client\_id': 'YOUR_CLIENT_ID',
                'redirect\_uri': 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
                'response\_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                'include\_granted\_scopes': 'true',
                'state': 'pass-through value'};
  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

새로운 방식

GIS 팝업 UX

이 예에서는 Google Identity Service JavaScript 라이브러리만 보여줍니다. 승인 코드 모델을 사용하여 사용자 동의를 묻는 팝업 대화상자가 표시됩니다. 콜백 핸들러에 전달하여 Google에서 승인 코드를 받습니다. 그것은 Google 게시자 태그를 구성하는 데 필요한 최소한의 단계를 동의를 얻고 백엔드로 승인 코드를 전송합니다. 있습니다.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly',
          ux_mode: 'popup',
          callback: (response) => {
            var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
            // Send auth code to your backend platform
            const xhr = new XMLHttpRequest();
            xhr.open('POST', code_receiver_uri, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onload = function() {
              console.log('Signed in as: ' + xhr.responseText);
            };
            xhr.send('code=' + response.code);
            // After receipt, the code is exchanged for an access token and
            // refresh token, and the platform then updates this web app
            // running in user's browser with the requested calendar info.
          },
        });
      }
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

GIS 리디렉션 UX

인증 코드 모델은 팝업 및 UX 모드를 사용자별 승인 코드를 플랫폼에서 호스팅하는 엔드포인트로 보냅니다. 리디렉션 UX 모드는 다음과 같습니다.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/photoslibrary.readonly',
          ux_mode: 'redirect',
          redirect_uri: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI'
        });
      }
      // Request an access token
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

JavaScript 라이브러리

Google ID 서비스는 사용자 인증 정보를 위해 사용되는 인증 및 승인은 Google Cloud의 여러 기능을 통합하고 여러 라이브러리 및 모듈에서 찾을 수 있습니다.

ID 서비스로 마이그레이션할 때 취해야 할 조치는 다음과 같습니다.

기존 JS 라이브러리 새 JS 라이브러리 참고
apis.google.com/js/api.js accounts.google.com/gsi/client 새 라이브러리를 추가하고 암시적 흐름을 따릅니다.
apis.google.com/js/client.js accounts.google.com/gsi/client 새 라이브러리 및 승인 코드 흐름을 추가합니다.

라이브러리 빠른 참조

이전 Google 로그인 JavaScript 간의 객체 및 메서드 비교 클라이언트 라이브러리와 새로운 Google ID 서비스 라이브러리, 그리고 메모에 추가 정보와 이전 중 취해야 할 조치가 표시됩니다.

변경 전 신규 참고
GoogleAuth 객체 및 관련 메서드:
GoogleAuth.attachClickHandler() 삭제
GoogleAuth.currentUser.get() 삭제
GoogleAuth.currentUser.listen() 삭제
GoogleAuth.disconnect() google.accounts.oauth2.revoke 오래된 것으로 교체합니다. https://myaccount.google.com/permissions에서도 해지될 수 있습니다.
GoogleAuth.grantOfflineAccess() 삭제하고 승인 코드 흐름을 따릅니다.
GoogleAuth.isSignedIn.get() 삭제
GoogleAuth.isSignedIn.listen() 삭제
GoogleAuth.signIn() 삭제
GoogleAuth.signOut() 삭제
GoogleAuth.then() 삭제
GoogleUser 객체 및 관련 메서드:
GoogleUser.disconnect() google.accounts.id.revoke 오래된 것으로 교체합니다. https://myaccount.google.com/permissions에서도 해지될 수 있습니다.
GoogleUser.getAuthResponse() requestCode() or requestAccessToken() 오래된 항목 교체
GoogleUser.getBasicProfile() 삭제를 탭합니다. 대신 ID 토큰을 사용하세요. Google 로그인에서 이전을 참고하세요.
GoogleUser.getGrantedScopes() hasGrantedAnyScope() 오래된 항목 교체
GoogleUser.getHostedDomain() 삭제
GoogleUser.getId() 삭제
GoogleUser.grantOfflineAccess() 삭제하고 승인 코드 흐름을 따릅니다.
GoogleUser.grant() 삭제
GoogleUser.hasGrantedScopes() hasGrantedAnyScope() 오래된 항목 교체
GoogleUser.isSignedIn() 삭제
GoogleUser.reloadAuthResponse() requestAccessToken() 이전 액세스 토큰을 삭제하고 new를 호출하여 만료되었거나 취소된 액세스 토큰을 교체합니다.
gapi.auth2 객체 및 관련 메서드:
gapi.auth2.AuthorizeConfig 객체 TokenClientConfig 또는 CodeClientConfig 오래된 항목 교체
gapi.auth2.AuthorizeResponse 객체 삭제
gapi.auth2.AuthResponse 객체 삭제
gapi.auth2.authorize() requestCode() or requestAccessToken() 오래된 항목 교체
gapi.auth2.ClientConfig() TokenClientConfig 또는 CodeClientConfig 오래된 항목 교체
gapi.auth2.getAuthInstance() 삭제
gapi.auth2.init() initTokenClient() or initCodeClient() 오래된 항목 교체
gapi.auth2.offlineAccessOptions 객체 삭제
gapi.auth2.SignInOptions 객체 삭제
gapi.signin2 객체 및 관련 메서드가 포함됩니다.
gapi.signin2.render() 삭제를 탭합니다. HTML DOM 로드 g_id_signin 요소 또는 JS 호출을 통해 google.accounts.id.renderButton Google 계정에 대한 사용자 로그인을 트리거합니다.

사용자 인증 정보 예시

기존 사용자 인증 정보

Google 로그인 플랫폼 라이브러리, JavaScript를 호출합니다. 또는 Google 인증 2.0 엔드포인트에 대한 직접 호출은 OAuth 2.0 액세스 토큰과 OpenID Connect ID 토큰을 하나로 있습니다.

access_tokenid_token를 모두 포함하는 응답 예시:

  {
    "token_type": "Bearer",
    "access_token": "ya29.A0ARrdaM-SmArZaCIh68qXsZSzyeU-8mxhQERHrP2EXtxpUuZ-3oW8IW7a6D2J6lRnZrRj8S6-ZcIl5XVEqnqxq5fuMeDDH_6MZgQ5dgP7moY-yTiKR5kdPm-LkuPM-mOtUsylWPd1wpRmvw_AGOZ1UUCa6UD5Hg",
    "scope": "https://www.googleapis.com/auth/calendar.readonly",
    "login_hint": "AJDLj6I2d1RH77cgpe__DdEree1zxHjZJr4Q7yOisoumTZUmo5W2ZmVFHyAomUYzLkrluG-hqt4RnNxrPhArd5y6p8kzO0t8xIfMAe6yhztt6v2E-_Bb4Ec3GLFKikHSXNh5bI-gPrsI",
    "expires_in": 3599,
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzNDFhYmM0MDkyYjZmYzAzOGU0MDNjOTEwMjJkZDNlNDQ1MzliNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzI2NDMxNjUxOTQzNjk4NjAwIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IkJBSW55TjN2MS1ZejNLQnJUMVo0ckEiLCJuYW1lIjoiQnJpYW4gRGF1Z2hlcnR5IiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdnenAyTXNGRGZvbVdMX3VDemRYUWNzeVM3ZGtxTE5ybk90S0QzVXNRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IkJyaWFuIiwiZmFtaWx5X25hbWUiOiJEYXVnaGVydHkiLCJsb2NhbGUiOiJlbiIsImlhdCI6MTYzODk5MTYzOCwiZXhwIjoxNjM4OTk1MjM4LCJqdGkiOiI5YmRkZjE1YWFiNzE2ZDhjYmJmNDYwMmM1YWM3YzViN2VhMDQ5OTA5In0.K3EA-3Adw5HA7O8nJVCsX1HmGWxWzYk3P7ViVBb4H4BoT2-HIgxKlx1mi6jSxIUJGEekjw9MC-nL1B9Asgv1vXTMgoGaNna0UoEHYitySI23E5jaMkExkTSLtxI-ih2tJrA2ggfA9Ekj-JFiMc6MuJnwcfBTlsYWRcZOYVw3QpdTZ_VYfhUu-yERAElZCjaAyEXLtVQegRe-ymScra3r9S92TA33ylMb3WDTlfmDpWL0CDdDzby2asXYpl6GQ7SdSj64s49Yw6mdGELZn5WoJqG7Zr2KwIGXJuSxEo-wGbzxNK-mKAiABcFpYP4KHPEUgYyz3n9Vqn2Tfrgp-g65BQ",
    "session_state": {
      "extraQueryParams": {
        "authuser": "0"
      }
    },
    "first_issued_at": 1638991637982,
    "expires_at": 1638995236982,
    "idpId": "google"
  }

Google ID 서비스 사용자 인증 정보

Google ID 서비스 라이브러리는 다음을 반환합니다.

  • 승인에 사용된 액세스 토큰:

    {
      "access_token": "ya29.A0ARrdaM_LWSO-uckLj7IJVNSfnUityT0Xj-UCCrGxFQdxmLiWuAosnAKMVQ2Z0LLqeZdeJii3TgULp6hR_PJxnInBOl8UoUwWoqsrGQ7-swxgy97E8_hnzfhrOWyQBmH6zs0_sUCzwzhEr_FAVqf92sZZHphr0g",
      "token_type": "Bearer",
      "expires_in": 3599,
      "scope": "https://www.googleapis.com/auth/calendar.readonly"
    }
    
  • 또는 인증에 사용된 ID 토큰:

    {
      "clientId": "538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com",
      "credential": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxODkyZWI0OWQ3ZWY5YWRmOGIyZTE0YzA1Y2EwZDAzMjcxNGEyMzciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MzkxNTcyNjQsImF1ZCI6IjUzODM0NDY1MzI1NS03NThjNWg1aXNjNDV2Z2syN2Q4aDhkZWFib3ZwZzZ0by5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjExNzcyNjQzMTY1MTk0MzY5ODYwMCIsIm5vbmNlIjoiZm9vYmFyIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkJyaWFuIERhdWdoZXJ0eSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHZ3pwMk1zRkRmb21XTF91Q3pkWFFjc3lTN2RrcUxOcm5PdEtEM1VzUT1zOTYtYyIsImdpdmVuX25hbWUiOiJCcmlhbiIsImZhbWlseV9uYW1lIjoiRGF1Z2hlcnR5IiwiaWF0IjoxNjM5MTU3NTY0LCJleHAiOjE2MzkxNjExNjQsImp0aSI6IjRiOTVkYjAyZjU4NDczMmUxZGJkOTY2NWJiMWYzY2VhYzgyMmI0NjUifQ.Cr-AgMsLFeLurnqyGpw0hSomjOCU4S3cU669Hyi4VsbqnAV11zc_z73o6ahe9Nqc26kPVCNRGSqYrDZPfRyTnV6g1PIgc4Zvl-JBuy6O9HhClAK1HhMwh1FpgeYwXqrng1tifmuotuLQnZAiQJM73Gl-J_6s86Buo_1AIx5YAKCucYDUYYdXBIHLxrbALsA5W6pZCqqkMbqpTWteix-G5Q5T8LNsfqIu_uMBUGceqZWFJALhS9ieaDqoxhIqpx_89QAr1YlGu_UO6R6FYl0wDT-nzjyeF5tonSs3FHN0iNIiR3AMOHZu7KUwZaUdHg4eYkU-sQ01QNY_11keHROCRQ",
      "select_by": "user"
    }
    

잘못된 토큰 응답

만료, 취소 또는 잘못된 액세스 토큰:

HTTP 응답 헤더

  www-authenticate: Bearer realm="https://accounts.google.com/", error="invalid_token"

응답 본문

  {
    "error": {
      "code": 401,
      "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
      "errors": [
        {
          "message": "Invalid Credentials",
          "domain": "global",
          "reason": "authError",
          "location": "Authorization",
          "locationType": "header"
        }
      ],
      "status": "UNAUTHENTICATED"
    }
  }