자바스크립트 애플리케이션에서 인증된 요청 전송

이 페이지에서는 로컬로 실행되는 자바스크립트 애플리케이션에서 Cloud Endpoints 프레임워크를 사용하여 생성된 REST API로 인증된 요청을 전송하는 방법을 설명합니다. 이 자바스크립트 애플리케이션은 Google 로그인을 사용하는 방법과 요청에 Google ID 토큰을 전송하여 사용자를 인증하는 방법을 보여줍니다. 자바스크립트 애플리케이션이 요청을 전송하면 Endpoints 프레임워크는 App Engine 표준 환경에서 실행 중인 백엔드 코드로 요청을 전달하기 전에 사용자를 인증합니다.

기본 요건

샘플 자바스크립트 애플리케이션을 실행하는 데 필요한 사항은 다음과 같습니다.

  • 샘플 자바스크립트 코드에 Google Cloud 프로젝트 ID를 추가해야 하므로 샘플 API용으로 만든 Google Cloud 프로젝트 ID를 확인합니다. 프로젝트 ID를 확인하는 데 도움이 필요하면 프로젝트 목록을 참조하세요.

  • 자바스크립트 코드가 포함된 샘플 index.html 파일을 제공하려면 로컬 컴퓨터에 웹 서버가 있어야 합니다. 이 페이지에는 Python을 사용하여 간단한 서버를 실행하는 단계가 포함되어 있지만 모든 웹 서버를 사용할 수 있습니다.

샘플 자바스크립트 클라이언트 코드 다운로드

  1. 샘플을 로컬 머신에 복제합니다.

    git clone https://github.com/GoogleCloudPlatform/web-docs-samples
    
  2. 자바스크립트 클라이언트가 포함된 디렉토리로 변경합니다.

    cd web-docs-samples/endpoints-frameworks
    

OAuth 2.0 클라이언트 ID 만들기

인증을 위해 샘플을 설정하려면 샘플 자바스크립트 코드와 백엔드 코드에서 OAuth 2.0 클라이언트 ID를 구성해야 합니다. 자바스크립트 앱은 클라이언트 ID를 사용하여 Google OAuth 2.0 서버에서 Google ID 토큰을 받은 후 이를 요청에 포함하여 전송합니다. Endpoints 프레임워크는 클라이언트 ID를 사용하여 자바스크립트 앱이 요청에 포함하여 전송한 ID 토큰을 인증합니다.

클라이언트 ID를 만들려면 다음 안내를 따르세요.

  1. Google Cloud Console에서 사용자 인증 정보 페이지로 이동합니다.

    사용자 인증 정보 페이지로 이동

  2. 프로젝트 목록에서 샘플 API용으로 만든 프로젝트를 선택합니다.

  3. 사용자 인증 정보 만들기 버튼을 클릭한 후 OAuth 클라이언트 ID를 선택합니다. 이 프로젝트에서 클라이언트 ID를 처음 만드는 경우, 동의 화면에서 하위 단계를 따라 제품 이름을 설정합니다. 그렇지 않으면 다음 단계로 건너뜁니다.

    1. 동의 화면 구성 버튼을 클릭합니다.
    2. 애플리케이션 이름 필드에 이름을 입력합니다.
    3. 저장을 클릭합니다.
  4. 애플리케이션 유형에서 웹 애플리케이션을 클릭합니다.

  5. 승인된 자바스크립트 원본 필드에 다음을 입력합니다.

    http://localhost:8080
    
  6. 만들기를 클릭합니다.

  7. 클라이언트 ID를 복사합니다. 전체 클라이언트 ID는 다음과 같지만 프로젝트의 웹 애플리케이션에 고유합니다.

    271473851874-mtll5dk2vultovbtilt31hakqbinpuvd.apps.googleusercontent.com

클라이언트 ID 만들기에 대한 자세한 내용은 OAuth 2.0 설정을 참조하세요.

백엔드 코드 구성 및 재배포

Cloud Endpoints 프레임워크에서 자바스크립트 애플리케이션에서 보낸 요청을 인증하려면 방금 만든 클라이언트 ID를 샘플 코드에 추가하고 업데이트된 OpenAPI 문서와 애플리케이션 백엔드 코드를 재배포해야 합니다.

다음 절차에서는 Python용 Endpoints 프레임워크 시작하기의 샘플 API를 이미 배포했다고 가정합니다. 다음 절차를 시작하기 전에 API에 요청 전송의 설명에 따라 API에 요청을 전송하면 성공 응답이 수신되는지 확인하세요.

