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 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_key, options) } /** * Authenticates to Google Ads Manager using 
>> the provided credentials. * @param clientId The client ID for 
>> authentication. * @param clientSecret The client secret for 
>> authentication. * @param refreshToken The refresh token for 
>> authentication. * @returns A promise that resolves to the access token. 
>> */ export async function authenticateToGoogleAdsManager( clientId: 
>> string, clientSecret: string, refreshToken: string ): Promise<string> { 
>> const url = 'https://www.googleapis.com/oauth2/v3/token' const body = { 
>> client_id: clientId, client_secret: clientSecret, refresh_token: 
>> refreshToken, grant_type: 'refresh_token' } const response = await 
>> fetch(url, 
>> { method: 'POST', body: JSON.stringify(body) }) const data = await 
>> response.json() return data.access_token } /** * Sends a click 
>> conversion to Google Ads Manager. * * @param customerId - The ID of the 
>> customer. * @param clickConversion - The click conversion data. * @param 
>> accessToken - The access token for authentication. * @param 
>> developerToken - The developer token for authentication. * @param options 
>> - Optional API options. * @returns A promise that resolves to void. */ 
>> export async function sendClickConversionToGoogleAdsManager( customerId: 
>> number, clickConversion: ClickConversion, accessToken: string, 
>> developerToken: string, options?: ApiOptions ): Promise<void> { const 
>> url = `https://googleads.googleapis.com/v15/customers/${customerId}
>> :uploadClickConversions` if (!options) { options = { partialFailure: 
>> false, validateOnly: false, debugEnabled: false, jobId: 0 } } const 
>> response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 
>> 'application/json', Authorization: `Bearer ${accessToken}`, 
>> 'developer-token': developerToken }, body: JSON.stringify({ conversions: 
>> [clickConversion], partialFailure: options.partialFailure, validateOnly: 
>> options.validateOnly, debugEnabled: options.debugEnabled, jobId: options.
>> jobId }) }) const data = await response.json() return data }
>>
>>
>>

-- 
-- 
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~
Also find us on our blog:
https://googleadsdeveloper.blogspot.com/
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~

You received this message because you are subscribed to the Google
Groups "AdWords API and Google Ads API Forum" group.
To post to this group, send email to adwords-api@googlegroups.com
To unsubscribe from this group, send email to
adwords-api+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/adwords-api?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Google Ads API and AdWords API Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to adwords-api+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/adwords-api/3bd3f46f-0e14-4139-a875-16a98c7e5a1bn%40googlegroups.com.
  • Re... Bjoern Ammon
    • ... 'Google Ads API Forum Advisor' via Google Ads API and AdWords API Forum
    • ... Bjoern Ammon

Reply via email to