Google API Client Library for Python that provides discovery-based access to hundreds of Google services with authentication, caching, and media upload/download support.
—
The Google API Python Client provides authentication helper functions that seamlessly integrate with google-auth and oauth2client libraries, enabling credential management, scope handling, and request authentication.
Helper functions for obtaining and managing authentication credentials.
def default_credentials():
"""
Get default credentials from the environment.
Uses Application Default Credentials (ADC) to find credentials from:
1. GOOGLE_APPLICATION_CREDENTIALS environment variable
2. User credentials from gcloud auth application-default login
3. Service account attached to Google Cloud resource
4. Google Cloud SDK default credentials
Returns:
tuple: (credentials, project_id) where credentials is a Credentials
object and project_id is the default project ID
Raises:
DefaultCredentialsError: When no valid credentials are found
"""
def with_scopes(credentials, scopes):
"""
Add OAuth2 scopes to credentials if the credentials support scoping.
Args:
credentials: OAuth2 credentials object (google-auth or oauth2client)
scopes (list or str): List of OAuth2 scope URLs or single scope string
Returns:
Credentials: Credentials object with scopes applied, or original
credentials if scoping is not supported
"""
def apply_credentials(credentials, headers):
"""
Apply authentication credentials to HTTP request headers.
Args:
credentials: OAuth2 credentials object
headers (dict): HTTP headers dictionary to modify in-place
Raises:
RefreshError: When credential refresh fails
TransportError: When credential application fails
"""Utility functions for working with different authentication flows and credential types.
def refresh_credentials(credentials):
"""
Refresh expired credentials.
Args:
credentials: OAuth2 credentials object to refresh
Returns:
Credentials: Refreshed credentials object
Raises:
RefreshError: When credential refresh fails
"""
def credentials_from_authorized_user_info(info, scopes=None):
"""
Create credentials from authorized user info dictionary.
Args:
info (dict): Dictionary containing authorized user information
scopes (list, optional): List of OAuth2 scopes to apply
Returns:
Credentials: OAuth2 credentials object
"""
def credentials_from_service_account_info(info, scopes=None):
"""
Create credentials from service account info dictionary.
Args:
info (dict): Dictionary containing service account information
scopes (list, optional): List of OAuth2 scopes to apply
Returns:
Credentials: Service account credentials object
"""from googleapiclient import discovery
from googleapiclient._auth import default_credentials
# Get default credentials from environment
credentials, project = default_credentials()
# Build service with default credentials
service = discovery.build('gmail', 'v1', credentials=credentials)
# Use the service
messages = service.users().messages().list(userId='me').execute()
print(f"Project: {project}")
print(f"Messages: {len(messages.get('messages', []))}")from googleapiclient._auth import default_credentials, with_scopes
# Get default credentials
credentials, project = default_credentials()
# Define required scopes
gmail_scopes = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.send'
]
# Add scopes to credentials
scoped_credentials = with_scopes(credentials, gmail_scopes)
# Build service with scoped credentials
service = discovery.build('gmail', 'v1', credentials=scoped_credentials)from googleapiclient._auth import apply_credentials
import httplib2
# Get credentials
credentials, _ = default_credentials()
# Create HTTP client
http = httplib2.Http()
# Prepare request headers
headers = {
'Content-Type': 'application/json',
'User-Agent': 'MyApp/1.0'
}
# Apply credentials to headers
apply_credentials(credentials, headers)
# Headers now contain Authorization header
print(headers.get('authorization')) # Bearer <access_token>from google.oauth2 import service_account
from googleapiclient import discovery
from googleapiclient._auth import with_scopes
# Load service account credentials from file
credentials = service_account.Credentials.from_service_account_file(
'path/to/service-account-key.json'
)
# Add required scopes
scopes = ['https://www.googleapis.com/auth/gmail.readonly']
scoped_credentials = with_scopes(credentials, scopes)
# Build service
service = discovery.build('gmail', 'v1', credentials=scoped_credentials)from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient import discovery
import os
def get_authenticated_service():
"""Get authenticated Gmail service using OAuth2 flow."""
scopes = ['https://www.googleapis.com/auth/gmail.readonly']
creds = None
# Load existing credentials
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', scopes)
# If no valid credentials, run OAuth flow
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', scopes)
creds = flow.run_local_server(port=0)
# Save credentials for next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
return discovery.build('gmail', 'v1', credentials=creds)
# Use the authenticated service
service = get_authenticated_service()from googleapiclient._auth import default_credentials, apply_credentials
from google.auth.exceptions import RefreshError
from googleapiclient.errors import HttpError
import httplib2
def make_authenticated_request(uri, method='GET', body=None):
"""Make an authenticated HTTP request with automatic credential refresh."""
credentials, _ = default_credentials()
try:
# Prepare headers
headers = {'Content-Type': 'application/json'}
apply_credentials(credentials, headers)
# Make request
http = httplib2.Http()
response, content = http.request(
uri, method=method, body=body, headers=headers
)
return response, content
except RefreshError as e:
print(f"Credential refresh failed: {e}")
raise
except HttpError as e:
if e.status_code == 401:
print("Authentication failed - credentials may be invalid")
raise
# Usage
response, content = make_authenticated_request(
'https://gmail.googleapis.com/gmail/v1/users/me/messages'
)from googleapiclient import discovery
from googleapiclient._auth import with_scopes
from google.oauth2 import service_account
import google.auth
class CredentialManager:
"""Manage multiple credential types for different services."""
def __init__(self):
self.credentials = {}
self.services = {}
def add_default_credentials(self, name, scopes=None):
"""Add Application Default Credentials."""
creds, project = google.auth.default()
if scopes:
creds = with_scopes(creds, scopes)
self.credentials[name] = creds
return creds
def add_service_account(self, name, key_file, scopes=None):
"""Add service account credentials."""
creds = service_account.Credentials.from_service_account_file(key_file)
if scopes:
creds = with_scopes(creds, scopes)
self.credentials[name] = creds
return creds
def get_service(self, cred_name, service_name, version):
"""Get an authenticated service using named credentials."""
if cred_name not in self.credentials:
raise ValueError(f"No credentials found for {cred_name}")
service_key = f"{cred_name}:{service_name}:{version}"
if service_key not in self.services:
self.services[service_key] = discovery.build(
service_name, version,
credentials=self.credentials[cred_name]
)
return self.services[service_key]
# Usage
cred_manager = CredentialManager()
# Add different credential types
cred_manager.add_default_credentials(
'user_gmail',
['https://www.googleapis.com/auth/gmail.readonly']
)
cred_manager.add_service_account(
'service_drive',
'service-account.json',
['https://www.googleapis.com/auth/drive']
)
# Get services with different credentials
gmail_service = cred_manager.get_service('user_gmail', 'gmail', 'v1')
drive_service = cred_manager.get_service('service_drive', 'drive', 'v3')from googleapiclient import discovery
from googleapiclient._auth import apply_credentials
import unittest.mock
class MockCredentials:
"""Mock credentials for testing."""
def __init__(self, token='mock_token'):
self.token = token
self.expired = False
def refresh(self, request):
"""Mock credential refresh."""
pass
def apply(self, headers, token=None):
"""Apply mock token to headers."""
headers['authorization'] = f'Bearer {self.token}'
def test_service_with_mock_credentials():
"""Test service creation with mock credentials."""
mock_creds = MockCredentials('test_token')
# Test header application
headers = {}
mock_creds.apply(headers)
assert headers['authorization'] == 'Bearer test_token'
# Test service building (with HTTP mock)
from googleapiclient.http import HttpMock
http_mock = HttpMock()
with unittest.mock.patch('googleapiclient._auth.default_credentials') as mock_default:
mock_default.return_value = (mock_creds, 'test-project')
service = discovery.build('gmail', 'v1', http=http_mock)
# Service created successfully with mock credentials
# Run test
test_service_with_mock_credentials()
print("Mock credential test passed")from googleapiclient._auth import default_credentials
from google.oauth2.credentials import Credentials
import json
import os
class CredentialStore:
"""Store and retrieve credentials securely."""
def __init__(self, store_path='credentials_store.json'):
self.store_path = store_path
self.credentials = {}
self.load_credentials()
def load_credentials(self):
"""Load credentials from storage."""
if os.path.exists(self.store_path):
try:
with open(self.store_path, 'r') as f:
data = json.load(f)
for name, cred_data in data.items():
if cred_data['type'] == 'authorized_user':
self.credentials[name] = Credentials.from_authorized_user_info(
cred_data['info']
)
except (json.JSONDecodeError, KeyError, ValueError):
print("Warning: Could not load stored credentials")
def save_credentials(self):
"""Save credentials to storage."""
data = {}
for name, creds in self.credentials.items():
if hasattr(creds, 'to_json'):
data[name] = {
'type': 'authorized_user',
'info': json.loads(creds.to_json())
}
with open(self.store_path, 'w') as f:
json.dump(data, f, indent=2)
def add_credentials(self, name, credentials):
"""Add credentials to store."""
self.credentials[name] = credentials
self.save_credentials()
def get_credentials(self, name):
"""Get credentials by name."""
return self.credentials.get(name)
# Usage
store = CredentialStore()
# Add default credentials
creds, _ = default_credentials()
store.add_credentials('default', creds)
# Retrieve later
stored_creds = store.get_credentials('default')
service = discovery.build('gmail', 'v1', credentials=stored_creds)Install with Tessl CLI
npx tessl i tessl/pypi-google-api-python-client@2.181.1