Generate User Credentials
Stay organized with collections
Save and categorize content based on your preferences.
Java
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package
com.google.ads.googleads.examples.authentication
;
import
com.beust.jcommander.Parameter
;
import
com.google.ads.googleads.examples.utils.ArgumentNames
;
import
com.google.ads.googleads.examples.utils.CodeSampleParams
;
import
com.google.ads.googleads.lib.GoogleAdsClient
;
import
com.google.ads.googleads.lib.GoogleAdsClient.Builder.ConfigPropertyKey
;
import
com.google.api.client.http.GenericUrl
;
import
com.google.api.client.http.HttpStatusCodes
;
import
com.google.api.client.util.Key
;
import
com.google.auth.oauth2.ClientId
;
import
com.google.auth.oauth2.UserAuthorizer
;
import
com.google.auth.oauth2.UserCredentials
;
import
com.google.common.base.MoreObjects
;
import
com.google.common.base.Preconditions
;
import
com.google.common.base.Strings
;
import
com.google.common.collect.ImmutableList
;
import
java.io.BufferedReader
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.io.OutputStreamWriter
;
import
java.io.Writer
;
import
java.math.BigInteger
;
import
java.net.ServerSocket
;
import
java.net.Socket
;
import
java.net.URI
;
import
java.nio.charset.StandardCharsets
;
import
java.security.SecureRandom
;
import
java.util.List
;
import
java.util.Properties
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
/**
* Creates an OAuth2 refresh token for the Google Ads API. This example works with both web and
* desktop app OAuth client ID types.
*
* <p>IMPORTANT: For web app clients types, you must add {@code http://127.0.0.1} to the "Authorized
* redirect URIs" list in your Google Cloud Console project before running this example. Desktop app
* client types do not require the local redirect to be explicitly configured in the console.
*
* <p>This example will start a basic server that listens for requests at {@code
* http://127.0.0.1:PORT}, where {@code PORT} is dynamically assigned.
*/
public
class
GenerateUserCredentials
{
private
static
class
GenerateUserCredentialsParams
extends
CodeSampleParams
{
@Parameter
(
names
=
ArgumentNames
.
OAUTH_CLIENT_FILE
,
required
=
true
,
description
=
"JSON file downloaded from the Google Cloud Console that contains the OAuth client"
+
" details."
)
private
String
oAuthClientFile
;
@Parameter
(
names
=
ArgumentNames
.
LOGIN_EMAIL_ADDRESS_HINT
,
required
=
false
,
description
=
"If your application knows which user is trying to authenticate, you can set this to"
+
" the user's email address so that the Google Authentication Server will"
+
" automatically populate the account selection prompt with that address."
)
private
String
loginEmailAddressHint
;
@Parameter
(
names
=
ArgumentNames
.
OAUTH_SCOPES
,
required
=
false
,
description
=
"Scopes for the generated OAuth2 credentials. Set to the Google Ads API scope by"
+
" default, but you can add multiple scopes if you want to use the credentials for"
+
" other Google APIs."
)
private
List<String>
oAuthScopes
=
SCOPES
;
}
// Scopes for the generated OAuth2 credentials. The list here only contains the Google Ads API
// scope, but you can add multiple scopes if you want to use the credentials for other Google
// APIs.
private
static
final
ImmutableList<String>
SCOPES
=
ImmutableList
.
< String>builder
().
add
(
"https://www.googleapis.com/auth/adwords"
).
build
();
private
static
final
String
OAUTH2_CALLBACK_BASE_URI
=
"http://127.0.0.1"
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
// To fill in the values below, generate a client ID and client secret from the Google Cloud
// Console (https://console.cloud.google.com) by creating credentials for either a web or
// desktop app OAuth client ID.
// If using a web application, add the following to its "Authorized redirect URIs":
// http://127.0.0.1
String
clientId
;
String
clientSecret
;
String
loginEmailAddressHint
;
List<String>
scopes
=
SCOPES
;
GenerateUserCredentialsParams
params
=
new
GenerateUserCredentialsParams
();
if
(
!
params
.
parseArguments
(
args
))
{
// Either pass the required parameters for this example on the command line, or insert them
// into the code here. See the parameter class definition above for descriptions.
clientId
=
"INSERT_CLIENT_ID_HERE"
;
clientSecret
=
"INSERT_CLIENT_SECRET_HERE"
;
// Optional: If your application knows which user is trying to authenticate, you can set this
// to the user's email address so that the Google Authentication Server will automatically
// populate the account selection prompt with that address.
loginEmailAddressHint
=
null
;
// Ensures that the client ID and client secret are not the "INSERT_..._HERE" values.
Preconditions
.
checkArgument
(
!
clientId
.
matches
(
"INSERT_.*_HERE"
),
"Client ID is invalid. Please update the example and try again."
);
Preconditions
.
checkArgument
(
!
clientSecret
.
matches
(
"INSERT_.*_HERE"
),
"Client secret is invalid. Please update the example and try again."
);
}
else
{
// Extracts the OAuth client information from the provided file.
ClientId
parsedClient
=
ClientId
.
fromStream
(
new
FileInputStream
(
params
.
oAuthClientFile
));
clientId
=
parsedClient
.
getClientId
();
clientSecret
=
parsedClient
.
getClientSecret
();
loginEmailAddressHint
=
params
.
loginEmailAddressHint
;
scopes
=
params
.
oAuthScopes
;
}
new
GenerateUserCredentials
().
runExample
(
clientId
,
clientSecret
,
loginEmailAddressHint
,
scopes
);
}
public
void
runExample
(
String
clientId
,
String
clientSecret
,
String
loginEmailAddressHint
,
List<String>
scopes
)
throws
Exception
{
// Creates an anti-forgery state token as described here:
// https://developers.google.com/identity/protocols/OpenIDConnect#createxsrftoken
String
state
=
new
BigInteger
(
130
,
new
SecureRandom
()).
toString
(
32
);
// Creates an HTTP server that will listen for the OAuth2 callback request.
URI
baseUri
;
UserAuthorizer
userAuthorizer
;
AuthorizationResponse
authorizationResponse
=
null
;
try
(
SimpleCallbackServer
simpleCallbackServer
=
new
SimpleCallbackServer
())
{
userAuthorizer
=
UserAuthorizer
.
newBuilder
()
.
setClientId
(
ClientId
.
of
(
clientId
,
clientSecret
))
.
setScopes
(
scopes
)
// Provides an empty callback URI so that no additional suffix is added to the
// redirect. By default, UserAuthorizer will use "/oauth2callback" if this is either
// not set or set to null.
.
setCallbackUri
(
URI
.
create
(
""
))
.
build
();
baseUri
=
URI
.
create
(
OAUTH2_CALLBACK_BASE_URI
+
":"
+
simpleCallbackServer
.
getLocalPort
());
System
.
out
.
printf
(
"Paste this url in your browser:%n%s%n"
,
userAuthorizer
.
getAuthorizationUrl
(
loginEmailAddressHint
,
state
,
baseUri
));
// Waits for the authorization code.
simpleCallbackServer
.
accept
();
authorizationResponse
=
simpleCallbackServer
.
authorizationResponse
;
}
if
(
authorizationResponse
==
null
||
authorizationResponse
.
code
==
null
)
{
throw
new
NullPointerException
(
"OAuth2 callback did not contain an authorization code: "
+
authorizationResponse
);
}
// Confirms that the state in the response matches the state token used to generate the
// authorization URL.
if
(
!
state
.
equals
(
authorizationResponse
.
state
))
{
throw
new
IllegalStateException
(
"State does not match expected state"
);
}
// Exchanges the authorization code for credentials and print the refresh token.
UserCredentials
userCredentials
=
userAuthorizer
.
getCredentialsFromCode
(
authorizationResponse
.
code
,
baseUri
);
System
.
out
.
printf
(
"Your refresh token is: %s%n"
,
userCredentials
.
getRefreshToken
());
// Prints the configuration file contents.
Properties
adsProperties
=
new
Properties
();
adsProperties
.
put
(
ConfigPropertyKey
.
CLIENT_ID
.
getPropertyKey
(),
clientId
);
adsProperties
.
put
(
ConfigPropertyKey
.
CLIENT_SECRET
.
getPropertyKey
(),
clientSecret
);
adsProperties
.
put
(
ConfigPropertyKey
.
REFRESH_TOKEN
.
getPropertyKey
(),
userCredentials
.
getRefreshToken
());
adsProperties
.
put
(
ConfigPropertyKey
.
DEVELOPER_TOKEN
.
getPropertyKey
(),
"INSERT_DEVELOPER_TOKEN_HERE"
);
showConfigurationFile
(
adsProperties
);
}
private
void
showConfigurationFile
(
Properties
adsProperties
)
throws
IOException
{
System
.
out
.
printf
(
"Copy the text below into a file named %s in your home directory, and replace "
+
"INSERT_XXX_HERE with your configuration:%n"
,
GoogleAdsClient
.
Builder
.
DEFAULT_PROPERTIES_CONFIG_FILE_NAME
);
System
.
out
.
println
(
"######################## Configuration file start ########################"
);
adsProperties
.
store
(
System
.
out
,
null
);
System
.
out
.
printf
(
"# Required for manager accounts only: Specify the login customer ID used to%n"
+
"# authenticate API calls. This will be the customer ID of the authenticated%n"
+
"# manager account. You can also specify this later in code if your application%n"
+
"# uses multiple manager account + OAuth pairs.%n"
+
"#%n"
);
System
.
out
.
println
(
"# "
+
ConfigPropertyKey
.
LOGIN_CUSTOMER_ID
.
getPropertyKey
()
+
"=INSERT_LOGIN_CUSTOMER_ID"
);
System
.
out
.
println
(
"######################## Configuration file end ##########################"
);
}
/** Basic server that listens for the OAuth2 callback. */
private
static
class
SimpleCallbackServer
extends
ServerSocket
{
private
AuthorizationResponse
authorizationResponse
;
SimpleCallbackServer
()
throws
IOException
{
// Passes a port # of zero so that a port will be automatically allocated.
super
(
0
);
}
/**
* Blocks until a connection is made to this server. After this method completes, the
* authorizationResponse of this server will be set, provided the request line is in the
* expected format.
*/
@Override
public
Socket
accept
()
throws
IOException
{
Socket
socket
=
super
.
accept
();
try
(
BufferedReader
in
=
new
BufferedReader
(
new
InputStreamReader
(
socket
.
getInputStream
(),
StandardCharsets
.
UTF_8
)))
{
String
callbackRequest
=
in
.
readLine
();
// Uses a regular expression to extract the request line from the first line of the
// callback request, e.g.:
// GET /?code=AUTH_CODE&state=XYZ&scope=https://www.googleapis.com/auth/adwords HTTP/1.1
Pattern
pattern
=
Pattern
.
compile
(
"GET +([^ ]+)"
);
Matcher
matcher
=
pattern
.
matcher
(
Strings
.
nullToEmpty
(
callbackRequest
));
if
(
matcher
.
find
())
{
String
relativeUrl
=
matcher
.
group
(
1
);
authorizationResponse
=
new
AuthorizationResponse
(
OAUTH2_CALLBACK_BASE_URI
+
relativeUrl
);
}
try
(
Writer
outputWriter
=
new
OutputStreamWriter
(
socket
.
getOutputStream
()))
{
outputWriter
.
append
(
"HTTP/1.1 "
);
outputWriter
.
append
(
Integer
.
toString
(
HttpStatusCodes
.
STATUS_CODE_OK
));
outputWriter
.
append
(
" OK\n"
);
outputWriter
.
append
(
"Content-Type: text/html\n\n"
);
outputWriter
.
append
(
"<b>"
);
if
(
authorizationResponse
.
code
!=
null
)
{
outputWriter
.
append
(
"Authorization code was successfully retrieved."
);
}
else
{
outputWriter
.
append
(
"Failed to retrieve authorization code."
);
}
outputWriter
.
append
(
"</b>"
);
outputWriter
.
append
(
"<p>Please check the console output from <code>"
);
outputWriter
.
append
(
GenerateUserCredentials
.
class
.
getSimpleName
());
outputWriter
.
append
(
"</code> for further instructions."
);
}
}
return
socket
;
}
}
/** Response object with attributes corresponding to OAuth2 callback parameters. */
static
class
AuthorizationResponse
extends
GenericUrl
{
/** The authorization code to exchange for an access token and (optionally) a refresh token. */
@Key
String
code
;
/** Error from the request or from the processing of the request. */
@Key
String
error
;
/** State parameter from the callback request. */
@Key
String
state
;
/**
* Constructs a new instance based on an absolute URL. All fields annotated with the {@link Key}
* annotation will be set if they are present in the URL.
*
* @param encodedUrl absolute URL with query parameters.
*/
public
AuthorizationResponse
(
String
encodedUrl
)
{
super
(
encodedUrl
);
}
@Override
public
String
toString
()
{
return
MoreObjects
.
toStringHelper
(
getClass
())
.
add
(
"code"
,
code
)
.
add
(
"error"
,
error
)
.
add
(
"state"
,
state
)
.
toString
();
}
}
}
C#
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using
Google.Apis.Auth.OAuth2
;
using
Google.Apis.Auth.OAuth2.Flows
;
using
Google.Apis.Util.Store
;
using
System
;
using
System.Threading
;
using
System.Threading.Tasks
;
namespace
Google.Ads.GoogleAds.Examples
{
/// <summary>
/// Entry point for the application.
/// </summary>
internal
class
Program
{
/// <summary>
/// The Google Ads API scope.
/// </summary>
private
const
string
GOOGLE_ADS_API_SCOPE
=
"https://www.googleapis.com/auth/adwords"
;
/// <summary>
/// The main entry point for the application.
/// </summary>
public
static
void
Main
(
string
[]
args
)
{
Console
.
WriteLine
(
"This code example creates an OAuth2 refresh token for the "
+
"Google Ads API .NET Client library. This example works with both web and "
+
"desktop app OAuth client ID types. To use this application\n"
+
"1) Follow the instructions on "
+
"https://developers.google.com/google-ads/api/docs/oauth/cloud-project "
+
"to generate a new client ID and secret.\n"
+
"2) Run this application.\n"
+
"3) Enter the client ID and client secret when prompted and follow the instructions.\n"
+
"4) Once the output is generated, copy its contents into your App.config "
+
"file. See https://developers.google.com/google-ads/api/docs/client-libs/dotnet/configuration "
+
"for other configuration options.\n\n"
);
Console
.
WriteLine
(
"IMPORTANT: For web app clients types, you must add "
+
"'http://127.0.0.1/authorize' to the 'Authorized redirect URIs' list in your "
+
"Google Cloud Console project before running this example to avoid getting a "
+
"redirect_uri_mismatch error. Desktop app client types do not require the "
+
"local redirect to be explicitly configured in the console.\n\n"
);
// Accept the client ID from user.
Console
.
Write
(
"Enter the client ID: "
);
string
clientId
=
Console
.
ReadLine
();
// Accept the client ID from user.
Console
.
Write
(
"Enter the client secret: "
);
string
clientSecret
=
Console
.
ReadLine
();
// Load the JSON secrets.
ClientSecrets
secrets
=
new
ClientSecrets
()
{
ClientId
=
clientId
,
ClientSecret
=
clientSecret
};
try
{
var
initializer
=
new
GoogleAuthorizationCodeFlow
.
Initializer
{
ClientSecrets
=
secrets
,
Prompt
=
"consent"
,
};
// Authorize the user using desktop flow. GoogleWebAuthorizationBroker creates a
// web server that listens to a random port at 127.0.0.1 and the /authorize url
// as loopback url. See https://github.com/googleapis/google-api-dotnet-client/blob/main/Src/Support/Google.Apis.Auth/OAuth2/LocalServerCodeReceiver.cs
// for details.
Task<UserCredential>
task
=
GoogleWebAuthorizationBroker
.
AuthorizeAsync
(
initializer
,
new
string
[]
{
GOOGLE_ADS_API_SCOPE
},
string
.
Empty
,
CancellationToken
.
None
,
new
NullDataStore
()
);
UserCredential
credential
=
task
.
Result
;
Console
.
WriteLine
(
"\nCopy the following content into your App.config file.\n\n"
+
$"<add key = 'OAuth2Mode' value = 'APPLICATION' />\n"
+
$"<add key = 'OAuth2ClientId' value = '{clientId}' />\n"
+
$"<add key = 'OAuth2ClientSecret' value = '{clientSecret}' />\n"
+
$"<add key = 'OAuth2RefreshToken' value = "
+
$"'{credential.Token.RefreshToken}' />\n"
);
Console
.
WriteLine
(
$"Make sure you also set the values of LOGIN_CUSTOMER_ID header."
+
" See https://developers.google.com/google-ads/api/docs/client-libs/dotnet/configuration#google_ads_api_settings"
+
" to learn more.\n"
+
"<add key = 'LoginCustomerId' value = 'INSERT_LOGIN_CUSTOMER_ID_HERE' />"
);
Console
.
WriteLine
(
"See https://developers.google.com/google-ads/api/docs/client-libs/dotnet/configuration "
+
"for alternate configuration options."
);
Console
.
WriteLine
(
"Press <Enter> to continue..."
);
Console
.
ReadLine
();
}
catch
(
AggregateException
)
{
Console
.
WriteLine
(
"An error occurred while authorizing the user."
);
}
}
}
}
PHP
< ?php
/*
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Google\AdsApi\Examples\Authentication;
require __DIR__ . '/../../vendor/autoload.php';
use Google\Auth\CredentialsLoader;
use Google\Auth\OAuth2;
use Psr\Http\Message\ServerRequestInterface;
use React\EventLoop\Loop;
use React\Http\HttpServer;
use React\Http\Message\Response;
use React\Socket\SocketServer;
use UnexpectedValueException;
/**
* This example will create an OAuth2 refresh token for the Google Ads API. This example works with
* both web and desktop app OAuth client ID types.
*
* We highly recommend running this example locally, since you won't need to generate refresh tokens
* very often and you can avoid issue of port settings that may occur when using a Docker container.
*
* IMPORTANT: For web app clients types, you must add "http://127.0.0.1" to the "Authorized
* redirect URIs" list in your Google Cloud Console project before running this example. Desktop app
* client types do not require the local redirect to be explicitly configured in the console.
*
* <p>This example will start a basic server that listens for requests at `http://127.0.0.1:PORT`,
* where `PORT` is dynamically assigned.
*/
class GenerateUserCredentials
{
/**
* @var string the OAuth2 scope for the Google Ads API
* @see https://developers.google.com/google-ads/api/docs/oauth/internals#scope
*/
private const SCOPE = 'https://www.googleapis.com/auth/adwords';
/**
* @var string the Google OAuth2 authorization URI for OAuth2 requests
* @see https://developers.google.com/identity/protocols/OAuth2InstalledApp#step-2-send-a-request-to-googles-oauth-20-server
*/
private const AUTHORIZATION_URI = 'https://accounts.google.com/o/oauth2/v2/auth';
/**
* @var string the OAuth2 call back IP address.
*/
private const OAUTH2_CALLBACK_IP_ADDRESS = '127.0.0.1';
public static function main()
{
if (!class_exists(HttpServer::class)) {
echo 'Please install "react/http" package to be able to run this example';
exit(1);
}
// Creates a socket for localhost with random port. Port 0 is used to tell the SocketServer
// to create a server with a random port.
$socket = new SocketServer(self::OAUTH2_CALLBACK_IP_ADDRESS . ':0');
// To fill in the values below, generate a client ID and client secret from the Google Cloud
// Console (https://console.cloud.google.com) by creating credentials for either a web or
// desktop app OAuth client ID.
// If using a web application, add the following to its "Authorized redirect URIs":
// http://127.0.0.1
print 'Enter your OAuth2 client ID here: ';
$clientId = trim(fgets(STDIN));
print 'Enter your OAuth2 client secret here: ';
$clientSecret = trim(fgets(STDIN));
$redirectUrl = str_replace('tcp:', 'http:', $socket->getAddress());
$oauth2 = new OAuth2(
[
'clientId' => $clientId,
'clientSecret' => $clientSecret,
'authorizationUri' => self::AUTHORIZATION_URI,
'redirectUri' => $redirectUrl,
'tokenCredentialUri' => CredentialsLoader::TOKEN_CREDENTIAL_URI,
'scope' => self::SCOPE,
// Create a 'state' token to prevent request forgery. See
// https://developers.google.com/identity/protocols/OpenIDConnect#createxsrftoken
// for details.
'state' => sha1(openssl_random_pseudo_bytes(1024))
]
);
$authToken = null;
$server = new HttpServer(
function (ServerRequestInterface $request) use ($oauth2, &$authToken) {
// Stops the server after tokens are retrieved.
if (!is_null($authToken)) {
Loop::stop();
}
// Check if the requested path is the one set as the redirect URI. We add '/' here
// so the parse_url method can function correctly, since it cannot detect the URI
// without '/' at the end, which is the case for the value of getRedirectUri().
if (
$request->getUri()->getPath()
!== parse_url($oauth2->getRedirectUri() . '/', PHP_URL_PATH)
) {
return new Response(
404,
['Content-Type' => 'text/plain'],
'Page not found'
);
}
// Exit if the state is invalid to prevent request forgery.
$state = $request->getQueryParams()['state'];
if (empty($state) || ($state !== $oauth2->getState())) {
throw new UnexpectedValueException(
"The state is empty or doesn't match expected one." . PHP_EOL
);
};
// Set the authorization code and fetch refresh and access tokens.
$code = $request->getQueryParams()['code'];
$oauth2->setCode($code);
$authToken = $oauth2->fetchAuthToken();
$refreshToken = $authToken['refresh_token'];
print 'Your refresh token is: ' . $refreshToken . PHP_EOL;
$propertiesToCopy = '[GOOGLE_ADS]' . PHP_EOL;
$propertiesToCopy .= 'developerToken = "INSERT_DEVELOPER_TOKEN_HERE"' . PHP_EOL;
$propertiesToCopy .= <<<EOD
; Required for manager accounts only: Specify the login customer ID used to authenticate API calls.
; This will be the customer ID of the authenticated manager account. You can also specify this later
; in code if your application uses multiple manager account + OAuth pairs.
; loginCustomerId = "INSERT_LOGIN_CUSTOMER_ID_HERE"
EOD;
$propertiesToCopy .= PHP_EOL . '[OAUTH2]' . PHP_EOL;
$propertiesToCopy .= "clientId = \"{$oauth2->getClientId()}\"" . PHP_EOL;
$propertiesToCopy .= "clientSecret = \"{$oauth2->getClientSecret()}\"" . PHP_EOL;
$propertiesToCopy .= "refreshToken = \"$refreshToken\"" . PHP_EOL;
print 'Copy the text below into a file named "google_ads_php.ini" in your home '
. 'directory, and replace "INSERT_DEVELOPER_TOKEN_HERE" with your developer '
. 'token:' . PHP_EOL;
print PHP_EOL . $propertiesToCopy;
return new Response(
200,
['Content-Type' => 'text/plain'],
'Your refresh token has been fetched. Check the console output for '
. 'further instructions.'
);
}
);
$server->listen($socket);
printf(
'Log into the Google account you use for Google Ads and visit the following URL '
. 'in your web browser: %1$s%2$s%1$s%1$s',
PHP_EOL,
$oauth2->buildFullAuthorizationUri(['access_type' => 'offline'])
);
}
}
GenerateUserCredentials::main();
Python
#!/usr/bin/env python
# Copyright 2018 Google LLC
from
typing
import
List
,
Dict
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This example will create an OAuth2 refresh token for the Google Ads API.
This example works with both web and desktop app OAuth client ID types.
https://console.cloud.google.com
IMPORTANT: For web app clients types, you must add "http://127.0.0.1" to the
"Authorized redirect URIs" list in your Google Cloud Console project before
running this example. Desktop app client types do not require the local
redirect to be explicitly configured in the console.
Once complete, download the credentials and save the file path so it can be
passed into this example.
This example is a very simple implementation, for a more detailed example see:
https://developers.google.com/identity/protocols/oauth2/web-server#python
"""
import
argparse
import
hashlib
import
os
import
re
import
socket
import
sys
from
urllib.parse
import
unquote
# If using Web flow, the redirect URL must match exactly what’s configured in GCP for
# the OAuth client. If using Desktop flow, the redirect must be a localhost URL and
# is not explicitly set in GCP.
from
google_auth_oauthlib.flow
import
Flow
_SCOPE
=
"https://www.googleapis.com/auth/adwords"
_SERVER
=
"127.0.0.1"
_PORT
=
8080
_REDIRECT_URI
=
f
"http://
{
_SERVER
}
:
{
_PORT
}
"
def
main
(
client_secrets_path
:
str
,
scopes
:
List
[
str
])
-
> None
:
"""The main method, starts a basic server and initializes an auth request.
Args:
client_secrets_path: a path to where the client secrets JSON file is
located on the machine running this example.
scopes: a list of API scopes to include in the auth request, see:
https://developers.google.com/identity/protocols/oauth2/scopes
"""
flow
=
Flow
.
from_client_secrets_file
(
client_secrets_path
,
scopes
=
scopes
)
flow
.
redirect_uri
=
_REDIRECT_URI
# Create an anti-forgery state token as described here:
# https://developers.google.com/identity/protocols/OpenIDConnect#createxsrftoken
passthrough_val
=
hashlib
.
sha256
(
os
.
urandom
(
1024
))
.
hexdigest
()
authorization_url
,
state
=
flow
.
authorization_url
(
access_type
=
"offline"
,
state
=
passthrough_val
,
prompt
=
"consent"
,
include_granted_scopes
=
"true"
,
)
# Prints the authorization URL so you can paste into your browser. In a
# typical web application you would redirect the user to this URL, and they
# would be redirected back to "redirect_url" provided earlier after
# granting permission.
print
(
"Paste this URL into your browser: "
)
print
(
authorization_url
)
print
(
f
"
\n
Waiting for authorization and callback to:
{
_REDIRECT_URI
}
"
)
# Retrieves an authorization code by opening a socket to receive the
# redirect request and parsing the query parameters set in the URL.
code
=
unquote
(
get_authorization_code
(
passthrough_val
))
# Pass the code back into the OAuth module to get a refresh token.
flow
.
fetch_token
(
code
=
code
)
refresh_token
=
flow
.
credentials
.
refresh_token
print
(
f
"
\n
Your refresh token is:
{
refresh_token
}
\n
"
)
print
(
"Add your refresh token to your client library configuration as "
"described here: "
"https://developers.google.com/google-ads/api/docs/client-libs/python/configuration"
)
def
get_authorization_code
(
passthrough_val
:
str
)
-
> str
:
"""Opens a socket to handle a single HTTP request containing auth tokens.
Args:
passthrough_val: an anti-forgery token used to verify the request
received by the socket.
Returns:
a str access token from the Google Auth service.
"""
# Open a socket at _SERVER:_PORT and listen for a request
sock
=
socket
.
socket
()
sock
.
setsockopt
(
socket
.
SOL_SOCKET
,
socket
.
SO_REUSEADDR
,
1
)
sock
.
bind
((
_SERVER
,
_PORT
))
sock
.
listen
(
1
)
connection
,
address
=
sock
.
accept
()
data
=
connection
.
recv
(
1024
)
# Parse the raw request to retrieve the URL query parameters.
params
=
parse_raw_query_params
(
data
)
try
:
if
not
params
.
get
(
"code"
):
# If no code is present in the query params then there will be an
# error message with more details.
error
=
params
.
get
(
"error"
)
message
=
f
"Failed to retrieve authorization code. Error:
{
error
}
"
raise
ValueError
(
message
)
elif
params
.
get
(
"state"
)
!=
passthrough_val
:
message
=
"State token does not match the expected state."
raise
ValueError
(
message
)
else
:
message
=
"Authorization code was successfully retrieved."
except
ValueError
as
error
:
print
(
error
)
sys
.
exit
(
1
)
finally
:
response
=
(
"HTTP/1.1 200 OK
\n
"
"Content-Type: text/html
\n\n
"
f
"<b>
{
message
}
< /b>"
"<p>Please check the console output.</p>
\n
"
)
connection
.
sendall
(
response
.
encode
())
connection
.
close
()
return
params
.
get
(
"code"
)
def
parse_raw_query_params
(
data
:
bytes
)
-
> Dict
[
str
,
str
]:
"""Parses a raw HTTP request to extract its query params as a dict.
Note that this logic is likely irrelevant if you're building OAuth logic
into a complete web application, where response parsing is handled by a
framework.
Args:
data: raw request data as bytes.
Returns:
a dict of query parameter key value pairs.
"""
# Decode the request into a utf-8 encoded string
decoded
=
data
.
decode
(
"utf-8"
)
# Use a regular expression to extract the URL query parameters string
match
=
re
.
search
(
r
"GET\s\/\?(.*) "
,
decoded
)
params
=
match
.
group
(
1
)
# Split the parameters to isolate the key/value pairs
pairs
=
[
pair
.
split
(
"="
)
for
pair
in
params
.
split
(
"&"
)]
# Convert pairs to a dict to make it easy to access the values
return
{
key
:
val
for
key
,
val
in
pairs
}
if
__name__
==
"__main__"
:
parser
=
argparse
.
ArgumentParser
(
description
=
(
"Generates OAuth2 refresh token using the Web application flow. "
"To retrieve the necessary client_secrets JSON file, first "
"generate OAuth 2.0 credentials of type Web application in the "
"Google Cloud Console (https://console.cloud.google.com). "
"Make sure 'http://_SERVER:_PORT' is included the list of "
"'Authorized redirect URIs' for this client ID."
),
)
# The following argument(s) should be provided to run the example.
parser
.
add_argument
(
"-c"
,
"--client_secrets_path"
,
required
=
True
,
type
=
str
,
help
=
(
"Path to the client secrets JSON file from the Google Developers "
"Console that contains your client ID, client secret, and "
"redirect URIs."
),
)
parser
.
add_argument
(
"--additional_scopes"
,
default
=
None
,
type
=
str
,
nargs
=
"+"
,
help
=
"Additional scopes to apply when generating the refresh token."
,
)
args
=
parser
.
parse_args
()
configured_scopes
=
[
_SCOPE
]
if
args
.
additional_scopes
:
configured_scopes
.
extend
(
args
.
additional_scopes
)
main
(
args
.
client_secrets_path
,
configured_scopes
)
Ruby
#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This example will create an OAuth2 refresh token for the Google Ads API using
# the Web application flow.
#
# This example will start a basic server that listens for requests at
# http://localhost:PORT, where PORT is the port specified below.
require
'googleauth'
require
'securerandom'
require
'uri'
require
'cgi'
require
'socket'
require
'json'
require
'optparse'
def
generate_user_credential
(
path
)
json
=
JSON
.
load_file
(
path
)
creds
,
callback_uri
,
port
=
if
!
json
[
"installed"
].
nil?
[
json
[
"installed"
]
,
"http://
#{
SERVER
}
:
#{
PORT
}
"
,
PORT
]
elsif
!
json
[
"web"
].
nil?
web_creds
=
json
[
"web"
]
# If you have more than one redirect URI, you may need to add some
# code here to ensure that you choose the correct one.
uri
=
json
[
"web"
][
"redirect_uris"
].
first
port
=
uri
.
split
(
":"
)
.
last
[
web_creds
,
uri
,
port
]
else
raise
"No installed or web credentials found."
end
# Create an anti-forgery state token as described here:
# https://developers.google.com/identity/protocols/OpenIDConnect#createxsrftoken
state
=
SecureRandom
.
hex
(
16
)
client_id
=
Google
::
Auth
::
ClientId
.
new
(
creds
[
"client_id"
]
,
creds
[
"client_secret"
]
,
)
# This example does not store credentials, so no TokenStore is needed.
user_authorizer
=
Google
::
Auth
::
UserAuthorizer
.
new
(
client_id
,
SCOPE
,
nil
,
callback_uri
)
authorization_url
=
user_authorizer
.
get_authorization_url
(
state
:
state
)
printf
(
"Paste this url in your browser:
\n
%s
\n
"
,
authorization_url
)
printf
(
"Waiting for authorization and callback...
\n
"
)
printf
(
"Listening at %s
\n
"
,
callback_uri
)
response_params
=
get_authorization_code
(
port
)
# Confirm that the state in the response matches the state token used to
# generate the authorization URL.
unless
state
==
response_params
[
'state'
][
0
]
raise
StandardError
,
'State returned from callback does not match the expected state'
end
user_credentials
=
user_authorizer
.
get_credentials_from_code
(
code
:
response_params
[
'code'
][
0
]
)
printf
(
"Your refresh token is: %s
\n
"
,
user_credentials
.
refresh_token
)
printf
(
"Copy your refresh token above into your google_ads_config.rb in your "
\
"home directory or use it when instantiating the library.
\n
"
)
end
def
get_authorization_code
(
port
)
authorization_code
=
nil
server
=
TCPServer
.
open
(
port
)
client
=
server
.
accept
callback_request
=
client
.
readline
# Use a regular expression to extract the request line from the first line of
# the callback request, e.g.:
# GET /?code=AUTH_CODE&state=XYZ&scope=... HTTP/1.1
matcher
=
/GET +([^ ]+)/
.
match
(
callback_request
)
response_params
=
CGI
.
parse
(
URI
.
parse
(
matcher
[
1
]
)
.
query
)
unless
matcher
.
nil?
client
.
puts
(
"HTTP/1.1 200 OK"
)
client
.
puts
(
"Content-Type: text/html"
)
client
.
puts
(
""
)
client
.
puts
(
"<b>"
)
if
response_params
[
'code'
].
nil?
client
.
puts
(
"Failed to retrieve authorization code."
)
else
client
.
puts
(
"Authorization code was successfully retrieved."
)
end
client
.
puts
(
"</b>"
)
client
.
puts
(
"<p>Please check the console output.</p>"
)
client
.
close
return
response_params
end
if
__FILE__
==
$PROGRAM_NAME
SCOPE
=
'https://www.googleapis.com/auth/adwords'
SERVER
=
'127.0.0.1'
PORT
=
8080
# To fill in the values below, generate a client secret JSON file from the
# Google Cloud Console (https://console.cloud.google.com) by creating
# credentials for a web or desktop application. If using a web application,
# add the following to its "Authorized redirect URIs":
# http://127.0.0.1:[PORT]
options
=
{}
# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
options
[
:path
]
=
'INSERT_CLIENT_SECRETS_PATH_HERE'
OptionParser
.
new
do
|
opts
|
opts
.
banner
=
sprintf
(
'Usage: %s [options]'
,
File
.
basename
(
__FILE__
))
opts
.
separator
''
opts
.
separator
'Options:'
opts
.
on
(
'-P'
,
'--client-secrets-path CLIENT-SECRETS-PATH'
,
String
,
'Client Secrets Path'
)
do
|
v
|
options
[
:path
]
=
v
end
opts
.
separator
''
opts
.
separator
'Help:'
opts
.
on_tail
(
'-h'
,
'--help'
,
'Show this message'
)
do
puts
opts
exit
end
end
.
parse!
generate_user_credential
(
options
[
:path
]
,
)
end
Perl
#!/usr/bin/perl -w
#
# Copyright 2019, Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This example will create an OAuth2 refresh token for the Google Ads API.
# This works with both web and desktop app OAuth client ID types.
#
# This example will start a basic server that listens for requests at
# http://127.0.0.1:PORT, where PORT defaults to 8080 as below.
#
#
# [IMPORTANT]: For web app client types, you must add http://127.0.0.1 to the
# "Authorize redirect URIs" list in your Google Cloud Console project before
# running this example. Desktop app client types do not require the local
# redirect to be explicitly configured in the console.
use
strict
;
use
warnings
;
use
utf8
;
use
FindBin
qw($Bin)
;
use
lib
"$Bin/../../lib"
;
use
Google::Ads::GoogleAds::Client
;
use
Google::Ads::GoogleAds::Utils::GoogleAdsHelper
;
use
Getopt::Long
qw(:config auto_help)
;
use
Pod::Usage
;
use
Cwd
qw(abs_path)
;
use
Data::Uniqid
qw(uniqid)
;
use
Digest::SHA
qw(sha1_hex)
;
use
constant
OAUTH2_CALLBACK_BASE_URI
=
>
"http://127.0.0.1"
;
use
constant
PORT
=
>
8080
;
# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
my
$client_id
=
"INSERT_CLIENT_ID_HERE"
;
my
$client_secret
=
"INSERT_CLIENT_SECRET_HERE"
;
my
$additional_scopes
=
"INSERT_ADDITIONAL_SCOPES_HERE"
;
# Create an anti-forgery state token as described here:
# https://developers.google.com/identity/protocols/OpenIDConnect#createxsrftoken
our
$state
=
sha1_hex
(
uniqid
);
sub
generate_user_credentials
{
my
(
$api_client
,
$client_id
,
$client_secret
,
$additional_scopes
)
=
@_
;
my
$auth_handler
=
$api_client
-
> get_oauth2_handler
();
my
$callback_url
=
sprintf
(
"%s:%d"
,
OAUTH2_CALLBACK_BASE_URI
,
PORT
);
$auth_handler
-
> set_client_id
(
$client_id
);
$auth_handler
-
> set_client_secret
(
$client_secret
);
$auth_handler
-
> set_redirect_uri
(
$callback_url
);
$auth_handler
-
> set_additional_scopes
(
$additional_scopes
)
if
check_params
(
$additional_scopes
);
# Open a browser and point it to the authorization URL, authorize the access.
print
"\nPaste this url in your browser:\n"
,
$auth_handler
-
> get_authorization_url
(
$state
),
"\n\n"
;
printf
"Waiting for authorization and callback to %s ...\n"
,
$callback_url
;
SimpleCallbackServer
-
> new
(
PORT
,
$auth_handler
)
-
> run
;
return
1
;
}
{
# Simple CGI server that listens for the OAuth2 callback.
package
SimpleCallbackServer
;
use
HTTP::Server::Simple::CGI
;
use
base
qw(HTTP::Server::Simple::CGI)
;
sub
new
{
my
(
$class
,
$port
,
$auth_handler
)
=
@_
;
my
$self
=
HTTP::Server::Simple::
CGI
-
> new
(
$port
);
$self
-
> {
auth_handler
}
=
$auth_handler
;
bless
$self
,
$class
;
return
$self
;
}
my
%dispatch
=
(
'/'
=
>
\
& resp_callback
);
sub
handle_request
{
my
(
$self
,
$cgi
)
=
@_
;
my
$path
=
$cgi
-
> path_info
;
my
$handler
=
$dispatch
{
$path
};
if
(
ref
(
$handler
)
eq
"CODE"
)
{
print
"HTTP/1.0 200 OK\r\n"
;
$handler
-
> (
$self
,
$cgi
);
}
else
{
print
"HTTP/1.0 404 Not found\r\n"
;
print
$cgi
-
> header
,
$cgi
-
> start_html
(
'Not found'
),
$cgi
-
> h1
(
'Not found'
),
$cgi
-
> end_html
;
}
}
# The method to handle the callback request after user logs in and accepts
# the OAuth2 prompt. An authorization code will be returned which can be
# exchanged for an access token and refresh token.
sub
resp_callback
{
my
(
$self
,
$cgi
)
=
@_
;
return
if
!
ref
$cgi
;
# Get the authorization code and state parameters from the URL.
my
$code
=
$cgi
-
> param
(
'code'
);
my
$state
=
$cgi
-
> param
(
'state'
);
if
(
!
$code
)
{
print
"\r\n<b>Failed to retrieve the authorization code.<b>"
;
}
elsif
(
$state
ne
$
main::
state
)
{
# Confirm that the state in the response matches the state token used to
# generate the authorization URL.
print
"\r\n<b>State in the callback does not match the expected value.<b>"
;
}
else
{
my
$auth_handler
=
$self
-
> {
auth_handler
};
$auth_handler
-
> issue_access_token
(
$code
);
# After the access token and refresh token are generated, you should store the
# refresh token and reuse it for future calls, by either changing your
# googleads.properties file or setting in the authorization handler as follows:
#
# $api_client->get_oauth2_handler()->set_client_id($client_id);
# $api_client->get_oauth2_handler()->set_client_secret($client_secret);
# $api_client->get_oauth2_handler()->set_refresh_token($refresh_token);
print
"\r\n<b>Authorization code was successfully retrieved.</b>"
;
print
"<p><b>Replace the following keys and values in your "
.
"googleads.properties configuration file:</b><p>"
;
printf
(
"clientId=%s<br>clientSecret=%s<br>refreshToken=%s<br>"
,
$auth_handler
-
> get_client_id
,
$auth_handler
-
> get_client_secret
,
$auth_handler
-
> get_refresh_token
);
print
STDERR
"Press Ctrl+C to quit.\n"
;
}
}
}
# Don't run the example if the file is being included.
if
(
abs_path
(
$0
)
ne
abs_path
(
__FILE__
))
{
return
1
;
}
# Get Google Ads Client with the default API version.
my
$api_client
=
Google::Ads::GoogleAds::
Client
-
> new
();
# Parameters passed on the command line will override any parameters set in code.
GetOptions
(
'client_id=s'
=
>
\
$client_id
,
'client_secret=s'
=
>
\
$client_secret
,
'additional_scopes=s'
=
>
\
$additional_scopes
);
# Print the help message if the parameters are not initialized in the code nor
# in the command line.
pod2usage
(
2
)
if
not
check_params
(
$client_id
,
$client_secret
);
# Call the example.
generate_user_credentials
(
$api_client
,
$client_id
,
$client_secret
,
$additional_scopes
);
=pod
=head1 NAME
generate_user_credentials
=head1 DESCRIPTION
This example will create an OAuth2 refresh token for the Google Ads API for either a web
or desktop app OAuth client ID.
For web app client types, you must add B<http://127.0.0.1> to the "Authorize redirect URIs"
list in your L<Google Cloud Console project|https://console.developers.google.com/apis/credentials>
before running this example, where PORT defaults to 8080. Desktop app client types do not
require the local redirect to be explicitly configured in the Cloud console.
=head1 SYNOPSIS
generate_user_credentials.pl [options]
-help Show the help message.
-client_id The OAuth2 client id.
-client_secret The OAuth2 client secret
-additional_scopes [optional] Additional OAuth2 scopes seperated by comma.
=cut
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License
, and code samples are licensed under the Apache 2.0 License
. For details, see the Google Developers Site Policies
. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-09-03 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-03 UTC."],[[["\u003cp\u003eThe code samples demonstrate how to generate OAuth2 refresh tokens for accessing the Google Ads API using various programming languages (Java, C#, PHP, Python, Ruby, Perl).\u003c/p\u003e\n"],["\u003cp\u003eRefresh tokens enable long-lived access to Google Ads accounts without repeated user logins, streamlining application integration.\u003c/p\u003e\n"],["\u003cp\u003eUsers need to provide their OAuth2 client ID and secret, obtained from the Google Cloud Console, to initiate the authorization process.\u003c/p\u003e\n"],["\u003cp\u003eWeb applications require configuring authorized redirect URIs in the Google Cloud Console for the authorization flow to function correctly.\u003c/p\u003e\n"],["\u003cp\u003eSecure storage and handling of client secrets and refresh tokens are crucial for protecting Google Ads account access.\u003c/p\u003e\n"]]],[],null,[]]