Skip to content

feat(source-gmail): add OAuth flow with credentials wrapper, config migration, and Service Account auth#76065

Open
Serhii Lazebnyi (lazebnyi) wants to merge 5 commits intomasterfrom
slazebnyi/source-gmail-granular-scopes
Open

feat(source-gmail): add OAuth flow with credentials wrapper, config migration, and Service Account auth#76065
Serhii Lazebnyi (lazebnyi) wants to merge 5 commits intomasterfrom
slazebnyi/source-gmail-granular-scopes

Conversation

@lazebnyi
Copy link
Copy Markdown
Contributor

@lazebnyi Serhii Lazebnyi (lazebnyi) commented Apr 3, 2026

What

Add oauth_connector_input_specification with granular scopes to support the Granular OAuth Scopes project, and restructure the connector's spec so that OAuth fields (client_id, client_secret, client_refresh_token) are properly hidden behind the platform's "Authenticate" button instead of being rendered as bare input fields. Also adds Service Account Key authentication as a second auth type.

References https://github.com/airbytehq/airbyte-internal-issues/issues/16023

How

  1. Spec restructuring: Wrapped client_id, client_secret, and client_refresh_token inside a credentials object with a oneOf auth type selector containing two options: OAuth and Service Account Key (matching the pattern used by source-google-sheets and other Google connectors).
  2. SelectiveAuthenticator: Replaced the inline OAuthAuthenticator on base_requester with a SelectiveAuthenticator that dispatches on credentials.auth_type:
    • Clientoauth_authenticator (OAuth refresh-token flow)
    • Servicejwt_profile_assertion_oauth_authenticator (JWT profile assertion via service account key)
  3. advanced_auth: Added predicate_key: [credentials, auth_type] and predicate_value: Client so the platform UI renders the OAuth button correctly. Added oauth_connector_input_specification with the gmail.readonly scope.
  4. path_in_connector_config: Updated all OAuth output paths to point to credentials.client_id, credentials.client_secret, and credentials.client_refresh_token.
  5. Config migration: Added config_normalization_rules with a ConfigMigration that transparently moves top-level OAuth fields into the nested credentials object for existing connections (so this is non-breaking for current users).

Review guide

  1. airbyte-integrations/connectors/source-gmail/manifest.yaml — all functional changes (authenticators, spec, config migration, advanced_auth)
  2. airbyte-integrations/connectors/source-gmail/metadata.yaml — version bump to 0.0.52
  3. docs/integrations/sources/gmail.md — updated config table and changelog

⚠️ Items worth verifying

  • Service Account + Gmail API: The JWT authenticator is modeled after source-google-sheets. However, Gmail API service accounts typically require domain-wide delegation with a subject (the user email to impersonate). The current implementation does not include a subject field — verify whether this works or if a subject property needs to be added to the Service Account oneOf option.
  • OAuth field hiding: The primary reason for adding the second oneOf option (Service Account) is that the platform UI does not hide complete_oauth_server_output_specification fields when there is only a single oneOf option. Confirm via prerelease that client_id and client_secret are now hidden behind the "Authenticate" button.
  • Config migration ordering: The migration first runs ConfigAddFields (condition: old top-level fields exist and credentials is absent), then ConfigRemoveFields (condition: credentials is present). Confirm the CDK applies these transformations sequentially on the mutated config within a single ConfigMigration.

User Impact

  • New connections: OAuth fields are now hidden behind the "Authenticate via Google" button, consistent with other Google connectors. Service Account Key authentication is also available.
  • Existing connections: The config migration transparently restructures the config on sync; no manual reconfiguration needed.

Can this PR be safely reverted and rolled back?

  • YES 💚

Link to Devin session: https://app.devin.ai/sessions/7bbf775a6ee347c9a4ee771219c3e133
Requested by: Serhii Lazebnyi (@lazebnyi)

@octavia-bot octavia-bot bot marked this pull request as draft April 3, 2026 05:14
@octavia-bot
Copy link
Copy Markdown
Contributor

octavia-bot bot commented Apr 3, 2026

Note

📝 PR Converted to Draft

More info...

Thank you for creating this PR. As a policy to protect our engineers' time, Airbyte requires all PRs to be created first in draft status. Your PR has been automatically converted to draft status in respect for this policy.

As soon as your PR is ready for formal review, you can proceed to convert the PR to "ready for review" status by clicking the "Ready for review" button at the bottom of the PR page.

To skip draft status in future PRs, please include [ready] in your PR title or add the skip-draft-status label when creating your PR.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

PR Slash Commands

