Skip to content

✨ Source Facebook-Marketing: Add Selectable Auth - #37625

Closed
John Mikkelson (JohnMikkelsonOvative) wants to merge 7 commits into
airbytehq:masterfrom
JohnMikkelsonOvative:JohnMikkelsonOvative/feature-facebook-marketing-selectable-auth
Closed

John Mikkelson (JohnMikkelsonOvative) wants to merge 7 commits into
airbytehq:masterfrom
JohnMikkelsonOvative:JohnMikkelsonOvative/feature-facebook-marketing-selectable-auth

Conversation

@JohnMikkelsonOvative

@JohnMikkelsonOvative John Mikkelson (JohnMikkelsonOvative) commented Apr 26, 2024 •

Copy link
Copy Markdown
Contributor

What

The Source Facebook Marketing Connector does not allow for choosing between providing an access token or using oauth, it only allows for users to define a source connection by following an oauth flow. This does not allow for use-cases in which a large organization may provision an access token to be used to authenticate to the Facebook Marketing data, rather than giving a user's personal Facebook account access.

How

The spec defines a credentials field that is a union between newly created OAuthCredentials and ServiceAccountCredentials. This allows for the user to select between using the Oauth flow and inserting Service Account Credentials.

Review guide

  1. spec.py
  2. config.py
  3. source.py
  4. sample_config.json
  5. metadata.yaml
  6. pyproject.toml
  7. request_builder.py
  8. test_ads_insights_action_product_id.py
  9. test_videos.py
  10. test_source.py

User Impact

The user is able to select between using the Oauth flow and inserting Service Account Credentials when setting up the Facebook Marketing Source.

Can this PR be safely reverted and rolled back?

  • YES 💚
  • NO ❌

…anges to solve build issues, and changes to solve unit testing issues.
…e config. Updated version to reflect Airbyte versioning standard (this use case is a major version upgrade due to configuration of credentials needed to be changed)
…ebook-marketing-selectable-auth' into JohnMikkelsonOvative/feature-facebook-marketing-selectable-auth
@vercel

vercel Bot commented Apr 26, 2024 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
airbyte-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 27, 2024 0:42am

@CLAassistant

CLAassistant commented Apr 26, 2024 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@JohnMikkelsonOvative

Copy link
Copy Markdown
Contributor Author

During the migration to credentials selectable configuration, the decision was made to change the naming of ACCESS_TOKEN to SERVICE_ACCOUNT_INFO. This was due to the same naming convention being used in the Source-Google-Drive. Does this make sense to the Airbyte team, or should we change that naming convention to something more agnostic?

@marcosmarxm M. Marx (marcosmarxm) left a comment

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.

Thanks for the contribution John Mikkelson (@JohnMikkelsonOvative). It was added to the Connector team backlog and it will be reviewed in future sprint. I'll check with the project manager a timeline to make aware, ask your patience until the moment of the review. As this impact in a critical connector the review can take some time and have some back and forward, the goal is to introduce new features with the lower impact possible. In any time, feel free to reach me out in Slack or ping here to get update about the review process.

return False, "End date must be equal or after start date."

api = API(access_token=config.access_token, page_size=config.page_size)
if config.credentials.auth_type == 'Client':

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.

Just small suggestion is to use maybe Enum class to represent the auth type value.

"end_date": "2021-01-01T00:00:00Z",
"account_id": "<YOUR_ACCOUNT_ID_HERE>",
"access_token": "<YOUR_TOKEN_HERE>"
"credentials": {

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.

  1. This change will be a breaking change for all of the existing customers.
  2. We should use the config migration to allow the existing Customers to continue using the existing credentials rather than forcing everyone to upgrade.
  3. This will also touch the way the OAuth2.0 works now, because it returns the obtained credentials to the root of the config, here, thus this method should be removed from the flow because the default method returns the obtained access_token/refresh_token under the credentials object, which is exactly what the new flow will require.

"access_token": {
"type": "string",
"path_in_connector_config": ["access_token"],
"path_in_connector_config": ["credentials", "access_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.

There is no backward compatibility for the existing Customers, we should be able to handle the access_token from the root level of the config, alongside the new credentials.access_token path.


api = API(access_token=config.access_token, page_size=config.page_size)
if config.credentials.auth_type == 'Client':
api = API(access_token=config.credentials.refresh_token, page_size=config.page_size)

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.

Why the refresh_token is addressed here? Where we use it in the code?

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 OAuth flow, will return the access_token only.
Based on this line of code

self._config: MutableMapping[str, Any] = {
"account_ids": [ACCOUNT_ID],
"access_token": ACCESS_TOKEN,
"credentials": {

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.

There is no need to replace the tests, but extend them with the new functionality, using parametrized test case. With this changes, we loose the backward compatibility tests for the existing Customers.

description="Client Secret for the Facebook Marketing API",
airbyte_secret=True,
)
refresh_token: str = Field(

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 OAuth2.0 Flow doesn't return the refresh_token, could you please refer to the official doc, where this is possible? Thank you.

@bazarnov Baz (bazarnov) left a comment

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.

Requesting changes, because this change will break the existing Customers.

The path should look like this:

  1. Support both old and new way of authentication to cover the existing Customers
  2. Write the test cases for both scenarios
  3. Make it possible to migrate existing customers to use the new way of authentication by applying the config migration, see the example in the /config_migrations.py
  4. Release this update (at this point, all existing Customers are covered with the config_migration, this will allow to win the time, before we update the OAuth Flow for the platform side, here by removing this method.
  5. Done; the platform will return the access_token back to the credentials.access_token as expected after point 4 is released, which means we are good to go with the new authentication way of things.

@maxi297

Copy link
Copy Markdown
Contributor

Baz (@bazarnov) For my personal knowledge, what does removing getDefaultOAuthOutputPath do? It is also deprecated in the interface which seems like we should move away from that

@bazarnov

Copy link
Copy Markdown
Contributor

Baz (@bazarnov) For my personal knowledge, what does removing getDefaultOAuthOutputPath do? It is also deprecated in the interface which seems like we should move away from that

You've looked to the wrong place, see this
Which is inherited from this

@bazarnov

Copy link
Copy Markdown
Contributor

We can safely move away from using this method, once the new way is released and the existing Customers are covered with the config_migration prior to the platform change.

@maxi297

Copy link
Copy Markdown
Contributor

Note that this method is in FacebookOAuthFlow and this will affect Instagram and Facebook Pages as well. Is this an issue? We can probably re-implement this in the specific classes for those connectors

@bazarnov

Copy link
Copy Markdown
Contributor

Note that this method is in FacebookOAuthFlow and this will affect Instagram and Facebook Pages as well. Is this an issue? We can probably re-implement this in the specific classes for those connectors

We can add the existing method from the base class to all of the other Facebook-related OAuth flows to keep them running as is for now, then create the follow-up issues, to modify each of them. In this way, the Instagram and Facebook Pages, will not be affected with the platform change.

@bazarnov

Baz (bazarnov) commented May 27, 2024 •

Copy link
Copy Markdown
Contributor

Cristina Mariscal (@cmm-airbyte) Could you please fix the conflicts and ensure we pass the CAT successfully before this is finally approved? Thanks.

UPDATE: dismiss this comment, because I missed the fact we work on this within another PR: #38304

This branch was successfully deployed

1 active and 1 inactive deployments
Preview — 7939c8ae Deployed Apr 27, 2024 by vercel[bot]
community-ci — 7939c8ae Deployed Apr 27, 2024 by marcosmarxm
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.

8 participants