I am attempting to use the Directory API to update Google passwords for users in our domain. I've followed the example for the Plus service account, which is almost identical (https://github.com/google/google-api-java-client-samples/blob/master/plus-serviceaccount-cmdline-sample/src/main/java/com/google/api/services/samples/plus/serviceaccount/cmdline/PlusServiceAccountSample.java).
I'm trying to determine why I am required to pass in the email address of a super admin user to the setServiceAccountUser() in order to set user passwords on the domain. Is there a setting somewhere that will let me use the API without settings the serviceAccountUser?
I receive the message below when I comment out the setServiceAccountUser() call:
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Not Authorized to access this resource/api",
"reason" : "forbidden"
} ],
"message" : "Not Authorized to access this resource/api"
Here is the code (from the Plus sample) that is relevant:
// service account credential (uncomment setServiceAccountUser for domain-wide delegation)
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton(PlusScopes.PLUS_ME))
.setServiceAccountPrivateKeyFromP12File(new File("key.p12"))
// .setServiceAccountUser("user#example.com")
.build();
Directory API write operations require an admin account. Either a super admin or a delegated admin who has rights to perform API user modifications. This is listed in the prerequisites document.
Related
I created a service account and generated a json key. I want to execute a get request to get a project.
I using https://cloud.google.com/dns/docs/reference/v1/projects/get
public static Dns createDnsService() throws IOException, GeneralSecurityException {
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
String jsonPath = "testdns-320312-136950c1074b.json";
FileInputStream stream = new FileInputStream(jsonPath);
GoogleCredential credential = GoogleCredential.fromStream(stream);
if (credential.createScopedRequired()) {
credential =credential.createScoped(Arrays.asList("https://www.googleapis.com/auth/cloud-platform"));
}
return new Dns.Builder(httpTransport, jsonFactory, credential)
.setApplicationName("Google-DnsSample/0.1")
.build();
}
When executing the code, I get error:
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
GET https://dns.googleapis.com/dns/v1/projects/testdns-320312
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Forbidden",
"reason" : "forbidden"
} ],
"message" : "Forbidden"
}
#John Hanley is right - you lack proper permissions.
If you didn't assign any role to a service account after you created it you can't use it to do anything.
You need a roles/dns.admin role to be able to administer all the DNS records in your project.
You can do this with the following steps:
In the Google Cloud Console, go to the IAM page.
Go to the IAM page
Select your project from the top pull-down menu.
Click Add.
In New members, enter the email address of a new member.
Select the desired role from the drop-down menu.
Click Save.
Verify that the member is listed with the role that you granted.
Granting DNS admin role to this account will be the easiest way of getting control over Cloud DNS section of your project. If you need more fine-grained / limited access then you can create your custom role and assign it to this account instead of the basic one.
Here's more info about granting roles in GCP that you may find useful.
Very similar question was also answered here.
I am trying to get the Delegates for a mailbox using Gmail API.
My application is running on Google App-engine and has the feature of Add, Remove,Get Delegates using Email Setting API.
Now I am planning to migrate these features to Gmail API since Email setting API will be deprecated.
Technology wise I am using Java language.
I have followed all the steps provided by Gmail API documentation. Authentication to Gmail API is successful. But When I am trying to get the delegates it's giving following error-
404 Not Found
{
"code" : 404,
"errors" : [ {
"domain" : "global",
"message" : "Invalid delegate",
"reason" : "notFound"
} ],
"message" : "Invalid delegate"
}
And inside console below is the error -
*com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found
{
"code" : 404,
"errors" : [ {
"domain" : "global",
"message" : "Invalid delegate",
"reason" : "notFound"
} ],
"message" : "Invalid delegate"
}
at
com.google.api.client.googleapis.json.GoogleJsonResponseException.fro
m(GoogleJsonResponseException.java:150)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClie
ntRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClie
ntRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest
$1.interceptResponse(AbstractGoogleClientRequest.java:321)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1067)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest
.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest
.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest
.execute(AbstractGoogleClientRequest.java:469)
at com.aeegle.services.GmailService.retrieveEmailDelegates(GmailService.
java:106)
at com.aeegle.DAOImpl.EmailDAOImpl.getDelegatesGmail(EmailDAOImpl.java:1
43)
at controllers.DelegateController.getListDelegatesGmail(DelegateControll
er.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:557)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:508)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:484)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:479)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:161)
at play.server.PlayHandler$NettyInvocation.execute(PlayHandler.java:255)
at play.Invoker$Invocation.run(Invoker.java:278)
at play.server.PlayHandler$NettyInvocation.run(PlayHandler.java:233)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:51
1)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.
access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.
run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.
java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor
.java:624)
at java.lang.Thread.run(Thread.java:748)*
You can observe GmailService line number 106 have an issue. Now I am going to Post my java code.
1: - Authentication Code -
public Gmail getGmailService(String email) throws Exception {
System.out.println("-------------getGmailService");
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
Collection<String> SCOPES = new ArrayList<String>();
SCOPES.add(GmailScopes.GMAIL_SETTINGS_BASIC);
SCOPES.add(GmailScopes.MAIL_GOOGLE_COM);
SCOPES.add(GmailScopes.GMAIL_MODIFY);
SCOPES.add(GmailScopes.GMAIL_READONLY);
GoogleCredential credential;
// To load classpath resources.
ClassLoader classLoader = getClass().getClassLoader();
new File(SERVICE_ACCOUNT_PKCS12_FILE_PATH);
credential = new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL).setServiceAccountUser(email).setServiceAccountScopes(SCOPES)
.setServiceAccountPrivateKeyFromP12File(new File(SERVICE_ACCOUNT_PKCS12_FILE_PATH)).build();
System.out.println("----calling Builder");
service = new Gmail.Builder(httpTransport, jsonFactory, null).setHttpRequestInitializer(credential)
.setApplicationName(APPLICATION_NAME).build();
return service;
}
2:- Next trying to get the Delegates for the mailbox using service object-
public Delegate retrieveEmailDelegates(String user, Gmail service) throws Exception {
if (isBlankOrNullString(user)) {
throw new IllegalArgumentException();
}
Delegate delegatesResponse=null;
try {
System.out.println("Call retrieveEmailDelegates for "+user);
delegatesResponse = service.users().settings().delegates().get(user, "me").execute();
System.out.println("-------service" + delegatesResponse.getDelegateEmail());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return delegatesResponse;
}
Please help me on this since I am still running this in my localhost machine.
If you want to access other users email account, you must turn on mail delagation that allows the delegate to read, send, and delete on their behalf:
Sign in to your Google Admin console.
Note: Sign in using your administrator account (does not end in
#gmail.com).
From the Admin console Home page, go to Apps>Gsuite>Gmail> User Setting.
Next to Mail delegation, select Let users delegate access to their mailbox to other users in the domain.
(Optional) Select each organization containing users you want to enable mail delegation for and check the Mail Delegation box.
Click Save.
Once enabled, any user who wants to assign a delegate to access their email must set up on mail delegation in their Gmail account.
Disclaimer: I work on Gmail and the Gmail API platform.
Looks like you're trying to get a list of all delegates for an account, so you must use service.users().settings().delegates().list() instead of service.users().settings().delegates().get().
Note that this will require further changes to your code, to deal with the returned ListDelegatesResponse.
As an aside, you are receiving the "Invalid delegate" error because service.users().settings().delegates().get(user, "me") is supplying me as the email of the delegate you are attempting to retrieve. You'd need to supply a valid email address for the request to possibly succeed. However, I realize this is all likely due to your mistaken use of the Get delegate method instead of the List delegates method.
I have an application set up to access the Google Classroom API. I have it authorized and can pull Course and Roster data. It's updated to use the V1 calls, but when I add in the Profile.Name and Profile.Email scopes, I get the following error:
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Unregistered request was blocked. Please sign up using Google Developers Console.",
"reason" : "forbidden"
} ],
"message" : "Unregistered request was blocked. Please sign up using Google Developers Console.",
"status" : "PERMISSION_DENIED"
}
The service account has been authorized in the admin console with all 4 relevant Classroom scopes. The Domain has also been confirmed as having the Classroom APIs enabled, if I attempt to use them through the OAuth playground it all works fine.
Any ideas as to why I'm getting the error only when I add in the profile scopes?
The issue was that we were required to fill in a second form for Google to authorize the domain, we'd only found the first one. After filling in the new form, it all started working.
I am trying to read gmail messages using GAE Service account. The code similar to below works well to read Google calendar but fails for gmail. I have only one user in the domain (who is also the admin account). I am trying to access the gmail of that user). Any help on why my code fails would be great.
I have delegated domain wide authority for the following scopes.
Email (Read/Write/Send) https://mail.google.com/
https://www.googleapis.com/auth/admin.directory.user.readonly
Calendar (Read-Write) https://www.googleapis.com/auth/calendar
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/userinfo.profile
I have enabled below APIs in the Google App Engine:
Admin SDK
Calendar API
Drive API
Gmail API
Google Cloud SQL
Google Cloud Storage
Google Cloud Storage JSON API
Below is the code that creates gmail service:
// Create HTTP transport
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
// Create JsonFactory using com.google.api.client.json.jackson2.JacksonFactory
JsonFactory jsonFactory = new JacksonFactory();
// Get service accont (contain service account email and P12 file name)
BaseGoogleService.GoogleServiceAccount serviceAccount = getGoogleServiceAccount();
//load private key from class path to File object.
Resource resource = appContext.getResource("classpath:"+serviceAccount.getServiceAccountPrivateKeyFile());
File privateKeyFile = resource.getFile();
// Create Google credential for service account
List<String> accountScopes = new ArrayList<String>();
accountScopes.add(GmailScopes.MAIL_GOOGLE_COM);
Credential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(serviceAccount.getServiceAccountId())
.setServiceAccountScopes(accountScopes)
.setServiceAccountPrivateKeyFromP12File(privateKeyFile)
.build();
// Create Gmail client
Gmail gmailClient = new Gmail.Builder(httpTransport, jsonFactory, credential)
.build();
Code that reads gmail messages:
ListMessagesResponse response = gmailClient.users().messages().list(userEmail).setQ(query).execute()
I am getting below error when I execute this code
com.google.api.client.googleapis.json.GoogleJsonResponseException: 500 OK
{
"code" : 500,
"errors" : [ {
"domain" : "global",
"message" : "Backend Error",
"reason" : "backendError"
} ],
"message" : "Backend Error"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:312)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1049)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
I was able to make it work.
Two things:
Have to add ".setServiceAccountUser(userEmail)" while building GoogleCredential. userEmail represents the email id to impersonate.
This cannot be done for admin account. I had to add a user to the domain and access that user's gmail.
Using google-api-java-client at this page we can read about some flows.
The service accounts flow works fine with calendar api:
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("[[]]")
.setServiceAccountScopes(CalendarScopes.CALENDAR)
.setServiceAccountPrivateKeyFromP12File(new File("key.p12")).build();
But we have always:
503 Service Unavailable
{
"code" : 503,
"errors" : [ {
"domain" : "global",
"message" : "Backend Error",
"reason" : "backendError"
} ],
"message" : "Backend Error"
}
if we use GroupssettingsScopes.APPS_GROUPS_SETTINGS (the api console grant access for this requests).
We have to use a mechanism near at the old 2 legged OAuth 1.0a for manage the groups of a GApps account.
Many thanks in advance
With the Groups Settings API, you will need to impersonate a Google Apps user. And that user needs to be an admin.
In addition, I personnally noticed that it is better to provide the service account id to the setServiceAccountId()method.
Here's what works for me :
GoogleCredential credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport())
.setJsonFactory(new GsonFactory())
.setServiceAccountId("516444413363-4i0cvva2abc8a3t63bbq1a9rfqe42p70#developer.gserviceaccount.com")
.setServiceAccountScopes(Collections.singletonList("https://www.googleapis.com/auth/apps.groups.settings"))
.setServiceAccountUser("admin#my.doma.in")
.setServiceAccountPrivateKeyFromP12File(new File("key.p12")).build();