Skip to content

Conversation

@bokelley
Copy link
Contributor

Summary

Fixes the CreateHttpHeader attribute error when using service account authentication by wrapping credentials in all remaining locations.

Problem

After PR #579 fixed the auth manager, service account authentication was still failing with:

Sync failed: GAM error: 'Credentials' object has no attribute 'CreateHttpHeader'

The previous fix only updated src/adapters/gam/auth.py, but there were two additional locations creating raw google.oauth2.service_account.Credentials objects and passing them directly to AdManagerClient.

Root Cause

AdManagerClient requires a googleads.oauth2.GoogleOAuth2Client subclass (like GoogleCredentialsClient), not raw google.auth.credentials.Credentials objects. The raw credentials don't implement the CreateHttpHeader() method that the googleads library expects.

Solution

Wrapped service account credentials in oauth2.GoogleCredentialsClient in the remaining two locations:

  1. src/admin/blueprints/inventory.py (line 571-578): Inventory sync operations
  2. src/adapters/gam/utils/health_check.py (line 82-89): GAM health checks

Both now follow the same pattern as the auth manager fix:

# Create credentials
credentials = google.oauth2.service_account.Credentials.from_service_account_file(...)
# Wrap in GoogleCredentialsClient for AdManagerClient compatibility
oauth2_client = oauth2.GoogleCredentialsClient(credentials)
# Pass wrapped client to AdManagerClient
client = ad_manager.AdManagerClient(oauth2_client, ...)

Changes

File: src/admin/blueprints/inventory.py

  • Line 571-578: Wrap credentials in GoogleCredentialsClient for inventory sync

File: src/adapters/gam/utils/health_check.py

  • Line 82-89: Wrap credentials in GoogleCredentialsClient for health checks

Test Results

✅ All 8 service account auth tests pass
✅ All 35 GAM unit tests pass
✅ All 846 unit tests pass
✅ All 174 integration tests pass

Related

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

bokelley and others added 3 commits October 23, 2025 21:23
Wrap service account credentials in GoogleCredentialsClient to ensure
compatibility with AdManagerClient. The AdManagerClient requires a
googleads OAuth2 client wrapper (GoogleOAuth2Client subclass), not raw
google.auth credentials.

Changes:
- Wrap Credentials objects in oauth2.GoogleCredentialsClient before
  returning from _get_service_account_credentials()
- Update tests to verify returned object is GoogleCredentialsClient
- Add test to confirm OAuth2 client compatibility with AdManagerClient

This fixes 400 errors when calling GAM API with service account auth.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Wrap service account credentials in GoogleCredentialsClient in
inventory sync and health check code to fix "CreateHttpHeader"
attribute errors.

The previous fix only updated src/adapters/gam/auth.py, but there
were additional places creating raw Credentials objects and passing
them directly to AdManagerClient:

1. src/admin/blueprints/inventory.py (line 571-576): Inventory sync
2. src/adapters/gam/utils/health_check.py (line 82-86): Health checks

Both now properly wrap credentials in oauth2.GoogleCredentialsClient
before passing to AdManagerClient, consistent with the auth.py fix.

Fixes: "Sync failed: GAM error: 'Credentials' object has no attribute
'CreateHttpHeader'" errors when using service account authentication.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@bokelley bokelley merged commit b9fa85d into main Oct 24, 2025
8 checks passed
EmmaLouise2018 pushed a commit that referenced this pull request Oct 24, 2025
* Fix GAM service account authentication

Wrap service account credentials in GoogleCredentialsClient to ensure
compatibility with AdManagerClient. The AdManagerClient requires a
googleads OAuth2 client wrapper (GoogleOAuth2Client subclass), not raw
google.auth credentials.

Changes:
- Wrap Credentials objects in oauth2.GoogleCredentialsClient before
  returning from _get_service_account_credentials()
- Update tests to verify returned object is GoogleCredentialsClient
- Add test to confirm OAuth2 client compatibility with AdManagerClient

This fixes 400 errors when calling GAM API with service account auth.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix remaining service account credential wrapping issues

Wrap service account credentials in GoogleCredentialsClient in
inventory sync and health check code to fix "CreateHttpHeader"
attribute errors.

The previous fix only updated src/adapters/gam/auth.py, but there
were additional places creating raw Credentials objects and passing
them directly to AdManagerClient:

1. src/admin/blueprints/inventory.py (line 571-576): Inventory sync
2. src/adapters/gam/utils/health_check.py (line 82-86): Health checks

Both now properly wrap credentials in oauth2.GoogleCredentialsClient
before passing to AdManagerClient, consistent with the auth.py fix.

Fixes: "Sync failed: GAM error: 'Credentials' object has no attribute
'CreateHttpHeader'" errors when using service account authentication.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
danf-newton pushed a commit to Newton-Research-Inc/salesagent that referenced this pull request Nov 24, 2025
…otocol#581)

* Fix GAM service account authentication

Wrap service account credentials in GoogleCredentialsClient to ensure
compatibility with AdManagerClient. The AdManagerClient requires a
googleads OAuth2 client wrapper (GoogleOAuth2Client subclass), not raw
google.auth credentials.

Changes:
- Wrap Credentials objects in oauth2.GoogleCredentialsClient before
  returning from _get_service_account_credentials()
- Update tests to verify returned object is GoogleCredentialsClient
- Add test to confirm OAuth2 client compatibility with AdManagerClient

This fixes 400 errors when calling GAM API with service account auth.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix remaining service account credential wrapping issues

Wrap service account credentials in GoogleCredentialsClient in
inventory sync and health check code to fix "CreateHttpHeader"
attribute errors.

The previous fix only updated src/adapters/gam/auth.py, but there
were additional places creating raw Credentials objects and passing
them directly to AdManagerClient:

1. src/admin/blueprints/inventory.py (line 571-576): Inventory sync
2. src/adapters/gam/utils/health_check.py (line 82-86): Health checks

Both now properly wrap credentials in oauth2.GoogleCredentialsClient
before passing to AdManagerClient, consistent with the auth.py fix.

Fixes: "Sync failed: GAM error: 'Credentials' object has no attribute
'CreateHttpHeader'" errors when using service account authentication.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants