I want to use Google Ads API with service account I managed to create a session using this Java code configuration:
ClassLoader classLoader = this.getClass().getClassLoader();
File configFile = new File(classLoader.getResource("ads.properties").getFile());
GoogleAdsClient googleAdsClient = GoogleAdsClient.newBuilder()
.fromEnvironment()
.fromPropertiesFile(configFile)
.build();
GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient();
I want to use this connection to make a request using this code:
AdWordsSession session = null;
try {
// Generate a refreshable OAuth2 credential.
Credential oAuth2Credential = new OfflineCredentials.Builder()
.forApi(Api.ADWORDS)
.fromFile()
.build()
.generateCredential();
// Construct an AdWordsSession.
session =
new AdWordsSession.Builder().fromFile().build();
} catch (ConfigurationLoadException cle) {
System.err.printf(
"Failed to load configuration from the %s file. Exception: %s%n",
DEFAULT_CONFIGURATION_FILENAME, cle);
return;
} catch (ValidationException ve) {
System.err.printf(
"Invalid configuration in the %s file. Exception: %s%n",
DEFAULT_CONFIGURATION_FILENAME, ve);
return;
} catch (OAuthException oe) {
System.err.printf(
"Failed to create OAuth credentials. Check OAuth settings in the %s file. "
+ "Exception: %s%n",
DEFAULT_CONFIGURATION_FILENAME, oe);
return;
}
AdWordsServicesInterface adWordsServices = AdWordsServices.getInstance();
try {
runExample(adWordsServices, session);
} catch (ApiException apiException) {
System.err.println("Request failed due to ApiException. Underlying ApiErrors:");
if (apiException.getErrors() != null) {
int i = 0;
for (ApiError apiError : apiException.getErrors()) {
System.err.printf(" Error %d: %s%n", i++, apiError);
}
}
} catch (RemoteException re) {
System.err.printf(
"Request failed unexpectedly due to RemoteException: %s%n", re);
}
AdWordsServicesInterface adWordsServices, AdWordsSession session) throws RemoteException {
// Get the TrafficEstimatorService.
TrafficEstimatorServiceInterface trafficEstimatorService =
adWordsServices.get(session, TrafficEstimatorServiceInterface.class);
Full source: https://developers.google.com/adwords/api/docs/samples/java/basic-operations
Do you know how I can use service account into the above code?
It looks like Adwords does support service account Authentication
OAuth2 service accounts
The AdWords API allows service account access through G Suite domains.
Which means you need to have your Gsuite domain admin authorize your service account to access it.
The Code should look something like this to authorize a service account
/**
* Initializes an adwords service object.
*
* #return An authorized adwords service object.
* #throws IOException
* #throws GeneralSecurityException
*/
private static AdWordsServices initializeAdWords() throws GeneralSecurityException, IOException {
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = GoogleCredential
.fromStream(new FileInputStream(KEY_FILE_LOCATION))
.createScoped(AdwordsScopes.all());
// Construct the Analytics Reporting service object.
return new AdWordsServices.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME).build();
}
Related
I'm developing application that provides access to gmail mailbox. I created new project and logged in with few email accounts. When I revoked access token through this endpoint: https://oauth2.googleapis.com/revoke, the number of accounts attached to my project didn't change.
When i try to select account again, google redirects me to uri I specified, but code within url is corrupted and I can't get new access token using code from this url.
Response i get using code from url:
{
"error": "invalid_grant",
"error_description": "Malformed auth code."
}
How can i completely log out from my app?
Credential authorize=getCredentials(gmailMailBox, emailProperties.getGoogleClientSecrets());
authorize.refreshToken();
Unirest.post(emailProperties.getRevokeTokenUrl(authorize.getAccessToken()));
getCredentials method:
Credential authorize = new GoogleCredential.Builder()
.setTransport(GoogleNetHttpTransport.newTrustedTransport())
.setJsonFactory(JacksonFactory.getDefaultInstance())
.setClientSecrets(clientSecrets)
.build()
.setAccessToken(gmailMailBox.getAccessToken())
.setRefreshToken(gmailMailBox.getRefreshToken());
private Credential getCredentials(GmailMailBox gmailMailBox, GoogleClientSecrets clientSecrets)
throws GeneralSecurityException, IOException {
return new GoogleCredential.Builder().setTransport(GoogleNetHttpTransport.newTrustedTransport())
.setJsonFactory(JacksonFactory.getDefaultInstance())
.setClientSecrets(clientSecrets)
.build()
.setAccessToken(gmailMailBox.getAccessToken())
.setRefreshToken(gmailMailBox.getRefreshToken());
}
public class GmailMailBox {
private String accessToken;
private String refreshToken;
private LocalDateTime expiresIn;
}
public GoogleClientSecrets getGoogleClientSecrets() {
GoogleClientSecrets clientSecrets = new GoogleClientSecrets();
GoogleClientSecrets.Details clientSecretsDetails = new GoogleClientSecrets.Details();
clientSecretsDetails.set("client_id", client_id);
clientSecretsDetails.set("project_id", project_id);
clientSecretsDetails.set("auth_uri", auth_uri);
clientSecretsDetails.set("token_uri", token_uri);
clientSecretsDetails.set("auth_provider_x509_cert_url", auth_provider_x509_cert_url);
clientSecretsDetails.set("client_secret", client_secret);
clientSecrets.setWeb(clientSecretsDetails);
return clientSecrets;
}
For instance I can authenticate through graph api by getaccesstokencredentials(username, password)
Can I use this token to access Azure?
Current we can use usertokencredentials and applicationtokencredentials from management library then once done you can create instance of azure class.
Azure azure = Azure.authenticate(credentials).withdefaultsubscription.
I'm wondering if we can use the token from getaccesstokencredentials instead of usertokentcredentials and applicationtokencredentials
We cannot use the the same access token to call graph api and call api to manage Azure resource. Because the resource url for graph api ishttps://graph.microsoft.com/ but the resource url for Azure management rest api is https://management.azure.com/. For more details, please refer to https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-api-authentication.
Besides, regarding how to use Azure AD to access Azure storage, please refer to the following steps:
Add role assignment to your principal.
Get token.
public static String getToken() throws Exception {
String TENANT_ID = "your tenant id or name, e4c9*-*-*-*-*57fb";
String AUTHORITY = "https://login.microsoftonline.com/" + TENANT_ID;
String CLIENT_ID = "your application id, dc17*-*-*-*a5e7";
String CLIENT_SECRET = "the secret, /pG*32";
String RESOURCE = "https://storage.azure.com/";
String ACCESS_TOKEN = null;
ExecutorService service = Executors.newFixedThreadPool(1);
AuthenticationContext context = null;
try {
context = new AuthenticationContext(AUTHORITY, false, service);
ClientCredential credential = new ClientCredential(CLIENT_ID, CLIENT_SECRET);
Future<AuthenticationResult> future = context.acquireToken(RESOURCE, credential, null);
ACCESS_TOKEN = future.get().getAccessToken();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} finally {
service.shutdown();
}
return ACCESS_TOKEN;
}
Access blob.
public static void main(String[] args) throws Exception {
String token = getToken();
StorageCredentialsToken credentialsToken = new StorageCredentialsToken("storagetest789", token);
CloudBlobClient blobClient = new CloudBlobClient(new URI("https://storagetest789.blob.core.windows.net/"), credentialsToken);
CloudBlobContainer blobContainer = blobClient.getContainerReference("pub");
CloudBlockBlob blockBlob = blobContainer.getBlockBlobReference("test1.txt");
blockBlob.uploadText("mytest");
}
For more details, please refer to https://learn.microsoft.com/en-us/azure/storage/common/storage-auth-aad.
I want to delete user from google Directory API. I received error while deleting
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden "Not Authorized to access this resource/api".
However my code works fine while insert user. I have super admin accounts and I'm using same directory instance for inserting and deleting user. It does work when I'm trying to delete the user.
Please help me out. Thanks in advance.
public class UserDisable {
private static final Logger LOGGER = Logger.getLogger(EmployeeAPI.class);
/** Application name. */
private static final String APPLICATION_NAME = "User Account Creation";
/** Directory to store user credentials for this application. */
private static final java.io.File DATA_STORE_DIR = new java.io.File(
System.getProperty("user.home"),
".credentials/admin-directory_v1-java-quickstart");
/** Global instance of the {#link FileDataStoreFactory}. */
private static FileDataStoreFactory DATA_STORE_FACTORY;
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = JacksonFactory
.getDefaultInstance();
/** Global instance of the HTTP transport. */
private static HttpTransport HTTP_TRANSPORT;
private static final Random randomGenerator = new Random();
static Directory directoryClient = null;
private static final List<String> SCOPES = Arrays.asList(
DirectoryScopes.ADMIN_DIRECTORY_USER, DirectoryScopes.ADMIN_DIRECTORY_GROUP);
static {
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
} catch (Throwable t) {
System.exit(1);
}
}
/**
* Creates an authorized Credential object.
*
* #return an authorized Credential object.
* #throws IOException
*/
public static Credential authorize() throws IOException {
// Load client secrets.
InputStream in = UserDisable.class
.getResourceAsStream("/client_secret.json");
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
JSON_FACTORY, new InputStreamReader(in));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline").build();
Credential credential = new AuthorizationCodeInstalledApp(flow,
new LocalServerReceiver()).authorize("user");
LOGGER.info("Credentials saved to "
+ DATA_STORE_DIR.getAbsolutePath());
return credential;
}
/**
* Build and return an authorized Admin SDK Directory client service.
*
* #return an authorized Directory client service
* #throws IOException
*/
public static Directory getDirectoryService() throws IOException {
Credential credential = authorize();
return new Directory.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME).build();
}
public static void demo(){
try {
directoryClient = getDirectoryService();
removeUser(directoryClient, "Anderson.Paul2#abc.com");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* removeGroup removes a group from Google.
* #param directoryClient a Directory (service) object
* #param userKey an identifier for a user (e-mail address is the most popular)
* #throws IOException
*/
public static void removeUser(Directory directoryClient, String userKey) throws IOException {
LOGGER.info("removeUser() - {}"+ userKey);
try {
directoryClient.users().delete(userKey).execute();
} catch (IOException e) {
LOGGER.info("An unknown error occurred: " + e);
}
}
}
Here is error that i have received:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Not Authorized to access this resource/api",
"reason" : "forbidden"
}
],
"message" : "Not Authorized to access this resource/api"
}
I try to access a google endpoint service from a native application with OAuth 2.0. I managed to authenticate with GoogleAuthorizationCodeFlow and the JavaFX webview (as browser).
After a successfull authentication I try to access the api method but the User object is always null and the question is why?
Code for api method call:
GoogleAuthorizationCodeFlow flow = getGoogleAuthorizationCodeFlow();
Credential credential = flow.loadCredential(USER_ID);
Helloworld.Builder builder = new Helloworld.Builder(new NetHttpTransport(),
new JacksonFactory(), credential);
Helloworld service = builder.build();
Helloworld.Greetings.Authed protectedApiMethod = service.
greetings().authed();
HelloGreeting execute = protectedApiMethod.execute();
System.out.println("Response " + execute.getMessage());
Code for creating the flow object:
private static GoogleAuthorizationCodeFlow getGoogleAuthorizationCodeFlow() {
return new GoogleAuthorizationCodeFlow(new NetHttpTransport(),
new JacksonFactory(), INSTALLED_ID, CLIENT_SECRET, Arrays.asList(SCOPE_EMAIL));
}
Code where I try to authenticate:
GoogleAuthorizationCodeFlow flow = getGoogleAuthorizationCodeFlow();
GoogleAuthorizationCodeTokenRequest tokenRequest = flow.newTokenRequest(code);
tokenRequest.setRedirectUri(REDIRECT_URL);
try {
GoogleTokenResponse execute = tokenRequest.execute();
flow.createAndStoreCredential(execute, USER_ID);
Platform.exit();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Declaration of the Api method:
#ApiMethod(name = "greetings.authed",
path = "greeting/authed",
clientIds = {Constants.WEB_CLIENT_ID, Constants.INSTALLED_ID,
Constants.API_EXPLORER_CLIENT_ID})
public HelloGreeting authedGreeting(User user) {
if (user != null) {
HelloGreeting response = new HelloGreeting("hello " + user.getEmail());
return response;
} else {
HelloGreeting response = new HelloGreeting("no user object was specified");
return response;
}
}
The only response I get is "no user object was specified". Since I can call the method without any error I guess I'm authenticated correctly.
From the docs: https://developers.google.com/appengine/docs/java/endpoints/getstarted/backend/auth
If the request coming in from the client has a valid auth token or is
in the list of authorized clientIDs, the backend framework supplies a
valid User to the parameter. If the incoming request does not have a
valid auth token or if the client is not on the clientIDs whitelist,
the framework sets User to null
So, you have to manully catch the case, where a null user is supplied by the infrastructure. So to answer the above question: The request is invalid. And the mistake in the code is, that the CodeFlow object is recreated for the actual request but since no CredentialStore is set, the token is lost and cannot be resend.
I am trying to access Adsense Management API using java google-api. However, I having troubles with oauth2 authentication. According with the doc the following code should be enough:
public static GoogleCredential getCredential()
throws GeneralSecurityException, IOException {
File file = new File("key.p12");
return new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT).setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_ID)
.setServiceAccountScopes(AdSenseScopes.ADSENSE)
.setServiceAccountPrivateKeyFromP12File(file)
.setServiceAccountUser(ACCOUNT_USER)
.build();
}
However, credential always returning accessToken null and I can't do any operation. I am getting a bad request:
Exception in thread "main" java.lang.RuntimeException: com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "invalid_grant"
}
My client code:
private static AdSense initializeAdsense() throws Exception {
// Authorization.
Credential credential = getCredential();
String token = credential.getAccessToken();
System.out.println(token);
AdSense adsense = new AdSense.Builder(new NetHttpTransport(), JSON_FACTORY, credential).setApplicationName("Google-AdSenseSample/1.2").build();
return adsense;
}
public static Accounts run(AdSense adsense, int maxPageSize) throws Exception {
System.out.println("=================================================================");
System.out.println("Listing all AdSense accounts");
System.out.println("=================================================================");
// Retrieve account list in pages and display data as we receive it.
String pageToken = null;
Accounts accounts = null;
do {
accounts = adsense.accounts().list().setMaxResults(maxPageSize).setPageToken(pageToken).execute();
if ((accounts.getItems() != null) && !accounts.getItems().isEmpty()) {
for (Account account : accounts.getItems()) {
System.out.printf("Account with ID \"%s\" and name \"%s\" was found.\n", account.getId(), account.getName());
}
} else {
System.out.println("No accounts found.");
}
pageToken = accounts.getNextPageToken();
} while (pageToken != null);
System.out.println();
return accounts;
}
public static void test() throws Exception {
AdSense adsense = initializeAdsense();
run(adsense, 30);
}
The question is, after all, what is wrong?
Edited:
Maybe I just cannot do that.
I'm afraid that accessing the AdSense Management API via service account authentication is not supported, since it's protected user information
https://groups.google.com/forum/#!msg/adsense-api/j-gQsp_fE94/CrOPhRLv4WUJ
SERVICE_ACCOUNT_ID should be email address of your service account (xxxxxx#developer.gserviceaccount.com) and do not set the ACCOUNT_USER.