백엔드 코드를 구성하고 재배포하려면 다음 안내를 따르세요.

  1. python-docs-samples 저장소를 클론한 디렉터리에서 Python 샘플이 있는 디렉터리로 변경합니다.

    cd YOUR_WORKING_DIRECTORY/python-docs-samples/appengine/standard/endpoints-frameworks-v2/echo
    
  2. 텍스트 편집기에서 main.py 파일을 엽니다.

  3. get_user_email 함수의 데코레이터에서 your-oauth-client-id.com을 방금 만든 클라이언트 ID로 바꿉니다.

  4. main.py 파일을 저장합니다.

  5. 현재 위치가 다음의 샘플 기본 디렉터리인지 확인합니다.

    python-docs-samples/appengine/standard/endpoints-frameworks-v2/echo
    
  6. 클라이언트 ID가 포함되도록 OpenAPI 문서를 재생성합니다. 다음 명령어에서 YOUR_PROJECT_ID를 샘플 API용으로 만든 프로젝트로 바꿉니다.

    python lib/endpoints/endpointscfg.py get_openapi_spec main.EchoApi \
        --hostname YOUR_PROJECT_ID.appspot.com
    

    성공적으로 완료되면 다음 메시지가 표시됩니다.

    OpenAPI spec written to ./echov1openapi.json
    
  7. Google Cloud CLI(gcloud)에 Google Cloud의 데이터 및 서비스에 액세스할 수 있는 권한이 있는지 확인합니다.

    gcloud auth login
    
  8. Google Cloud CLI의 기본 프로젝트를 설정합니다. YOUR_PROJECT_ID를 샘플 API용으로 만든 프로젝트 ID로 바꿉니다.

    gcloud config set project YOUR_PROJECT_ID
    
  9. 업데이트된 OpenAPI 문서를 배포합니다.

    gcloud endpoints services deploy echov1openapi.json
    

    성공적으로 완료되면 명령어가 다음과 같은 줄을 출력합니다.

    Service Configuration [2018-02-13r2] uploaded for service [example-project-12345.appspot.com]
    
  10. 새 서비스 구성 ID를 복사합니다.

  11. 텍스트 편집기에서 app.yaml 파일을 엽니다. ENDPOINTS_SERVICE_VERSION 필드의 값을 새 서비스 구성 ID로 바꿉니다. 예를 들면 다음과 같습니다.

    ENDPOINTS_SERVICE_NAME: example-project-12345.appspot.com
    ENDPOINTS_SERVICE_VERSION: 2018-02-13r2
    
  12. app.yaml 파일을 저장합니다.

  13. 백엔드 코드를 재배포합니다.

    gcloud app deploy
    

자바스크립트 코드 구성

자바스크립트 코드를 구성하려면 다음 안내를 따르세요.

  1. web-docs-samples/endpoints-frameworks 디렉터리에서 main.js 파일을 텍스트 편집기로 엽니다.
  2. initGoogleAuth 함수에서 YOUR_CLIENT_ID를 만든 클라이언트 ID로 바꿉니다.

    function initGoogleAuth (clientId = 'YOUR_CLIENT_ID') {
      gapi.auth2.init({
        client_id: clientId,
        scope: 'https://www.googleapis.com/auth/userinfo.email'
      }).then(() => {
        document.getElementById('sign-in-btn').disabled = false;
      }).catch(err => {
        console.log(err);
      });
    }
  3. sendSampleRequest 함수에서 YOUR_PROJECT_ID를 샘플 API용으로 만든 프로젝트 ID로 바꿉니다.

    function sendSampleRequest (projectId = 'YOUR_PROJECT_ID') {
      var user = gapi.auth2.getAuthInstance().currentUser.get();
      var idToken = user.getAuthResponse().id_token;
      var endpoint = `https://${projectId}.appspot.com/_ah/api/echo/v1/email`;
      var xhr = new XMLHttpRequest();
      xhr.open('GET', endpoint + '?access_token=' + encodeURIComponent(idToken));
      xhr.onreadystatechange = function () {
        if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
          window.alert(xhr.responseText);
        }
      };
      xhr.send();
    }