Airbyte Maintainers (that's you!) can execute the following slash commands on your PR:

  • 🛠️ Quick Fixes
    • /format-fix - Fixes most formatting issues.
    • /bump-version - Bumps connector versions, scraping changelog description from the PR title.
      • Bump types: patch (default), minor, major, major_rc, rc, promote.
      • The rc type is a smart default: applies minor_rc if stable, or bumps the RC number if already RC.
      • The promote type strips the RC suffix to finalize a release.
      • Example: /bump-version type=rc or /bump-version type=minor
    • /bump-progressive-rollout-version - Alias for /bump-version type=rc. Bumps with an RC suffix and enables progressive rollout.
  • ❇️ AI Testing and Review (internal link: AI-SDLC Docs):
    • /ai-prove-fix - Runs prerelease readiness checks, including testing against customer connections.
    • /ai-canary-prerelease - Rolls out prerelease to 5-10 connections for canary testing.
    • /ai-review - AI-powered PR review for connector safety and quality gates.
  • 🚀 Connector Releases:
    • /publish-connectors-prerelease - Publishes pre-release connector builds (tagged as {version}-preview.{git-sha}) for all modified connectors in the PR.
  • ☕️ JVM connectors:
    • /update-connector-cdk-version connector=<CONNECTOR_NAME> - Updates the specified connector to the latest CDK version.
      Example: /update-connector-cdk-version connector=destination-bigquery
  • 🐍 Python connectors:
    • /poe connector source-example lock - Run the Poe lock task on the source-example connector, committing the results back to the branch.
    • /poe source example lock - Alias for /poe connector source-example lock.
    • /poe source example use-cdk-branch my/branch - Pin the source-example CDK reference to the branch name specified.
    • /poe source example use-cdk-latest - Update the source-example CDK dependency to the latest available version.
  • ⚙️ Admin commands:
    • /force-merge reason="<REASON>" - Force merges the PR using admin privileges, bypassing CI checks. Requires a reason.
      Example: /force-merge reason="CI is flaky, tests pass locally"
📚 Show Repo Guidance

Helpful Resources

📝 Edit this welcome message.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

source-gmail Connector Test Results

3 tests   1 ✅  3s ⏱️
1 suites  2 💤
1 files    0 ❌

Results for commit 5480df5.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

Deploy preview for airbyte-docs ready!

✅ Preview
https://airbyte-docs-ml3mgskd7-airbyte-growth.vercel.app

Built with commit 5480df5.
This pull request is being automatically deployed with vercel-action

@lazebnyi Serhii Lazebnyi (lazebnyi) force-pushed the slazebnyi/source-gmail-granular-scopes branch from 70cfd3f to 4e39f55 Compare April 3, 2026 05:20
@lazebnyi Serhii Lazebnyi (lazebnyi) marked this pull request as ready for review April 3, 2026 10:10
@lazebnyi
Copy link
Copy Markdown
Contributor Author

Serhii Lazebnyi (lazebnyi) commented Apr 3, 2026

/publish-connectors-prerelease

Pre-release Connector Publish Started

Publishing pre-release build for connector source-gmail.
PR: #76065

Pre-release versions will be tagged as {version}-preview.4e39f55
and are available for version pinning via the scoped_configuration API.

View workflow run
Pre-release Publish: SUCCESS

Docker image (pre-release):
airbyte/source-gmail:0.0.51-preview.4e39f55

Docker Hub: https://hub.docker.com/layers/airbyte/source-gmail/0.0.51-preview.4e39f55

Registry JSON:

… and config migration

- Wrap client_id, client_secret, client_refresh_token under a credentials object with oneOf auth type
- Add predicate_key/predicate_value to advanced_auth for proper OAuth button rendering
- Update path_in_connector_config to use credentials prefix
- Add config_normalization_rules with ConfigMigration to transparently migrate old top-level configs
- Update authenticator references to read from config.credentials
- Update documentation to reflect new config structure

Co-Authored-By: gl_serhii.lazebnyi <serglazebny@gmail.com>
@lazebnyi
Copy link
Copy Markdown
Contributor Author

Serhii Lazebnyi (lazebnyi) commented Apr 3, 2026

/publish-connectors-prerelease

Pre-release Connector Publish Started

Publishing pre-release build for connector source-gmail.
PR: #76065

Pre-release versions will be tagged as {version}-preview.de4b3d4
and are available for version pinning via the scoped_configuration API.

View workflow run
Pre-release Publish: SUCCESS

Docker image (pre-release):
airbyte/source-gmail:0.0.51-preview.de4b3d4

Docker Hub: https://hub.docker.com/layers/airbyte/source-gmail/0.0.51-preview.de4b3d4

Registry JSON:

@devin-ai-integration devin-ai-integration bot changed the title feat(source-gmail): add oauth_connector_input_specification with granular scopes feat(source-gmail): add OAuth flow with credentials wrapper and config migration Apr 3, 2026
@devin-ai-integration
Copy link
Copy Markdown
Contributor

/bump-version type=patch


Devin session

Co-Authored-By: gl_serhii.lazebnyi <serglazebny@gmail.com>
@lazebnyi
Copy link
Copy Markdown
Contributor Author

Serhii Lazebnyi (lazebnyi) commented Apr 3, 2026

/publish-connectors-prerelease

Pre-release Connector Publish Started

Publishing pre-release build for connector source-gmail.
PR: #76065

Pre-release versions will be tagged as {version}-preview.14875ab
and are available for version pinning via the scoped_configuration API.

View workflow run
Pre-release Publish: SUCCESS

Docker image (pre-release):
airbyte/source-gmail:0.0.52-preview.14875ab

Docker Hub: https://hub.docker.com/layers/airbyte/source-gmail/0.0.52-preview.14875ab

Registry JSON:

…e 0.0.52 row

Co-Authored-By: gl_serhii.lazebnyi <serglazebny@gmail.com>
@lazebnyi
Copy link
Copy Markdown
Contributor Author

Serhii Lazebnyi (lazebnyi) commented Apr 3, 2026

/publish-connectors-prerelease

Pre-release Connector Publish Started

Publishing pre-release build for connector source-gmail.
PR: #76065

Pre-release versions will be tagged as {version}-preview.9886952
and are available for version pinning via the scoped_configuration API.

View workflow run
Pre-release Publish: SUCCESS

Docker image (pre-release):
airbyte/source-gmail:0.0.52-preview.9886952

Docker Hub: https://hub.docker.com/layers/airbyte/source-gmail/0.0.52-preview.9886952

Registry JSON:

…ticator to hide OAuth fields behind button

Co-Authored-By: gl_serhii.lazebnyi <serglazebny@gmail.com>
@devin-ai-integration devin-ai-integration bot changed the title feat(source-gmail): add OAuth flow with credentials wrapper and config migration feat(source-gmail): add OAuth flow with credentials wrapper, config migration, and Service Account auth Apr 3, 2026
@lazebnyi
Copy link
Copy Markdown
Contributor Author

Serhii Lazebnyi (lazebnyi) commented Apr 3, 2026

/publish-connectors-prerelease

Pre-release Connector Publish Started

Publishing pre-release build for connector source-gmail.
PR: #76065

Pre-release versions will be tagged as {version}-preview.5480df5
and are available for version pinning via the scoped_configuration API.

View workflow run
Pre-release Publish: SUCCESS

Docker image (pre-release):
airbyte/source-gmail:0.0.52-preview.5480df5

Docker Hub: https://hub.docker.com/layers/airbyte/source-gmail/0.0.52-preview.5480df5

Registry JSON:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVED
left some questions

additionalProperties: true
config_normalization_rules:
type: ConfigNormalizationRules
config_migrations:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember this works fine, did you have the chance to manually test it?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prerelease 0.0.52-preview.5480df5 was built and tested via version pinning in Cloud. The OAuth button renders correctly and the oneOf dropdown shows both auth types. The config migration structure is modeled after other connectors that use ConfigMigration with ConfigAddFields + ConfigRemoveFields.

One limitation we found: client_id/client_secret field hiding behind the OAuth button couldn't be fully verified via prerelease because the global cloud_registry.json still points to v0.0.49 (which has no advanced_auth). The prerelease per-version registry JSON has the correct advanced_auth (structurally identical to source-google-sheets), so field hiding should work once the connector is officially published.

Comment on lines +395 to +397
- - client_id
- - client_secret
- - client_refresh_token
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these array of arrays?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, do we need to remove them? I liked the idea that we could just pin the previous version.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes — field_pointers expects an array of field pointers, where each field pointer is itself an array of path segments. In YAML, - - client_id represents [["client_id"]]. If you had a nested field like credentials.client_id, it would be:

field_pointers:
  - - credentials
    - client_id

This is the standard format used by ConfigRemoveFields in the CDK.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removal is a cleanup step — after ConfigAddFields copies the values into credentials.client_id etc., the old top-level fields become stale duplicates. Without removal, the migrated config would have both config.client_id and config.credentials.client_id with the same value, which could be confusing.

That said, the removal only runs on configs that still have the old top-level format (guarded by the condition), so it's safe. And pinning the previous version for rollback would still work since the migration only triggers on old-format configs — configs that were already migrated wouldn't be affected.

This is ultimately a design choice for Serhii Lazebnyi (@lazebnyi) to decide on — happy to remove ConfigRemoveFields if you prefer keeping the stale top-level fields for extra safety.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants