웹 서버 애플리케이션에 OAuth 2.0 사용

이 문서에서는 웹 서버 애플리케이션이 Google API 클라이언트 라이브러리 또는 Google OAuth 2.0 엔드포인트를 사용하여 Google API에 액세스하기 위한 OAuth 2.0 인증을 구현하는 방법을 설명합니다.

OAuth 2.0을 사용하면 사용자가 사용자 이름, 비밀번호 및 기타 정보를 비공개로 유지하면서 특정 데이터를 애플리케이션과 공유할 수 있습니다. 예를 들어 애플리케이션은 OAuth 2.0을 사용하여 사용자의 Google 드라이브에 파일을 저장할 수 있는 권한을 얻을 수 있습니다.

이 OAuth 2.0 흐름은 특히 사용자 인증을 위한 것입니다. 기밀 정보를 저장하고 상태를 유지할 수 있는 응용 프로그램을 위해 설계되었습니다. 적절하게 승인된 웹 서버 응용 프로그램은 사용자가 응용 프로그램과 상호 작용하는 동안 또는 사용자가 응용 프로그램을 떠난 후에 API에 액세스할 수 있습니다.

웹 서버 애플리케이션은 자주도 사용할 서비스 계정 액세스 프로젝트 기반의 데이터보다는 사용자 별 데이터를 클라우드 API를 호출 특히, API 요청을 승인. 웹 서버 응용 프로그램은 사용자 권한 부여와 함께 서비스 계정을 사용할 수 있습니다.

클라이언트 라이브러리

이 페이지 사용에 대한 언어 별 예제 구글 API 클라이언트 라이브러리 의 OAuth 2.0 인증을 구현합니다. 코드 샘플을 실행하려면 먼저 해당 언어에 대한 클라이언트 라이브러리를 설치해야 합니다.

Google API 클라이언트 라이브러리를 사용하여 애플리케이션의 OAuth 2.0 흐름을 처리하는 경우 클라이언트 라이브러리는 애플리케이션이 자체적으로 처리해야 하는 많은 작업을 수행합니다. 예를 들어 애플리케이션이 저장된 액세스 토큰을 사용하거나 새로 고칠 수 있는 시기와 애플리케이션이 동의를 다시 받아야 하는 시기를 결정합니다. 클라이언트 라이브러리는 또한 올바른 리디렉션 URL을 생성하고 액세스 토큰에 대한 인증 코드를 교환하는 리디렉션 핸들러를 구현하는 데 도움이 됩니다.

클라이언트 라이브러리는 다음 언어로 사용할 수 있습니다.

전제 조건

프로젝트에 API 활성화

구글 API를 호출하는 응용 프로그램은에서와 API를 활성화 할 필요가 API Console.

프로젝트에 API를 사용 설정하려면 다음 안내를 따르세요.

  1. Open the API Library 에서 Google API Console.
  2. If prompted, select a project, or create a new one.
  3. API Library 제품군과 인기로 그룹화 목록을 사용할 수있는 모든 API를. 사용하려는 API가 목록에 표시되지 않으면 사용 검색을 찾거나이 속한 제품군에서 모두보기를 클릭합니다.
  4. 사용하려는 API를 선택한 후이 버튼을 사용을 클릭합니다.
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

인증 자격 증명 만들기

OAuth 2.0을 사용하여 Google API에 액세스하는 모든 애플리케이션에는 Google의 OAuth 2.0 서버에 대한 애플리케이션을 식별하는 인증 자격 증명이 있어야 합니다. 다음 단계에서는 프로젝트에 대한 자격 증명을 만드는 방법을 설명합니다. 그러면 애플리케이션에서 자격 증명을 사용하여 해당 프로젝트에 대해 활성화한 API에 액세스할 수 있습니다.

  1. Go to the Credentials page.
  2. > OAuth 클라이언트 ID를 자격 증명 만들기를 클릭합니다.
  3. 웹 응용 프로그램 응용 프로그램 유형을 선택합니다.
  4. 양식을 작성하고 만들기를 클릭합니다. PHP, 자바, 파이썬, 루비, 및 .NET 등 사용 언어 및 프레임 워크가 승인 된 리디렉션 URI를 지정해야합니다 응용 프로그램. 리디렉션 URI는 OAuth 2.0 서버가 응답을 보낼 수 있는 끝점입니다. 이 끝점을 준수해야합니다 구글의 유효성 검사 규칙 .

    테스트를 위해, 당신은 같은 로컬 컴퓨터를 참조 URI를 지정할 수 있습니다 http://localhost:8080 . 그 마음에, 제발 참고로이 문서의 사용 예제 모두 http://localhost:8080 리디렉션 URI있다.

    우리는 당신이하는 것이 좋습니다 앱의 인증 엔드 포인트를 설계 응용 프로그램 페이지에서 다른 자원에 대한 인증 코드를 노출하지 않도록.

자격 증명을 만든 후에서 client_secret.json 파일 다운로드 API Console. 응용 프로그램만 액세스할 수 있는 위치에 파일을 안전하게 저장합니다.

액세스 범위 식별

범위를 사용하면 애플리케이션이 필요한 리소스에 대한 액세스만 요청할 수 있고 사용자가 애플리케이션에 부여하는 액세스 권한의 양을 제어할 수 있습니다. 따라서 요청된 범위의 수와 사용자 동의를 얻을 가능성 사이에는 반비례 관계가 있을 수 있습니다.

OAuth 2.0 인증 구현을 시작하기 전에 앱에 액세스 권한이 필요한 범위를 식별하는 것이 좋습니다.

우리는 또한 허가 응용 프로그램 액세스를 요청이를 통해 스코프하는 것이 좋습니다 증가 인증 응용 프로그램이 상황에서 사용자 데이터에 대한 액세스를 요청하는 방법. 이 모범 사례를 통해 사용자는 애플리케이션에서 요청하는 액세스 권한이 필요한 이유를 더 쉽게 이해할 수 있습니다.

의 OAuth 2.0 API 스코프의 문서는 액세스 구글의 API에 사용할 수있는 범위의 전체 목록이 포함되어 있습니다.

언어별 요구사항

이 문서의 코드 샘플을 실행하려면 Google 계정, 인터넷 액세스 및 웹 브라우저가 필요합니다. API 클라이언트 라이브러리 중 하나를 사용하는 경우 아래 언어별 요구 사항도 참조하세요.

PHP

이 문서에서 PHP 코드 샘플을 실행하려면 다음이 필요합니다.

  • 명령줄 인터페이스(CLI) 및 JSON 확장이 설치된 PHP 5.4 이상.
  • 작곡가의 의존성 관리 도구입니다.
  • PHP용 Google API 클라이언트 라이브러리:

    php composer.phar require google/apiclient:^2.0

파이썬

이 문서에서 Python 코드 샘플을 실행하려면 다음이 필요합니다.

  • 파이썬 2.6 이상
  • 패키지 관리 도구입니다.
  • Python 용 Google API 클라이언트 라이브러리 :
    pip install --upgrade google-api-python-client
  • google-auth , google-auth-oauthlibgoogle-auth-httplib2 사용자 권한 부여.
    pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
  • Flask Python 웹 애플리케이션 프레임워크.
    pip install --upgrade flask
  • requests HTTP 라이브러리.
    pip install --upgrade requests

루비

이 문서에서 Ruby 코드 샘플을 실행하려면 다음이 필요합니다.

  • 루비 2.2.2 이상
  • Ruby용 Google API 클라이언트 라이브러리:

    gem install google-api-client
  • Sinatra Ruby 웹 애플리케이션 프레임워크.

    gem install sinatra

HTTP/휴식

OAuth 2.0 엔드포인트를 직접 호출하기 위해 라이브러리를 설치할 필요는 없습니다.

OAuth 2.0 액세스 토큰 얻기

다음 단계는 애플리케이션이 Google의 OAuth 2.0 서버와 상호작용하여 사용자를 대신하여 API 요청을 수행하기 위해 사용자의 동의를 얻는 방법을 보여줍니다. 애플리케이션에서 사용자 승인이 필요한 Google API 요청을 실행하려면 먼저 해당 동의가 있어야 합니다.

아래 목록은 이러한 단계를 빠르게 요약한 것입니다.

  1. 애플리케이션은 필요한 권한을 식별합니다.
  2. 애플리케이션은 요청된 권한 목록과 함께 사용자를 Google로 리디렉션합니다.
  3. 사용자는 애플리케이션에 권한을 부여할지 여부를 결정합니다.
  4. 귀하의 응용 프로그램은 사용자가 결정한 것을 찾습니다.
  5. 사용자가 요청된 권한을 부여한 경우 애플리케이션은 사용자를 대신하여 API 요청을 수행하는 데 필요한 토큰을 검색합니다.

1단계: 승인 매개변수 설정

첫 번째 단계는 승인 요청을 생성하는 것입니다. 이 요청은 애플리케이션을 식별하고 사용자가 애플리케이션에 부여할 권한을 정의하는 매개변수를 설정합니다.

  • OAuth 2.0 인증 및 권한 부여를 위해 Google 클라이언트 라이브러리를 사용하는 경우 이러한 매개변수를 정의하는 개체를 만들고 구성합니다.
  • Google OAuth 2.0 엔드포인트를 직접 호출하는 경우 URL을 생성하고 해당 URL에 대한 매개변수를 설정합니다.

아래 탭은 웹 서버 애플리케이션에 대해 지원되는 인증 매개변수를 정의합니다. 언어별 예는 클라이언트 라이브러리 또는 권한 부여 라이브러리를 사용하여 해당 매개변수를 설정하는 개체를 구성하는 방법도 보여줍니다.

PHP

그러면 코드는 아래의 생성 Google_Client() 인증 요청 파라미터를 정의하는 오브젝트.

당신의 client_secret.json 파일에서 그 객체가 사용하는 정보는 응용 프로그램을 식별합니다. (참조 인증 자격 증명을 만들고 그 파일에 대한 더 많은 것을 위해.) 객체는 응용 프로그램에 액세스 할 수있는 권한과 구글의 OAuth 2.0 서버의 응답을 처리하는 응용 프로그램의 인증 엔드 포인트의 URL을 요청하는 범위를 식별합니다. 마지막으로, 코드는 옵션 설정 access_typeinclude_granted_scopes 매개 변수를.

예를 들어 다음 코드는 사용자의 Google 드라이브에 대한 읽기 전용 오프라인 액세스를 요청합니다.

$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
// offline access will give you both an access and refresh token so that
// your app can refresh the access token without user interaction.
$client->setAccessType('offline');
// Using "consent" ensures that your application always receives a refresh token.
// If you are not using offline access, you can omit this.
$client->setApprovalPrompt("consent");
$client->setIncludeGrantedScopes(true);   // incremental auth

요청은 다음 정보를 지정합니다.

매개변수
client_id 필수의

애플리케이션의 클라이언트 ID입니다. 당신은이 값 찾을 수 있습니다 API ConsoleCredentials page.

PHP에서 전화 setAuthConfig client_secret.json 파일에서 인증 자격 증명을로드하는 기능.

$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
redirect_uri 필수의

사용자가 권한 부여 흐름을 완료한 후 API 서버가 사용자를 리디렉션하는 위치를 결정합니다. 값은 정확하게 고객의에 구성하여 OAuth 2.0 클라이언트에 대한 인증 된 리디렉션 된 URI 중 하나와 일치해야합니다 API ConsoleCredentials page. 이 값은 제공을 위해 승인 된 리디렉션 URI와 일치하지 않는 경우 client_id 당신은 얻을 것이다 redirect_uri_mismatch 오류입니다.

참고 그 http 또는 https 방식의 경우, 후행 슬래시 ( ' / ') 모두 일치해야합니다.

PHP에서이 값을 설정하려면 전화 setRedirectUri 기능을. 당신이 제공에 대한 유효한 리디렉션 URI를 지정해야합니다 client_id .

$client->setRedirectUri('https://oauth2.example.com/code');
scope 필수의

애플리케이션이 사용자를 대신하여 액세스할 수 있는 리소스를 식별하는 공백으로 구분된 범위 목록입니다. 이 값은 Google이 사용자에게 표시하는 동의 화면을 알려줍니다.

범위를 사용하면 애플리케이션이 필요한 리소스에 대한 액세스만 요청할 수 있고 사용자가 애플리케이션에 부여하는 액세스 권한의 양을 제어할 수 있습니다. 따라서 요청된 범위의 수와 사용자 동의를 얻을 가능성 사이에는 반비례 관계가 있습니다.

PHP에서이 값을 설정하려면 전화 addScope 기능 :

$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);

가능하면 애플리케이션이 컨텍스트에서 권한 부여 범위에 대한 액세스를 요청하는 것이 좋습니다. 를 통해 상황에서 사용자 데이터에 대한 액세스를 요청하여 증분 인증 , 당신은 당신의 응용 프로그램이 요청하는 액세스해야하는 이유를보다 쉽게에 사용자가 이해하는 데 도움이.

access_type 추천

사용자가 브라우저에 없을 때 애플리케이션이 액세스 토큰을 새로 고칠 수 있는지 여부를 나타냅니다. 유효한 매개 변수 값은 online 디폴트 값 및 인 offline .

에 값을 설정 offline 사용자가 브라우저에 존재하지 않을 때 응용 프로그램 요구 사항이 액세스 토큰을 새로 고침합니다. 이것은 이 문서의 뒷부분에서 설명하는 액세스 토큰을 새로 고치는 방법입니다. 이 값은 토큰 새로 고침 처음으로 액세스 토큰을 반환 구글 인증 서버에 지시 토큰 응용 프로그램 교환 인증 코드가.

PHP에서이 값을 설정하려면 전화 setAccessType 기능 :

$client->setAccessType('offline');
state 추천

애플리케이션이 권한 부여 요청과 권한 부여 서버의 응답 사이의 상태를 유지하기 위해 사용하는 문자열 값을 지정합니다. 서버는 당신이로 보내 정확한 값 반환 name=value 의 URL 쿼리 구성 요소의 쌍 ( ? )의 redirect_uri 에 사용자의 동의 후 또는 응용 프로그램의 액세스 요청을 거부합니다.

이 매개변수는 사용자를 애플리케이션의 올바른 리소스로 안내하고, 임시값을 보내고, 사이트 간 요청 위조를 완화하는 것과 같은 여러 목적으로 사용할 수 있습니다. 하여 이후 redirect_uri 추측 할 수있다하는 사용 state 값은 인입 접속 인증 요청의 결과인지하여 확신을 높일 수있다. 임의의 문자열을 생성하거나 쿠키의 해시 또는 클라이언트의 상태를 캡처하는 다른 값을 인코딩하는 경우 응답을 검증하여 요청과 응답이 동일한 브라우저에서 시작되었는지 추가로 확인하여 교차 사이트와 같은 공격으로부터 보호할 수 있습니다. 위조요청. 참고 항목 오픈 ID 연결 작성하고 확인하는 방법의 예를 들어 문서를 state 토큰을.

PHP에서이 값을 설정하려면 전화 setState 기능 :

$client->setState($sample_passthrough_value);
include_granted_scopes 선택 과목

애플리케이션이 컨텍스트에서 추가 범위에 대한 액세스를 요청하기 위해 증분 권한 부여를 사용할 수 있습니다. 당신이이 매개 변수의 값을 설정하면 true 및 승인 요청이 승인, 새로운 액세스 토큰은 사용자가 이전 응용 프로그램 액세스 권한이 부여되는 모든 범위를 커버합니다. 참고 항목 증가 인증 예제 섹션을 참조하십시오.

PHP에서이 값을 설정하려면 전화 setIncludeGrantedScopes 기능 :

$client->setIncludeGrantedScopes(true);
login_hint 선택 과목

애플리케이션이 인증하려는 사용자를 알고 있는 경우 이 매개변수를 사용하여 Google 인증 서버에 힌트를 제공할 수 있습니다. 서버는 로그인 양식에서 이메일 필드를 미리 채우거나 적절한 다중 로그인 세션을 선택하여 로그인 흐름을 단순화하기 위해 힌트를 사용합니다.

이메일 주소 또는 매개 변수 값을 설정 sub 사용자의 Google ID에 해당 식별자.

PHP에서이 값을 설정하려면 전화 setLoginHint 기능 :

$client->setLoginHint('None');
prompt 선택 과목

사용자에게 표시할 프롬프트의 공백으로 구분되고 대소문자를 구분하는 목록입니다. 이 매개변수를 지정하지 않으면 프로젝트에서 처음으로 액세스를 요청할 때만 사용자에게 메시지가 표시됩니다. 참조 다시 동의를 묻 자세한 내용은.

PHP에서이 값을 설정하려면 전화 setApprovalPrompt 기능 :

$client->setApprovalPrompt('consent');

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

none 인증 또는 동의 화면을 표시하지 마십시오. 다른 값으로 지정하면 안 됩니다.
consent 사용자에게 동의를 요청합니다.
select_account 사용자에게 계정을 선택하라는 메시지를 표시합니다.

파이썬

다음 코드는 사용 google-auth-oauthlib.flow 인증 요청을 구성하는 모듈.

코드는 구축 Flow 이 후 다운로드하는 client_secret.json 파일에서 응용 프로그램을 사용하여 정보를 식별하는 객체, 인증 자격 증명을 만들기를 . 이 객체는 또한 애플리케이션이 액세스 권한을 요청하는 범위와 Google OAuth 2.0 서버의 응답을 처리할 애플리케이션의 인증 엔드포인트에 대한 URL을 식별합니다. 마지막으로, 코드는 옵션 설정 access_typeinclude_granted_scopes 매개 변수를.

예를 들어 다음 코드는 사용자의 Google 드라이브에 대한 읽기 전용 오프라인 액세스를 요청합니다.

import google.oauth2.credentials
import google_auth_oauthlib.flow

# Use the client_secret.json file to identify the application requesting
# authorization. The client ID (from that file) and access scopes are required.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])

# Indicate where the API server will redirect the user after the user completes
# the authorization flow. The redirect URI is required. The value must exactly
# match one of the authorized redirect URIs for the OAuth 2.0 client, which you
# configured in the API Console. If this value doesn't match an authorized URI,
# you will get a 'redirect_uri_mismatch' error.
flow.redirect_uri = 'https://www.example.com/oauth2callback'

# Generate URL for request to Google's OAuth 2.0 server.
# Use kwargs to set optional request parameters.
authorization_url, state = flow.authorization_url(
    # Enable offline access so that you can refresh an access token without
    # re-prompting the user for permission. Recommended for web server apps.
    access_type='offline',
    # Enable incremental authorization. Recommended as a best practice.
    include_granted_scopes='true')

요청은 다음 정보를 지정합니다.

매개변수
client_id 필수의

애플리케이션의 클라이언트 ID입니다. 당신은이 값 찾을 수 있습니다 API ConsoleCredentials page.

파이썬에서 전화 from_client_secrets_file client_secret.json 파일에서 클라이언트 ID를 검색하는 방법을. (당신은 또한 사용할 수 있습니다 from_client_config 원래 클라이언트 비밀 파일에 등장하지만, 파일 자체에 액세스하지 않는 클라이언트 구성을 전달 방법을.)

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])
redirect_uri 필수의

사용자가 권한 부여 흐름을 완료한 후 API 서버가 사용자를 리디렉션하는 위치를 결정합니다. 값은 정확하게 고객의에 구성하여 OAuth 2.0 클라이언트에 대한 인증 된 리디렉션 된 URI 중 하나와 일치해야합니다 API ConsoleCredentials page. 이 값은 제공을 위해 승인 된 리디렉션 URI와 일치하지 않는 경우 client_id 당신은 얻을 것이다 redirect_uri_mismatch 오류입니다.

참고 그 http 또는 https 방식의 경우, 후행 슬래시 ( ' / ') 모두 일치해야합니다.

파이썬에서이 값을 설정하려면 설정 flow 객체의 redirect_uri 속성을 :

flow.redirect_uri = 'https://oauth2.example.com/code'
scope 필수의

애플리케이션이 사용자를 대신하여 액세스할 수 있는 리소스를 식별하는 범위 목록입니다. 이 값은 Google이 사용자에게 표시하는 동의 화면을 알려줍니다.

범위를 사용하면 애플리케이션이 필요한 리소스에 대한 액세스만 요청할 수 있고 사용자가 애플리케이션에 부여하는 액세스 권한의 양을 제어할 수 있습니다. 따라서 요청된 범위의 수와 사용자 동의를 얻을 가능성 사이에는 반비례 관계가 있습니다.

파이썬에서, 당신은 설정하는 데 사용하는 것과 동일한 방법을 사용 client_id 범위의 목록을 지정합니다.

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])

가능하면 애플리케이션이 컨텍스트에서 권한 부여 범위에 대한 액세스를 요청하는 것이 좋습니다. 를 통해 상황에서 사용자 데이터에 대한 액세스를 요청하여 증분 인증 , 당신은 당신의 응용 프로그램이 요청하는 액세스해야하는 이유를보다 쉽게에 사용자가 이해하는 데 도움이.

access_type 추천

사용자가 브라우저에 없을 때 애플리케이션이 액세스 토큰을 새로 고칠 수 있는지 여부를 나타냅니다. 유효한 매개 변수 값은 online 디폴트 값 및 인 offline .

에 값을 설정 offline 사용자가 브라우저에 존재하지 않을 때 응용 프로그램 요구 사항이 액세스 토큰을 새로 고침합니다. 이것은 이 문서의 뒷부분에서 설명하는 액세스 토큰을 새로 고치는 방법입니다. 이 값은 토큰 새로 고침 처음으로 액세스 토큰을 반환 구글 인증 서버에 지시 토큰 응용 프로그램 교환 인증 코드가.

파이썬에서 설정 access_type 지정하여 매개 변수를 access_type 호출 할 때 키워드 인수로 flow.authorization_url 방법 :

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
state 추천

애플리케이션이 권한 부여 요청과 권한 부여 서버의 응답 사이의 상태를 유지하기 위해 사용하는 문자열 값을 지정합니다. 서버는 당신이로 보내 정확한 값 반환 name=value 의 URL 쿼리 구성 요소의 쌍 ( ? )의 redirect_uri 에 사용자의 동의 후 또는 응용 프로그램의 액세스 요청을 거부합니다.

이 매개변수는 사용자를 애플리케이션의 올바른 리소스로 안내하고, 임시값을 보내고, 사이트 간 요청 위조를 완화하는 것과 같은 여러 목적으로 사용할 수 있습니다. 하여 이후 redirect_uri 추측 할 수있다하는 사용 state 값은 인입 접속 인증 요청의 결과인지하여 확신을 높일 수있다. 임의의 문자열을 생성하거나 쿠키의 해시 또는 클라이언트의 상태를 캡처하는 다른 값을 인코딩하는 경우 응답을 검증하여 요청과 응답이 동일한 브라우저에서 시작되었는지 추가로 확인하여 교차 사이트와 같은 공격으로부터 보호할 수 있습니다. 위조요청. 참고 항목 오픈 ID 연결 작성하고 확인하는 방법의 예를 들어 문서를 state 토큰을.

파이썬에서 설정 state 를 지정하여 매개 변수를 state 호출 할 때 키워드 인수로 flow.authorization_url 방법 :

authorization_url, state = flow.authorization_url(
    access_type='offline',
    state=sample_passthrough_value,
    include_granted_scopes='true')
include_granted_scopes 선택 과목

애플리케이션이 컨텍스트에서 추가 범위에 대한 액세스를 요청하기 위해 증분 권한 부여를 사용할 수 있습니다. 당신이이 매개 변수의 값을 설정하면 true 및 승인 요청이 승인, 새로운 액세스 토큰은 사용자가 이전 응용 프로그램 액세스 권한이 부여되는 모든 범위를 커버합니다. 참고 항목 증가 인증 예제 섹션을 참조하십시오.

파이썬에서 설정 include_granted_scopes 매개 변수를 지정하여 include_granted_scopes 호출 할 때 키워드 인수로 flow.authorization_url 방법 :

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
login_hint 선택 과목

애플리케이션이 인증하려는 사용자를 알고 있는 경우 이 매개변수를 사용하여 Google 인증 서버에 힌트를 제공할 수 있습니다. 서버는 로그인 양식에서 이메일 필드를 미리 채우거나 적절한 다중 로그인 세션을 선택하여 로그인 흐름을 단순화하기 위해 힌트를 사용합니다.

이메일 주소 또는 매개 변수 값을 설정 sub 사용자의 Google ID에 해당 식별자.

파이썬에서 설정 login_hint 지정하여 매개 변수를 login_hint 호출 할 때 키워드 인수로 flow.authorization_url 방법 :

authorization_url, state = flow.authorization_url(
    access_type='offline',
    login_hint='None',
    include_granted_scopes='true')
prompt 선택 과목

사용자에게 표시할 프롬프트의 공백으로 구분되고 대소문자를 구분하는 목록입니다. 이 매개변수를 지정하지 않으면 프로젝트에서 처음으로 액세스를 요청할 때만 사용자에게 메시지가 표시됩니다. 참조 다시 동의를 묻 자세한 내용은.

파이썬에서 설정 prompt 지정하여 매개 변수를 prompt 호출 할 때 키워드 인수로 flow.authorization_url 방법 :

authorization_url, state = flow.authorization_url(
      access_type='offline',
      prompt='consent',
      include_granted_scopes='true')

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

none 인증 또는 동의 화면을 표시하지 마십시오. 다른 값으로 지정하면 안 됩니다.
consent 사용자에게 동의를 요청합니다.
select_account 사용자에게 계정을 선택하라는 메시지를 표시합니다.

루비

생성한 client_secrets.json 파일을 사용하여 애플리케이션에서 클라이언트 개체를 구성합니다. 클라이언트 개체를 구성할 때 OAuth 2.0 서버의 응답을 처리할 애플리케이션의 인증 끝점에 대한 URL과 함께 애플리케이션이 액세스해야 하는 범위를 지정합니다.

예를 들어 다음 코드는 사용자의 Google 드라이브에 대한 읽기 전용 오프라인 액세스를 요청합니다.

require 'google/apis/drive_v2'
require 'google/api_client/client_secrets'

client_secrets = Google::APIClient::ClientSecrets.load
auth_client = client_secrets.to_authorization
auth_client.update!(
  :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
  :redirect_uri => 'http://www.example.com/oauth2callback',
  :additional_parameters => {
    "access_type" => "offline",         # offline access
    "include_granted_scopes" => "true"  # incremental auth
  }
)

애플리케이션은 클라이언트 개체를 사용하여 인증 요청 URL 생성 및 HTTP 요청에 액세스 토큰 적용과 같은 OAuth 2.0 작업을 수행합니다.

HTTP/휴식

구글의 OAuth 2.0 엔드 포인트에 있습니다 https://accounts.google.com/o/oauth2/v2/auth . 이 끝점은 HTTPS를 통해서만 액세스할 수 있습니다. 일반 HTTP 연결은 거부됩니다.

Google 인증 서버는 웹 서버 애플리케이션에 대해 다음 쿼리 문자열 매개변수를 지원합니다.

매개변수
client_id 필수의

애플리케이션의 클라이언트 ID입니다. 당신은이 값 찾을 수 있습니다 API ConsoleCredentials page.

redirect_uri 필수의

사용자가 권한 부여 흐름을 완료한 후 API 서버가 사용자를 리디렉션하는 위치를 결정합니다. 값은 정확하게 고객의에 구성하여 OAuth 2.0 클라이언트에 대한 인증 된 리디렉션 된 URI 중 하나와 일치해야합니다 API ConsoleCredentials page. 이 값은 제공을 위해 승인 된 리디렉션 URI와 일치하지 않는 경우 client_id 당신은 얻을 것이다 redirect_uri_mismatch 오류입니다.

참고 그 http 또는 https 방식의 경우, 후행 슬래시 ( ' / ') 모두 일치해야합니다.

response_type 필수의

Google OAuth 2.0 엔드포인트가 인증 코드를 반환하는지 여부를 결정합니다.

매개 변수 값 설정 code 웹 서버 응용 프로그램을.

scope 필수의

애플리케이션이 사용자를 대신하여 액세스할 수 있는 리소스를 식별하는 공백으로 구분된 범위 목록입니다. 이 값은 Google이 사용자에게 표시하는 동의 화면을 알려줍니다.

범위를 사용하면 애플리케이션이 필요한 리소스에 대한 액세스만 요청할 수 있고 사용자가 애플리케이션에 부여하는 액세스 권한의 양을 제어할 수 있습니다. 따라서 요청된 범위의 수와 사용자 동의를 얻을 가능성 사이에는 반비례 관계가 있습니다.

가능하면 애플리케이션이 컨텍스트에서 권한 부여 범위에 대한 액세스를 요청하는 것이 좋습니다. 를 통해 상황에서 사용자 데이터에 대한 액세스를 요청하여 증분 인증 , 당신은 당신의 응용 프로그램이 요청하는 액세스해야하는 이유를보다 쉽게에 사용자가 이해하는 데 도움이.

access_type 추천

사용자가 브라우저에 없을 때 애플리케이션이 액세스 토큰을 새로 고칠 수 있는지 여부를 나타냅니다. 유효한 매개 변수 값은 online 디폴트 값 및 인 offline .

에 값을 설정 offline 사용자가 브라우저에 존재하지 않을 때 응용 프로그램 요구 사항이 액세스 토큰을 새로 고침합니다. 이것은 이 문서의 뒷부분에서 설명하는 액세스 토큰을 새로 고치는 방법입니다. 이 값은 토큰 새로 고침 처음으로 액세스 토큰을 반환 구글 인증 서버에 지시 토큰 응용 프로그램 교환 인증 코드가.

state 추천

애플리케이션이 권한 부여 요청과 권한 부여 서버의 응답 사이의 상태를 유지하기 위해 사용하는 문자열 값을 지정합니다. 서버는 당신이로 보내 정확한 값 반환 name=value 의 URL 쿼리 구성 요소의 쌍 ( ? )의 redirect_uri 에 사용자의 동의 후 또는 응용 프로그램의 액세스 요청을 거부합니다.

이 매개변수는 사용자를 애플리케이션의 올바른 리소스로 안내하고, 임시값을 보내고, 사이트 간 요청 위조를 완화하는 것과 같은 여러 목적으로 사용할 수 있습니다. 하여 이후 redirect_uri 추측 할 수있다하는 사용 state 값은 인입 접속 인증 요청의 결과인지하여 확신을 높일 수있다. 임의의 문자열을 생성하거나 쿠키의 해시 또는 클라이언트의 상태를 캡처하는 다른 값을 인코딩하는 경우 응답을 검증하여 요청과 응답이 동일한 브라우저에서 시작되었는지 추가로 확인하여 교차 사이트와 같은 공격으로부터 보호할 수 있습니다. 위조요청. 참고 항목 오픈 ID 연결 작성하고 확인하는 방법의 예를 들어 문서를 state 토큰을.

include_granted_scopes 선택 과목

애플리케이션이 증분 권한 부여를 사용하여 컨텍스트에서 추가 범위에 대한 액세스를 요청할 수 있도록 합니다. 당신이이 매개 변수의 값을 설정하면 true 및 승인 요청이 승인, 새로운 액세스 토큰은 사용자가 이전 응용 프로그램 액세스 권한이 부여되는 모든 범위를 커버합니다. 참고 항목 증가 인증 예제 섹션을 참조하십시오.

login_hint 선택 과목

애플리케이션이 인증하려는 사용자를 알고 있는 경우 이 매개변수를 사용하여 Google 인증 서버에 힌트를 제공할 수 있습니다. 서버는 로그인 양식에서 이메일 필드를 미리 채우거나 적절한 다중 로그인 세션을 선택하여 로그인 흐름을 단순화하기 위해 힌트를 사용합니다.

