Posts tagged with refresh-token

I've set up the whole Google Ads API according to this manual here: https://developers.google.com/google-ads/api/docs/client-libs/python/oauth-desktop?hl=en

I got my refresh token and put it in my google-ads.yaml file which looks exactly like this: https://github.com/googleads/google-ads-python/blob/master/google-ads.yaml. I also put my client_id, developer_token and client_secret at the corresponding spots in the file.

Everything worked out and I could for example ask for all campaigns: https://developers.google.com/google-ads/api/docs/samples/get-campaigns#python. Also I could use other services of the API.

Each time I use the API I access it via the client using the following code:

from google.ads.google_ads.client import GoogleAdsClient client = GoogleAdsClient.load_from_storage(path_to_google_ads_yaml_file) 

As I already said it worked.

A few days later I tried to connect again and I got the following error:

 “error”: “invalid_grant”, “error_description”: “Token has been expired or revoked.” 

So I did the process of getting a new refresh token again (https://developers.google.com/google-ads/api/docs/client-libs/python/oauth-desktop?hl=en) such that everything worked out again.

One day later I got the same error again. So my question is: What is the purpose of the refresh token? I thought it allows me to access the API without ever having to ask for a new token or refresh token!?

Now, I again tried to connect to the API once more (although it didn't work last time) and now I got an even worse and new error:

'invalid_grant: Bad Request', '{\n  "error": "invalid_grant",\n  "error_description": "Bad Request"\n}' 

So things are getting even more complicated...

I am very new to Python and Stackoverflow. I am working on connecting my Google Ads account with Python to automate few standard charts creation and email them to my team members. Please help me resolve this as I had not been able to find an answer to it upon Googling either. Let me know if I have missed out on any info which might provide more context to the question here.

I have been using the steps as mentioned by @msaniscalchi. Created client ID and client Secret from https://console.developers.google.com and created googleads.yaml file in the same directory as the generate_refresh_token.py. When I run the script with respective client ID and client Secret values, I am getting "invalid syntax" error. I have verified my multiple times my client secret and ID values multiple times.

"""Generates refresh token for AdWords using the Installed Application flow.""" import argparse import sys from google_auth_oauthlib.flow import InstalledAppFlow from oauthlib.oauth2.rfc6749.errors import InvalidGrantError # Your OAuth2 Client ID and Secret. If you do not have an ID and Secret yet, # please go to https://console.developers.google.com and create a set. DEFAULT_CLIENT_ID = 609XXXXXXX22-58mbhXXXXXXXXXXXXXXXXXX6ri.apps.googleusercontent.com DEFAULT_CLIENT_SECRET = 7uO7XXXXXXXXXXXXXX7dKBAP # The AdWords API OAuth2 scope. SCOPE = u'https://www.googleapis.com/auth/adwords' # The redirect URI set for the given Client ID. The redirect URI for Client ID # generated for an installed application will always have this value. _REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob' parser = argparse.ArgumentParser(description='Generates a refresh token with '                                  'the provided credentials.') parser.add_argument('--client_id', default=DEFAULT_CLIENT_ID,                     help='Client Id retrieved from the Developer\'s Console.') parser.add_argument('--client_secret', default=DEFAULT_CLIENT_SECRET,                     help='Client Secret retrieved from the Developer\'s '                     'Console.') parser.add_argument('--additional_scopes', default=None,                     help='Additional scopes to apply when generating the '                     'refresh token. Each scope should be separated by a comma.') class ClientConfigBuilder(object):   """Helper class used to build a client config dict used in the OAuth 2.0 flow.   """   _DEFAULT_AUTH_URI = 'https://accounts.google.com/o/oauth2/auth'   _DEFAULT_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token'   CLIENT_TYPE_WEB = 'web'   CLIENT_TYPE_INSTALLED_APP = 'installed'   def __init__(self, client_type=None, client_id=None, client_secret=None,                auth_uri=_DEFAULT_AUTH_URI, token_uri=_DEFAULT_TOKEN_URI):     self.client_type = client_type     self.client_id = client_id     self.client_secret = client_secret     self.auth_uri = auth_uri     self.token_uri = token_uri   def Build(self):     """Builds a client config dictionary used in the OAuth 2.0 flow."""     if all((self.client_type, self.client_id, self.client_secret,             self.auth_uri, self.token_uri)):       client_config = {           self.client_type: {               'client_id': self.client_id,               'client_secret': self.client_secret,               'auth_uri': self.auth_uri,               'token_uri': self.token_uri           }       }     else:       raise ValueError('Required field is missing.')     return client_config def main(client_id, client_secret, scopes):   """Retrieve and display the access and refresh token."""   client_config = ClientConfigBuilder(       client_type=ClientConfigBuilder.CLIENT_TYPE_WEB, client_id=client_id,       client_secret=client_secret)   flow = InstalledAppFlow.from_client_config(       client_config.Build(), scopes=scopes)   # Note that from_client_config will not produce a flow with the   # redirect_uris (if any) set in the client_config. This must be set   # separately.   flow.redirect_uri = _REDIRECT_URI   auth_url, _ = flow.authorization_url(prompt='consent')   print('Log into the Google Account you use to access your AdWords account '         'and go to the following URL: \n%s\n' % auth_url)   print('After approving the token enter the verification code (if specified).')   code = input('Code: ').strip()   try:     flow.fetch_token(code=code)   except InvalidGrantError as ex:     print('Authentication has failed: %s' % ex)     sys.exit(1)   print('Access token: %s' % flow.credentials.token)   print('Refresh token: %s' % flow.credentials.refresh_token) if __name__ == '__main__':   args = parser.parse_args()   configured_scopes = [SCOPE]   if not (any([args.client_id, DEFAULT_CLIENT_ID]) and           any([args.client_secret, DEFAULT_CLIENT_SECRET])):     raise AttributeError('No client_id or client_secret specified.')   if args.additional_scopes:     configured_scopes.extend(args.additional_scopes.replace(' ', '').split(','))   main(args.client_id, args.client_secret, configured_scopes) 

When I run the above code, I am getting the "Invalid Syntax" error highlighting at the numeric part of the Client ID and Secret.

Syntax error screenshot attached here

Editor Highlighter screenshot attached here

I am using the Google Oauth2 API to connect to Google Ads and become only one refresh token when my @gmail.com account has read access to two different Google Ads accounts.

I have the account a@gmail.com. This account has read access to the Google Ads accounts b@gmail.com and c@gmnail.com.

When I create two connections to Google Ads with the email a@gmail.com for the accounts b@gmail.com and c@gmail.com, then I receive only one refresh token, for the first connection and none refresh token for the second connection. Why? How can I manage this, to become 2 refresh tokens for each connection? The only way to become a refresh token for the second connection is to go to my account a@gmail.com and to decline the access to my app manually and connect again with c@gmail.com. But then b@gmail.com has no refresh token anymore.

code:

$oauth2 = new OAuth2(             [                 'authorizationUri' => $this->container->getParameter('oauth2.google.adwords.authorizationUri'),                 'tokenCredentialUri' => $this->container->getParameter('oauth2.google.adwords.tokenCredentialUri'),                 'redirectUri' => $this->container->getParameter('domain.system') . $this->container->getParameter(                         'oauth2.google.adwords.redirectUri.advertiser'                     ),                 'clientId' => $this->container->getParameter('oauth2.google.adwords.clientId'),                 'clientSecret' => $this->container->getParameter('oauth2.google.adwords.clientSecret'),                 'scope' => $this->container->getParameter('oauth2.google.adwords.scope')             ]         ); // Create a 'state' token to prevent request forgery.             // Store it in the session for later validation.             $randomState = sha1(openssl_random_pseudo_bytes(1024)) . '---' . $accountId;             $oauth2->setState($randomState);             // Redirect the user to the authorization URL.             $config = [                 // Set to 'offline' if you require offline access.                 'access_type' => 'offline',                 'approval_prompt' => 'force'             ];             // redirect to google ads             return new RedirectResponse($oauth2->buildFullAuthorizationUri($config));