인증된 요청 전송

  1. web-docs-samples 저장소를 클론한 디렉터리에서 자바스크립트 샘플이 있는 디렉터리로 변경합니다.

    cd YOUR_WORKING_DIRECTORY/web-docs-samples/endpoints-frameworks
    
  2. 포트 8080에서 index.html을 제공할 웹 서버를 시작합니다. 다음 예시에서는 Python의 간단한 서버를 사용합니다.

    python -m http.server 8080
    
  3. 브라우저에서 localhost:8080을 입력합니다.

    자바스크립트 애플리케이션에 버튼 두 개가 표시됩니다.

    로그인

  4. 로그인을 클릭합니다. Google 계정으로 로그인 페이지가 나타납니다.

  5. 로그인한 후 샘플 요청 전송 버튼을 클릭합니다. 요청을 처음 전송하면 App Engine이 시작될 때 약 20초 정도 지연될 수 있습니다. Endpoints 프레임워크가 요청을 가로채고 백엔드 코드에 구성된 클라이언트 ID를 사용하여 요청을 인증합니다. 인증이 성공하면 다음과 같이 작동합니다.

    1. Endpoints Frameworks가 요청을 App Engine에서 실행 중인 샘플 백엔드로 전달합니다.

    2. 백엔드 코드에서 get_user_email 메서드가 로그인 시 사용된 사용자 계정의 이메일 주소를 반환합니다.

    3. 자바스크립트 클라이언트에 이메일 주소와 함께 대화상자가 표시됩니다.

자바스크립트 클라이언트 개요

자바스크립트 클라이언트는 OAuth 2.0 흐름을 관리하는 Google 로그인을 사용합니다. 이 섹션에서는 자바스크립트 클라이언트 코드를 간략하게 설명합니다.

Auth 설정

  1. Google API 플랫폼 라이브러리를 로드하여 gapi 객체를 만듭니다.

      <script src="https://apis.google.com/js/platform.js?onload=loadAuthClient" async defer></script>
    </head>
  2. Google API 플랫폼 라이브러리를 로드한 후 auth2 라이브러리를 로드합니다.

    function loadAuthClient () {
      gapi.load('auth2', initGoogleAuth);
    }
  3. GoogleAuth 객체를 초기화합니다.

    function initGoogleAuth (clientId = 'YOUR_CLIENT_ID') {
      gapi.auth2.init({
        client_id: clientId,
        scope: 'https://www.googleapis.com/auth/userinfo.email'
      }).then(() => {
        document.getElementById('sign-in-btn').disabled = false;
      }).catch(err => {
        console.log(err);
      });
    }

GoogleAuth 객체를 초기화할 때 OAuth 2.0 클라이언트 ID와 지정할 추가 옵션으로 객체를 구성합니다. 일반적으로 액세스 범위를 지정합니다. 범위를 사용 설정하면 애플리케이션은 필요한 리소스에 대한 액세스만 요청하고 사용자는 애플리케이션에 부여하는 액세스 양을 제어할 수 있습니다. OAuth 2.0 승인을 구현하기 전에 애플리케이션에서 액세스 권한이 필요한 범위를 지정하는 것이 좋습니다. 이 예시에서는 사용자의 이메일 주소를 볼 수 있는 액세스 권한을 부여하는 https://www.googleapis.com/auth/userinfo.email 범위에 대한 액세스를 요청합니다.

로그인

GoogleAuth 객체를 초기화한 후 GoogleAuth 객체의 signIn 함수를 호출하여 사용자에게 로그인하라는 메시지를 표시할 수 있습니다.

function signIn () {
  gapi.auth2.getAuthInstance().signIn().then(() => {
    document.getElementById('sign-in-btn').hidden = true;
    document.getElementById('sign-out-btn').hidden = false;
    document.getElementById('send-request-btn').disabled = false;
  }).catch(err => {
    console.log(err);
  });
}

ID 토큰으로 요청

사용자가 로그인을 완료하면 사용자의 ID 토큰이 있는 승인 헤더가 포함된 요청을 전송합니다.

function sendSampleRequest (projectId = 'YOUR_PROJECT_ID') {
  var user = gapi.auth2.getAuthInstance().currentUser.get();
  var idToken = user.getAuthResponse().id_token;
  var endpoint = `https://${projectId}.appspot.com/_ah/api/echo/v1/email`;
  var xhr = new XMLHttpRequest();
  xhr.open('GET', endpoint + '?access_token=' + encodeURIComponent(idToken));
  xhr.onreadystatechange = function () {
    if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
      window.alert(xhr.responseText);
    }
  };
  xhr.send();
}

다음 단계