이메일 주소 또는 매개 변수 값을 설정 sub 사용자의 Google ID에 해당 식별자.

prompt 선택 과목

사용자에게 표시할 프롬프트의 공백으로 구분되고 대소문자를 구분하는 목록입니다. 이 매개변수를 지정하지 않으면 프로젝트에서 처음으로 액세스를 요청할 때만 사용자에게 메시지가 표시됩니다. 참조 다시 동의를 묻 자세한 내용은.

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

none 인증 또는 동의 화면을 표시하지 마십시오. 다른 값으로 지정하면 안 됩니다.
consent 사용자에게 동의를 요청합니다.
select_account 사용자에게 계정을 선택하라는 메시지를 표시합니다.

2단계: Google의 OAuth 2.0 서버로 리디렉션

사용자를 Google의 OAuth 2.0 서버로 리디렉션하여 인증 및 권한 부여 프로세스를 시작합니다. 일반적으로 이는 애플리케이션이 사용자 데이터에 처음 액세스해야 할 때 발생합니다. 의 경우 증가 허가 응용 프로그램이 먼저 아직 액세스 권한이 없음을 액세스 추가 리소스를 필요로 할 때,이 단계가 발생합니다.

PHP

  1. : 구글의 OAuth 2.0 서버에서 요청에 액세스 할 수있는 URL 생성
    $auth_url = $client->createAuthUrl();
  2. 에 사용자를 리디렉션 $auth_url :
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

파이썬

이 예에서는 Flask 웹 애플리케이션 프레임워크를 사용하여 사용자를 인증 URL로 리디렉션하는 방법을 보여줍니다.

return flask.redirect(authorization_url)

루비

  1. : 구글의 OAuth 2.0 서버에서 요청에 액세스 할 수있는 URL 생성
    auth_uri = auth_client.authorization_uri.to_s
  2. 사용자가 리디렉션 auth_uri .

HTTP/휴식

Google 인증 서버로의 샘플 리디렉션

가독성을 위해 줄 바꿈과 공백이 있는 예제 URL이 아래에 나와 있습니다.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 access_type=offline&
 include_granted_scopes=true&
 response_type=code&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

요청 URL을 만든 후 사용자를 해당 URL로 리디렉션합니다.

Google의 OAuth 2.0 서버는 사용자를 인증하고 애플리케이션이 요청된 범위에 액세스할 수 있도록 사용자의 동의를 얻습니다. 응답은 지정한 리디렉션 URL을 사용하여 애플리케이션으로 다시 전송됩니다.

3단계: Google에서 사용자에게 동의를 요청합니다.

이 단계에서 사용자는 요청된 액세스 권한을 애플리케이션에 부여할지 여부를 결정합니다. 이 단계에서 Google은 사용자의 인증 자격 증명으로 액세스 권한을 요청하는 애플리케이션 및 Google API 서비스의 이름과 부여할 액세스 범위의 요약을 보여주는 동의 창을 표시합니다. 그런 다음 사용자는 애플리케이션에서 요청한 하나 이상의 범위에 대한 액세스 권한 부여에 동의하거나 요청을 거부할 수 있습니다.

애플리케이션은 액세스가 부여되었는지 여부를 나타내는 Google OAuth 2.0 서버의 응답을 기다리기 때문에 이 단계에서 아무 것도 할 필요가 없습니다. 그 응답은 다음 단계에서 설명됩니다.

오류

Google의 OAuth 2.0 권한 부여 엔드포인트에 대한 요청은 예상되는 인증 및 권한 부여 흐름 대신 사용자에게 표시되는 오류 메시지를 표시할 수 있습니다. 일반적인 오류 코드 및 제안된 해결 방법은 아래에 나열되어 있습니다.

admin_policy_enforced

Google 계정은 Google Workspace 관리자의 정책으로 인해 요청된 하나 이상의 범위를 승인할 수 없습니다. 구글 작업 공간 관리자 도움말을 참조하십시오 타사 및 내부 애플리케이션은 구글 작업 공간 데이터에 액세스 제어 액세스가 명시 적으로 OAuth 클라이언트 ID에 부여 될 때까지 관리자가 모든 범위 또는 민감하고 제한된 범위에 대한 액세스를 제한 할 수있는 방법에 대한 자세한 정보를.

disallowed_useragent

권한 부여 엔드 포인트는 구글에 의해 허용되지 임베디드 사용자 에이전트 내부에 표시됩니다 의 OAuth 2.0 정책 .

기계적 인조 인간

에 승인 요청을 열 때 안드로이드 개발자는이 오류 메시지가 발생할 수 있습니다 android.webkit.WebView . 개발자는 대신 같은 안드로이드 라이브러리를 사용한다 구글 안드로이드에 대한 로그인 또는 오픈 ID 재단의 안드로이드에 대한 AppAuth을 .

웹 개발자는 Android 앱이 포함된 사용자 에이전트에서 일반 웹 링크를 열고 사용자가 사이트에서 Google의 OAuth 2.0 인증 끝점으로 이동할 때 이 오류가 발생할 수 있습니다. 개발자는 일반적으로 링크가 모두 포함하는 운영 체제의 기본 링크 처리기에서 열 수 있어야 안드로이드 앱 링크 핸들러 또는 기본 브라우저 응용 프로그램을. 안드로이드 사용자 정의 탭의 라이브러리는 지원되는 옵션입니다.

iOS

에 승인 요청을 열 때 iOS 및 맥 OS 개발자는이 오류가 발생할 수 있습니다 WKWebView . 개발자는 대신 같은 아이폰 OS 라이브러리를 사용한다 구글 iOS 용 로그인 또는 오픈 ID 재단의 iOS 용 AppAuth .

iOS 또는 macOS 앱이 내장된 사용자 에이전트에서 일반 웹 링크를 열고 사용자가 사이트에서 Google의 OAuth 2.0 인증 엔드포인트로 이동할 때 웹 개발자에게 이 오류가 발생할 수 있습니다. 개발자는 일반적으로 링크가 모두 포함하는 운영 체제의 기본 링크 처리기에서 열 수 있도록해야 유니버설 링크 핸들러 또는 기본 브라우저 응용 프로그램을. SFSafariViewController 라이브러리는 지원되는 옵션입니다.

org_internal

요청의 OAuth 클라이언트 ID는 특정 구글 계정에 대한 액세스 제한 프로젝트의 일부입니다 Google 클라우드 조직 . 이 구성 옵션에 대한 자세한 내용은 참조 사용자 유형의 당신의 OAuth 동의 화면 도움말까지 설정 섹션을.

redirect_uri_mismatch

redirect_uri 승인 요청 전달은 OAuth 클라이언트 ID에 대한 권한이 부여 된 리디렉션 URI와 일치하지 않습니다. 평가는 현재의 리디렉션 URI를 허가 Google API Console Credentials page.

4단계: OAuth 2.0 서버 응답 처리

OAuth 2.0 서버는 요청에 지정된 URL을 사용하여 애플리케이션의 액세스 요청에 응답합니다.

사용자가 액세스 요청을 승인하면 응답에 인증 코드가 포함됩니다. 사용자가 요청을 승인하지 않으면 응답에 오류 메시지가 포함됩니다. 웹 서버에 반환된 인증 코드 또는 오류 메시지는 아래와 같이 쿼리 문자열에 나타납니다.

오류 응답:

https://oauth2.example.com/auth?error=access_denied

승인 코드 응답:

https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7

샘플 OAuth 2.0 서버 응답

Google 드라이브에 있는 파일의 메타데이터를 보기 위해 읽기 전용 액세스 권한을 요청하는 다음 샘플 URL을 클릭하여 이 흐름을 테스트할 수 있습니다.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 access_type=offline&
 include_granted_scopes=true&
 response_type=code&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

After completing the OAuth 2.0 flow, you should be redirected to http://localhost/oauth2callback , which will likely yield a 404 NOT FOUND error unless your local machine serves a file at that address. The next step provides more detail about the information returned in the URI when the user is redirected back to your application.

Step 5: Exchange authorization code for refresh and access tokens

After the web server receives the authorization code, it can exchange the authorization code for an access token.

PHP

To exchange an authorization code for an access token, use the authenticate method:

$client->authenticate($_GET['code']);

You can retrieve the access token with the getAccessToken method:

$access_token = $client->getAccessToken();

Python

On your callback page, use the google-auth library to verify the authorization server response. Then, use the flow.fetch_token method to exchange the authorization code in that response for an access token:

state = flask.session['state']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'],
    state=state)
flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

authorization_response = flask.request.url
flow.fetch_token(authorization_response=authorization_response)

# Store the credentials in the session.
# ACTION ITEM for developers:
#     Store user's access and refresh tokens in your data store if
#     incorporating this code into your real app.
credentials = flow.credentials
flask.session['credentials'] = {
    'token': credentials.token,
    'refresh_token': credentials.refresh_token,
    'token_uri': credentials.token_uri,
    'client_id': credentials.client_id,
    'client_secret': credentials.client_secret,
    'scopes': credentials.scopes}

Ruby

To exchange an authorization code for an access token, use the fetch_access_token! method:

auth_client.code = auth_code
auth_client.fetch_access_token!

HTTP/REST

To exchange an authorization code for an access token, call the https://oauth2.googleapis.com/token endpoint and set the following parameters:

Fields
client_id The client ID obtained from the API ConsoleCredentials page.
client_secret The client secret obtained from the API ConsoleCredentials page.
code The authorization code returned from the initial request.
grant_type As defined in the OAuth 2.0 specification , this field's value must be set to authorization_code .
redirect_uri One of the redirect URIs listed for your project in the API ConsoleCredentials page for the given client_id .

The following snippet shows a sample request:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code

Google responds to this request by returning a JSON object that contains a short-lived access token and a refresh token. Note that the refresh token is only returned if your application set the access_type parameter to offline in the initial request to Google's authorization server .

The response contains the following fields:

Fields
access_token The token that your application sends to authorize a Google API request.
expires_in The remaining lifetime of the access token in seconds.
refresh_token A token that you can use to obtain a new access token. Refresh tokens are valid until the user revokes access. Again, this field is only present in this response if you set the access_type parameter to offline in the initial request to Google's authorization server.
scope The scopes of access granted by the access_token expressed as a list of space-delimited, case-sensitive strings.
token_type The type of token returned. At this time, this field's value is always set to Bearer .

The following snippet shows a sample response:

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "token_type": "Bearer",
  "scope": "https://www.googleapis.com/auth/drive.metadata.readonly",
  "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}

Calling Google APIs

PHP

Use the access token to call Google APIs by completing the following steps:

  1. If you need to apply an access token to a new Google_Client object—for example, if you stored the access token in a user session—use the setAccessToken method:
    $client->setAccessToken($access_token);
  2. Build a service object for the API that you want to call. You build a service object by providing an authorized Google_Client object to the constructor for the API you want to call. For example, to call the Drive API:
    $drive = new Google_Service_Drive($client);
  3. Make requests to the API service using the interface provided by the service object . For example, to list the files in the authenticated user's Google Drive:
    $files = $drive->files->listFiles(array())->getItems();

Python

After obtaining an access token, your application can use that token to authorize API requests on behalf of a given user account or service account. Use the user-specific authorization credentials to build a service object for the API that you want to call, and then use that object to make authorized API requests.

  1. Build a service object for the API that you want to call. You build a service object by calling the googleapiclient.discovery library's build method with the name and version of the API and the user credentials: For example, to call version 2 of the Drive API:
    from googleapiclient.discovery import build
    
    drive = build('drive', 'v2', credentials=credentials)
  2. Make requests to the API service using the interface provided by the service object . For example, to list the files in the authenticated user's Google Drive:
    files = drive.files().list().execute()

Ruby

Use the auth_client object to call Google APIs by completing the following steps:

  1. Build a service object for the API that you want to call. For example, to call version 2 of the Drive API:
    drive = Google::Apis::DriveV2::DriveService.new
  2. Set the credentials on the service:
    drive.authorization = auth_client
  3. Make requests to the API service using the interface provided by the service object . For example, to list the files in the authenticated user's Google Drive:
    files = drive.list_files

Alternately, authorization can be provided on a per-method basis by supplying the options parameter to a method:

files = drive.list_files(options: { authorization: auth_client })

HTTP/REST

After your application obtains an access token, you can use the token to make calls to a Google API on behalf of a given user account if the scope(s) of access required by the API have been granted. To do this, include the access token in a request to the API by including either an access_token query parameter or an Authorization HTTP header Bearer value. When possible, the HTTP header is preferable, because query strings tend to be visible in server logs. In most cases you can use a client library to set up your calls to Google APIs (for example, when calling the Drive Files API ).

You can try out all the Google APIs and view their scopes at the OAuth 2.0 Playground .

HTTP GET examples

A call to the drive.files endpoint (the Drive Files API) using the Authorization: Bearer HTTP header might look like the following. Note that you need to specify your own access token:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

Here is a call to the same API for the authenticated user using the access_token query string parameter:

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

curl examples

You can test these commands with the curl command-line application. Here's an example that uses the HTTP header option (preferred):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

Or, alternatively, the query string parameter option:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

Complete example

The following example prints a JSON-formatted list of files in a user's Google Drive after the user authenticates and gives consent for the application to access the user's Drive metadata.

PHP

To run this example:

  1. In the API Console, add the URL of the local machine to the list of redirect URLs. For example, add http://localhost:8080 .
  2. Create a new directory and change to it. For example:
    mkdir ~/php-oauth2-example
    cd ~/php-oauth2-example
  3. Install the Google API Client Library for PHP using Composer :
    composer require google/apiclient:^2.0
  4. Create the files index.php and oauth2callback.php with the content below.
  5. Run the example with a web server configured to serve PHP. If you use PHP 5.4 or newer, you can use PHP's built-in test web server:
    php -S localhost:8080 ~/php-oauth2-example

index.php

<?php
require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google_Client();
$client->setAuthConfig('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);

if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
  $client->setAccessToken($_SESSION['access_token']);
  $drive = new Google_Service_Drive($client);
  $files = $drive->files->listFiles(array())->getItems();
  echo json_encode($files);
} else {
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

oauth2callback.php

<?php
require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);

if (! isset($_GET['code'])) {
  $auth_url = $client->createAuthUrl();
  header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
  $client->authenticate($_GET['code']);
  $_SESSION['access_token'] = $client->getAccessToken();
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

Python

This example uses the Flask framework. It runs a web application at http://localhost:8080 that lets you test the OAuth 2.0 flow. If you go to that URL, you should see four links:

  • Test an API request: This link points to a page that tries to execute a sample API request. If necessary, it starts the authorization flow. If successful, the page displays the API response.
  • Test the auth flow directly: This link points to a page that tries to send the user through the authorization flow . The app requests permission to submit authorized API requests on the user's behalf.
  • Revoke current credentials: This link points to a page that revokes permissions that the user has already granted to the application.
  • Clear Flask session credentials: This link clears authorization credentials that are stored in the Flask session. This lets you see what would happen if a user who had already granted permission to your app tried to execute an API request in a new session. It also lets you see the API response your app would get if a user had revoked permissions granted to your app, and your app still tried to authorize a request with a revoked access token.
# -*- coding: utf-8 -*-

import os
import flask
import requests

import google.oauth2.credentials
import google_auth_oauthlib.flow
import googleapiclient.discovery

# This variable specifies the name of a file that contains the OAuth 2.0
# information for this application, including its client_id and client_secret.
CLIENT_SECRETS_FILE = "client_secret.json"

# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account and requires requests to use an SSL connection.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
API_SERVICE_NAME = 'drive'
API_VERSION = 'v2'

app = flask.Flask(__name__)
# Note: A secret key is included in the sample so that it works.
# If you use this code in your application, replace this with a truly secret
# key. See https://flask.palletsprojects.com/quickstart/#sessions.
app.secret_key = 'REPLACE ME - this value is here as a placeholder.'


@app.route('/')
def index():
  return print_index_table()


@app.route('/test')
def test_api_request():
  if 'credentials' not in flask.session:
    return flask.redirect('authorize')

  # Load credentials from the session.
  credentials = google.oauth2.credentials.Credentials(
      **flask.session['credentials'])

  drive = googleapiclient.discovery.build(
      API_SERVICE_NAME, API_VERSION, credentials=credentials)

  files = drive.files().list().execute()

  # Save credentials back to session in case access token was refreshed.
  # ACTION ITEM: In a production app, you likely want to save these
  #              credentials in a persistent database instead.
  flask.session['credentials'] = credentials_to_dict(credentials)

  return flask.jsonify(**files)


@app.route('/authorize')
def authorize():
  # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps.
  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE, scopes=SCOPES)

  # The URI created here must exactly match one of the authorized redirect URIs
  # for the OAuth 2.0 client, which you configured in the API Console. If this
  # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch'
  # error.
  flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

  authorization_url, state = flow.authorization_url(
      # Enable offline access so that you can refresh an access token without
      # re-prompting the user for permission. Recommended for web server apps.
      access_type='offline',
      # Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes='true')

  # Store the state so the callback can verify the auth server response.
  flask.session['state'] = state

  return flask.redirect(authorization_url)


@app.route('/oauth2callback')
def oauth2callback():
  # Specify the state when creating the flow in the callback so that it can
  # verified in the authorization server response.
  state = flask.session['state']

  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
  flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

  # Use the authorization server's response to fetch the OAuth 2.0 tokens.
  authorization_response = flask.request.url
  flow.fetch_token(authorization_response=authorization_response)

  # Store credentials in the session.
  # ACTION ITEM: In a production app, you likely want to save these
  #              credentials in a persistent database instead.
  credentials = flow.credentials
  flask.session['credentials'] = credentials_to_dict(credentials)

  return flask.redirect(flask.url_for('test_api_request'))


@app.route('/revoke')
def revoke():
  if 'credentials' not in flask.session:
    return ('You need to <a href="/authorize">authorize</a> before ' +
            'testing the code to revoke credentials.')

  credentials = google.oauth2.credentials.Credentials(
    **flask.session['credentials'])

  revoke = requests.post('https://oauth2.googleapis.com/revoke',
      params={'token': credentials.token},
      headers = {'content-type': 'application/x-www-form-urlencoded'})

  status_code = getattr(revoke, 'status_code')
  if status_code == 200:
    return('Credentials successfully revoked.' + print_index_table())
  else:
    return('An error occurred.' + print_index_table())


@app.route('/clear')
def clear_credentials():
  if 'credentials' in flask.session:
    del flask.session['credentials']
  return ('Credentials have been cleared.<br><br>' +
          print_index_table())


def credentials_to_dict(credentials):
  return {'token': credentials.token,
          'refresh_token': credentials.refresh_token,
          'token_uri': credentials.token_uri,
          'client_id': credentials.client_id,
          'client_secret': credentials.client_secret,
          'scopes': credentials.scopes}

def print_index_table():
  return ('<table>' +
          '<tr><td><a href="/test">Test an API request</a></td>' +
          '<td>Submit an API request and see a formatted JSON response. ' +
          '    Go through the authorization flow if there are no stored ' +
          '    credentials for the user.</td></tr>' +
          '<tr><td><a href="/authorize">Test the auth flow directly</a></td>' +
          '<td>Go directly to the authorization flow. If there are stored ' +
          '    credentials, you still might not be prompted to reauthorize ' +
          '    the application.</td></tr>' +
          '<tr><td><a href="/revoke">Revoke current credentials</a></td>' +
          '<td>Revoke the access token associated with the current user ' +
          '    session. After revoking credentials, if you go to the test ' +
          '    page, you should see an <code>invalid_grant</code> error.' +
          '</td></tr>' +
          '<tr><td><a href="/clear">Clear Flask session credentials</a></td>' +
          '<td>Clear the access token currently stored in the user session. ' +
          '    After clearing the token, if you <a href="/test">test the ' +
          '    API request</a> again, you should go back to the auth flow.' +
          '</td></tr></table>')


if __name__ == '__main__':
  # When running locally, disable OAuthlib's HTTPs verification.
  # ACTION ITEM for developers:
  #     When running in production *do not* leave this option enabled.
  os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

  # Specify a hostname and port that are set as a valid redirect URI
  # for your API project in the Google API Console.
  app.run('localhost', 8080, debug=True)

Ruby

This example uses the Sinatra framework.

require 'google/apis/drive_v2'
require 'google/api_client/client_secrets'
require 'json'
require 'sinatra'

enable :sessions
set :session_secret, 'setme'

get '/' do
  unless session.has_key?(:credentials)
    redirect to('/oauth2callback')
  end
  client_opts = JSON.parse(session[:credentials])
  auth_client = Signet::OAuth2::Client.new(client_opts)
  drive = Google::Apis::DriveV2::DriveService.new
  files = drive.list_files(options: { authorization: auth_client })
  "<pre>#{JSON.pretty_generate(files.to_h)}</pre>"
end

get '/oauth2callback' do
  client_secrets = Google::APIClient::ClientSecrets.load
  auth_client = client_secrets.to_authorization
  auth_client.update!(
    :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
    :redirect_uri => url('/oauth2callback'))
  if request['code'] == nil
    auth_uri = auth_client.authorization_uri.to_s
    redirect to(auth_uri)
  else
    auth_client.code = request['code']
    auth_client.fetch_access_token!
    auth_client.client_secret = nil
    session[:credentials] = auth_client.to_json
    redirect to('/')
  end
end

HTTP/REST

This Python example uses the Flask framework and the Requests library to demonstrate the OAuth 2.0 web flow. We recommend using the Google API Client Library for Python for this flow. (The example in the Python tab does use the client library.)

import json

import flask
import requests


app = flask.Flask(__name__)

CLIENT_ID = '123456789.apps.googleusercontent.com'
CLIENT_SECRET = 'abc123'  # Read from a file or environmental variable in a real app
SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly'
REDIRECT_URI = 'http://example.com/oauth2callback'


@app.route('/')
def index():
  if 'credentials' not in flask.session:
    return flask.redirect(flask.url_for('oauth2callback'))
  credentials = json.loads(flask.session['credentials'])
  if credentials['expires_in'] <= 0:
    return flask.redirect(flask.url_for('oauth2callback'))
  else:
    headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])}
    req_uri = 'https://www.googleapis.com/drive/v2/files'
    r = requests.get(req_uri, headers=headers)
    return r.text


@app.route('/oauth2callback')
def oauth2callback():
  if 'code' not in flask.request.args:
    auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code'
                '&client_id={}&redirect_uri={}&scope={}').format(CLIENT_ID, REDIRECT_URI, SCOPE)
    return flask.redirect(auth_uri)
  else:
    auth_code = flask.request.args.get('code')
    data = {'code': auth_code,
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'redirect_uri': REDIRECT_URI,
            'grant_type': 'authorization_code'}
    r = requests.post('https://oauth2.googleapis.com/token', data=data)
    flask.session['credentials'] = r.text
    return flask.redirect(flask.url_for('index'))


if __name__ == '__main__':
  import uuid
  app.secret_key = str(uuid.uuid4())
  app.debug = False
  app.run()

Redirect URI validation rules

Google applies the following validation rules to redirect URIs in order to help developers keep their applications secure. Your redirect URIs must adhere to these rules. See RFC 3986 section 3 for the definition of domain, host, path, query, scheme and userinfo, mentioned below.

Validation rules
Scheme

Redirect URIs must use the HTTPS scheme, not plain HTTP. Localhost URIs (including localhost IP address URIs) are exempt from this rule.

Host

Hosts cannot be raw IP addresses. Localhost IP addresses are exempted from this rule.

Domain
  • Host TLDs ( Top Level Domains ) must belong to the public suffix list .
  • Host domains cannot be “googleusercontent.com” .
  • Redirect URIs cannot contain URL shortener domains (eg goo.gl ) unless the app owns the domain. Furthermore, if an app that owns a shortener domain chooses to redirect to that domain, that redirect URI must either contain “/google-callback/” in its path or end with “/google-callback” .
  • Userinfo

    Redirect URIs cannot contain the userinfo subcomponent.

    Path

    Redirect URIs cannot contain a path traversal (also called directory backtracking), which is represented by an “/..” or “\..” or their URL encoding.

    Query

    Redirect URIs cannot contain open redirects .

    Fragment

    Redirect URIs cannot contain the fragment component.

    Characters Redirect URIs cannot contain certain characters including:
    • Wildcard characters ( '*' )
    • Non-printable ASCII characters
    • Invalid percent encodings (any percent encoding that does not follow URL-encoding form of a percent sign followed by two hexadecimal digits)
    • Null characters (an encoded NULL character, eg, %00 , %C0%80 )

    Incremental authorization

    In the OAuth 2.0 protocol, your app requests authorization to access resources, which are identified by scopes. It is considered a best user-experience practice to request authorization for resources at the time you need them. To enable that practice, Google's authorization server supports incremental authorization. This feature lets you request scopes as they are needed and, if the user grants permission for the new scope, returns an authorization code that may be exchanged for a token containing all scopes the user has granted the project.

    For example, an app that lets people sample music tracks and create mixes might need very few resources at sign-in time, perhaps nothing more than the name of the person signing in. However, saving a completed mix would require access to their Google Drive. Most people would find it natural if they only were asked for access to their Google Drive at the time the app actually needed it.

    In this case, at sign-in time the app might request the openid and profile scopes to perform basic sign-in, and then later request the https://www.googleapis.com/auth/drive.file scope at the time of the first request to save a mix.

    To implement incremental authorization, you complete the normal flow for requesting an access token but make sure that the authorization request includes previously granted scopes. This approach allows your app to avoid having to manage multiple access tokens.

    The following rules apply to an access token obtained from an incremental authorization:

    • The token can be used to access resources corresponding to any of the scopes rolled into the new, combined authorization.
    • When you use the refresh token for the combined authorization to obtain an access token, the access token represents the combined authorization and can be used for any of the scope values included in the response.
    • The combined authorization includes all scopes that the user granted to the API project even if the grants were requested from different clients. For example, if a user granted access to one scope using an application's desktop client and then granted another scope to the same application via a mobile client, the combined authorization would include both scopes.
    • If you revoke a token that represents a combined authorization, access to all of that authorization's scopes on behalf of the associated user are revoked simultaneously.

    The language-specific code samples in Step 1: Set authorization parameters and the sample HTTP/REST redirect URL in Step 2: Redirect to Google's OAuth 2.0 server all use incremental authorization. The code samples below also show the code that you need to add to use incremental authorization.

    PHP

    $client->setIncludeGrantedScopes(true);

    Python

    In Python, set the include_granted_scopes keyword argument to true to ensure that an authorization request includes previously granted scopes. It is very possible that include_granted_scopes will not be the only keyword argument that you set, as shown in the example below.

    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='true')

    Ruby

    auth_client.update!(
      :additional_parameters => {"include_granted_scopes" => "true"}
    )

    HTTP/REST

    GET https://accounts.google.com/o/oauth2/v2/auth?
      client_id=your_client_id&
      response_type=code&
      state=state_parameter_passthrough_value&
      scope=https%3A//www.googleapis.com/auth/drive.file&
      redirect_uri=https%3A//oauth2.example.com/code&
      prompt=consent&
      include_granted_scopes=true

    Refreshing an access token (offline access)

    Access tokens periodically expire and become invalid credentials for a related API request. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.

    • If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that object for offline access.
    • If you are not using a client library, you need to set the access_type HTTP query parameter to offline when redirecting the user to Google's OAuth 2.0 server . In that case, Google's authorization server returns a refresh token when you exchange an authorization code for an access token. Then, if the access token expires (or at any other time), you can use a refresh token to obtain a new access token.

    Requesting offline access is a requirement for any application that needs to access a Google API when the user is not present. For example, an app that performs backup services or executes actions at predetermined times needs to be able to refresh its access token when the user is not present. The default style of access is called online .

    Server-side web applications, installed applications, and devices all obtain refresh tokens during the authorization process. Refresh tokens are not typically used in client-side (JavaScript) web applications.

    PHP

    If your application needs offline access to a Google API, set the API client's access type to offline :

    $client->setAccessType("offline");

    After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed.

    Python

    In Python, set the access_type keyword argument to offline to ensure that you will be able to refresh the access token without having to re-prompt the user for permission. It is very possible that access_type will not be the only keyword argument that you set, as shown in the example below.

    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='true')

    After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed.

    Ruby

    If your application needs offline access to a Google API, set the API client's access type to offline :

    auth_client.update!(
      :additional_parameters => {"access_type" => "offline"}
    )

    After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed.

    HTTP/REST

    To refresh an access token, your application sends an HTTPS POST request to Google's authorization server ( https://oauth2.googleapis.com/token ) that includes the following parameters:

    Fields
    client_id The client ID obtained from the API Console.
    client_secret The client secret obtained from the API Console.
    grant_type As defined in the OAuth 2.0 specification , this field's value must be set to refresh_token .
    refresh_token The refresh token returned from the authorization code exchange.

    The following snippet shows a sample request:

    POST /token HTTP/1.1
    Host: oauth2.googleapis.com
    Content-Type: application/x-www-form-urlencoded
    
    client_id=your_client_id&
    client_secret=your_client_secret&
    refresh_token=refresh_token&
    grant_type=refresh_token

    As long as the user has not revoked the access granted to the application, the token server returns a JSON object that contains a new access token. The following snippet shows a sample response:

    {
      "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
      "expires_in": 3920,
      "scope": "https://www.googleapis.com/auth/drive.metadata.readonly",
      "token_type": "Bearer"
    }

    Note that there are limits on the number of refresh tokens that will be issued; one limit per client/user combination, and another per user across all clients. You should save refresh tokens in long-term storage and continue to use them as long as they remain valid. If your application requests too many refresh tokens, it may run into these limits, in which case older refresh tokens will stop working.

    Revoking a token

    In some cases a user may wish to revoke access given to an application. A user can revoke access by visiting Account Settings . See the Remove site or app access section of the Third-party sites & apps with access to your account support document for more information.

    It is also possible for an application to programmatically revoke the access given to it. Programmatic revocation is important in instances where a user unsubscribes, removes an application, or the API resources required by an app have significantly changed. In other words, part of the removal process can include an API request to ensure the permissions previously granted to the application are removed.

    PHP

    To programmatically revoke a token, call revokeToken() :

    $client->revokeToken();

    Python

    To programmatically revoke a token, make a request to https://oauth2.googleapis.com/revoke that includes the token as a parameter and sets the Content-Type header:

    requests.post('https://oauth2.googleapis.com/revoke',
        params={'token': credentials.token},
        headers = {'content-type': 'application/x-www-form-urlencoded'})

    Ruby

    To programmatically revoke a token, make an HTTP request to the oauth2.revoke endpoint:

    uri = URI('https://oauth2.googleapis.com/revoke')
    response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)
    

    The token can be an access token or a refresh token. If the token is an access token and it has a corresponding refresh token, the refresh token will also be revoked.

    If the revocation is successfully processed, then the status code of the response is 200 . For error conditions, a status code 400 is returned along with an error code.

    HTTP/REST

    To programmatically revoke a token, your application makes a request to https://oauth2.googleapis.com/revoke and includes the token as a parameter:

    curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
            https://oauth2.googleapis.com/revoke?token={token}

    The token can be an access token or a refresh token. If the token is an access token and it has a corresponding refresh token, the refresh token will also be revoked.

    If the revocation is successfully processed, then the HTTP status code of the response is 200 . For error conditions, an HTTP status code 400 is returned along with an error code.