Re: How do I authenticate to send a clickConversion to google Ads with a service account and over REST API with typescript
This error appears in python RefreshError: ('unauthorized_client: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.', {'error': 'unauthorized_client', 'error_description': 'Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.'}) Bjoern Ammon schrieb am Mittwoch, 31. Januar 2024 um 10:47:11 UTC+1: > Addition: > The error i receive comes with authentication to googleapis > [image: IIF1Y.png] > > Bjoern Ammon schrieb am Mittwoch, 31. Januar 2024 um 10:20:35 UTC+1: > >> I've tried with this documentation >> <https://developers.google.com/google-ads/api/rest/auth> authenticate >> and with this REST >> <https://developers.google.com/google-ads/api/rest/reference/rest/v15/customers/uploadClickConversions> >> to >> send the conversion over REST API due to missing >> Typescript/Javascript-Client-Bib. >> >> *My error:* >> error: invalid_client >> error_description: Unauthorized >> >> *My setup:* >> Regarding to the documentation I have a google ads account with a >> developer token. This token will be used, when I send the click conversion, >> as you can see here >> <https://developers.google.com/google-ads/api/rest/auth#request_headers>. >> The token has nothing to do with the authentication of the service account. >> Therefore I have a service account on the Google Cloud Project, which also >> has the Google Ads Api enabled.[image: Ii3VN.png] >> >> I also added to the workspace domain to the domain wide delegation the >> client id of the service account with the scope >> >> *https://www.googleapis.com/auth/adwords >> <https://www.googleapis.com/auth/adwords>[image: W0d6l.png][image: >> pB83U.png]* >> >> The clientIds are fitting as well. >> >> Just in case I also added an OAuth consent screen with the scope >> *https://www.googleapis.com/auth/adwords >> <https://www.googleapis.com/auth/adwords>* with the Testing status and >> external. But I don't think I will need this with a service account. >> >> The service account itself has no further related rights. The >> documentation don't give me the info, that the service account need further >> rights. My thoughts: I added the client id to the domain wide delegation, >> this should be enough. I hope I am wrong here. >> >> Now everything should be set up. I hope I didn't miss a step. >> >> *My guess:* Either I am missing some rights. Or I missunderstand the >> refresh token in the function authenticateToGoogleAdsManager. I create a >> signed JWT. Google says here, I need a refresh token. But the >> authentication via await fetch('https://oauth2.googleapis.com/token' just >> gives me an access token. So I thought I just need a jwt here. >> >> This is the way I am executing my code (in a testcase. Service Account >> JSON and clickConversion are given.) >> >> *My code to understand what i do (I suggest to check my Question on >> Stackoverflow >> <https://stackoverflow.com/questions/77833488/how-do-i-authenticate-to-send-a-clickconversion-to-google-ads-with-a-service-acc> >> >> to read the codeblock) * >> >> ``` >> // First I create a signed jwt >> const jwt = generateJsonWebTokenForServiceAccount( serviceAccount, [' >> https://www.googleapis.com/auth/adwords'], 'googleads' ) >> >> // Then I use the signed jwt to authenticate to Google Ads Manager >> const authenticationResult = await authenticateToGoogleAdsManager( >> serviceAccount.client_id, serviceAccount.private_key, jwt ) >> >> // Then I use the access token to send a click conversion to Google Ads >> Manager >> const test = await sendClickConversionToGoogleAdsManager( CUSTOMERID, >> clickConversion, accessToken.access_token, 'DEV-TOKEN' ) >> >> >> Here are the functions: >> /** * Generates a JSON Web Token (JWT) for a service account. * * @param >> serviceAccount - The service account object containing the client email >> and private key. * @param scopes - An array of scopes for which the >> token will be authorized. * @param serviceName - The name of the service >> for which the token will be authorized. Default is 'oauth2'. * @param >> expirationTimeInSeconds - The expiration time of the token in seconds. >> Default is 3600 seconds (1 hour). * @returns The generate
Re: How do I authenticate to send a clickConversion to google Ads with a service account and over REST API with typescript
Addition: The error i receive comes with authentication to googleapis [image: IIF1Y.png] Bjoern Ammon schrieb am Mittwoch, 31. Januar 2024 um 10:20:35 UTC+1: > I've tried with this documentation > <https://developers.google.com/google-ads/api/rest/auth> authenticate and > with this REST > <https://developers.google.com/google-ads/api/rest/reference/rest/v15/customers/uploadClickConversions> > to > send the conversion over REST API due to missing > Typescript/Javascript-Client-Bib. > > *My error:* > error: invalid_client > error_description: Unauthorized > > *My setup:* > Regarding to the documentation I have a google ads account with a > developer token. This token will be used, when I send the click conversion, > as you can see here > <https://developers.google.com/google-ads/api/rest/auth#request_headers>. > The token has nothing to do with the authentication of the service account. > Therefore I have a service account on the Google Cloud Project, which also > has the Google Ads Api enabled.[image: Ii3VN.png] > > I also added to the workspace domain to the domain wide delegation the > client id of the service account with the scope > > *https://www.googleapis.com/auth/adwords > <https://www.googleapis.com/auth/adwords>[image: W0d6l.png][image: > pB83U.png]* > > The clientIds are fitting as well. > > Just in case I also added an OAuth consent screen with the scope > *https://www.googleapis.com/auth/adwords > <https://www.googleapis.com/auth/adwords>* with the Testing status and > external. But I don't think I will need this with a service account. > > The service account itself has no further related rights. The > documentation don't give me the info, that the service account need further > rights. My thoughts: I added the client id to the domain wide delegation, > this should be enough. I hope I am wrong here. > > Now everything should be set up. I hope I didn't miss a step. > > *My guess:* Either I am missing some rights. Or I missunderstand the > refresh token in the function authenticateToGoogleAdsManager. I create a > signed JWT. Google says here, I need a refresh token. But the > authentication via await fetch('https://oauth2.googleapis.com/token' just > gives me an access token. So I thought I just need a jwt here. > > This is the way I am executing my code (in a testcase. Service Account > JSON and clickConversion are given.) > > *My code to understand what i do (I suggest to check my Question on > Stackoverflow > <https://stackoverflow.com/questions/77833488/how-do-i-authenticate-to-send-a-clickconversion-to-google-ads-with-a-service-acc> > > to read the codeblock) * > > ``` > // First I create a signed jwt > const jwt = generateJsonWebTokenForServiceAccount( serviceAccount, [' > https://www.googleapis.com/auth/adwords'], 'googleads' ) > > // Then I use the signed jwt to authenticate to Google Ads Manager > const authenticationResult = await authenticateToGoogleAdsManager( > serviceAccount.client_id, serviceAccount.private_key, jwt ) > > // Then I use the access token to send a click conversion to Google Ads > Manager > const test = await sendClickConversionToGoogleAdsManager( CUSTOMERID, > clickConversion, accessToken.access_token, 'DEV-TOKEN' ) > > > Here are the functions: > /** * Generates a JSON Web Token (JWT) for a service account. * * @param > serviceAccount - The service account object containing the client email > and private key. * @param scopes - An array of scopes for which the token > will be authorized. * @param serviceName - The name of the service for > which the token will be authorized. Default is 'oauth2'. * @param > expirationTimeInSeconds - The expiration time of the token in seconds. > Default is 3600 seconds (1 hour). * @returns The generated JSON Web > Token. */ export function generateJsonWebTokenForServiceAccount( > serviceAccount: ServiceAccount, scopes: string[], serviceName: string = > 'oauth2', expirationTimeInSeconds = 3600 ) { const aud = serviceName === > 'oauth2' ? 'https://oauth2.googleapis.com/token' : `https://${serviceName} > .googleapis.com/` <http://googleapis.com/> const currentTimestamp = Math. > floor(Date.now() / 1000) const expirationTimestamp = currentTimestamp + > expirationTimeInSeconds const payload = { iss: serviceAccount.client_email, > sub: serviceAccount.client_email, scope: scopes.join(' '), aud: aud, exp: > expirationTimestamp, iat: currentTimestamp } const options: SignOptions = > { algorithm: 'RS256' } return jwt.sign(payload, serviceAccount.private