BingAds / BingAds-Python-SDK

Other
118 stars 164 forks source link

Support Client Credentials oauth flow for unsupervised clients #197

Open DrPyser opened 2 years ago

DrPyser commented 2 years ago

We have scripts running as unsupervised background processes(as cronjobs). These scripts cannot rely on an interactive user consent flow for authentication. Previously we had been using the desktop flow to manually(through developer intervention on a local machine) retrieve an access and refresh token that were then copied over to the server side, which is obviously a problematic workflow for efficiency, reliability and security reasons.

Instead, I am trying to use the Client Credentials oauth flow which is designed for this purpose. Since we are part of the same entity owning the application and the bingads account which we are using with the API, we do not need explicit consent from a specific user(we are not acting on behalf of another user). we already possess the client credentials needed to authenticate.

I am trying to use tokens acquired through this flow using the microsoft service authentication library (https://github.com/AzureAD/microsoft-authentication-library-for-python). I am trying to implement a custom bingads.OAuthAuthorization subclass implementing this flow using the msal python library. Here's the code:

class OauthClientCredentialGrant(bingads.OAuthAuthorization):
    oauth_scopes = ["https://ads.microsoft.com/.default"]

    def __init__(self, client_id, msal_app: msal.ConfidentialClientApplication, environment: str):
        super(OauthClientCredentialGrant, self).__init__(
            client_id,
            env=environment,
            require_live_connect=False
        )
        self._msal_app = msal_app
        self.logger = logging.getLogger(f"{__name__}.{self.__class__.__name__}")

    def request_oauth_tokens(self) -> bingads.OAuthTokens:
        """
        request oauth tokens using the msal.ConfidentialClientApplication.
        Returns OauthToken containing access token(no refresh token)
        """
        response = self._msal_app.acquire_token_for_client(scopes=self.oauth_scopes)
        if "error" in response:
            self.logger.error("Error requesting access token through client credential flow")
            raise bingads.OAuthTokenRequestException(
                error_code=response["error_codes"][0],
                description=response["error_description"]
            )
        else:
            access_token = response["access_token"]
            expires_in = response["expires_in"]
            self._oauth_tokens = bingads.OAuthTokens(access_token=access_token, access_token_expires_in_seconds=expires_in, response_json=response)
            self.logger.info("Successfully obtained access token through client credential flow")

            return self.oauth_tokens

Acquiring the access token using msal works, but for some reason the bingads library still cannot successfully authenticate with the API.

Also, no refresh token are used in this flow.

Thanks!

oaosman84 commented 2 years ago

Our team is having the same issue. We're also building a server-to-server flow with no third-party, and the standard interactive flow is not very feasible or secure. We'd love to be able to do a client_credentials flow but have been unable to get this to work.

oaosman84 commented 2 years ago

It would be good to understand whether this is something the Ads API supports (in which case it's just a matter of getting the code working) or whether the API just doesn't support it at all and we have to use the standard flow w/ refresh tokens and such.

qitia commented 2 years ago

to minimize dependency, bingads library does not use msal. I see you are using scope "https://ads.microsoft.com/.default", which is different from here, is that expected?

oaosman84 commented 2 years ago

@qitia thanks! I've tried scope=https://ads.microsoft.com/msads.manage but get an error:

The provided value for scope https://ads.microsoft.com/msads.manage is not valid. Client credential flows must have a scope value with /.default suffixed to the resource identifier

Sending scope=https://ads.microsoft.com/msads.manage/.default results in:

The resource principal named https://ads.microsoft.com/msads.manage was not found in the tenant named Microsoft Display Programmatic Direct. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant

I guess the question is whether we should expect the Ads API to support the client credentials flow or not

ukankal commented 2 years ago

Our team is facing the same issue as described by @oaosman84.

I guess the question is whether we should expect the Ads API to support the client credentials flow or not

@qitia - could you please confirm on this?

Luttik commented 2 years ago

This is quite an elementary and fundamentally essential feature for most use-cases for any api. Can you guys confirm or deny if this works for the reporting API (i.e. that having a headless / unsupervised service is even possible)?

pep4eto1211 commented 2 years ago

Has there been any update on that? I've recently had to deal with the LinkedIn API, which also doesn't allow for client_credentials flow for ad analytics, so I don't have high hopes. However, if anyone had managed to find something, please share. In addition the auth page in the docs now shows a message that says that all API usage will require 2FA, which doesn't look promising: image

oaosman84 commented 2 years ago

We had to eliminate our spend on the Bing Ads platform and shift that budget to other platforms since the current API flow is untenable for us.

shalakhin commented 2 years ago

Microsoft does a bad job as always. No answers, no docs, no convenient API just that SOAP crap that thousands of developers have to deal with

npt-dev commented 1 year ago

It's been 2 years and there hasn't been any further interest from Microsoft. I think it's not difficult to explain why Bing is rated so low by users.

troy-microbians commented 3 months ago

Wondering if a definitive answer of yes or no has been established? Why doesn't MS just answer the question!?

H4rryp0tt3r commented 3 months ago

Is there an update on this? We are thinking of using this SDK.

hknkkn commented 3 months ago

I have recently reached out to Bing Ads support through Azure to ask if this will be supported and the answer was no.