1

Currently I need to use the Gmail API to check the labels of newly arrived emails. It was perfect on my laptop, that I need to manually authorize for the first time starting the program(Java), and subsequent calls don't require user interactions.

This program is a quickstart sample code from Gmail API https://developers.google.com/gmail/api/quickstart/java

Now I need this program to run on the server so that I can monitor the landing status. After dozens of attempts, the server was unable to detect the tokens I uploaded from my laptop and kept asking me to open a redirecting url to authorize.

gmailLog.info("getCredentials start!");
InputStream in = GmailAPI.class.getResourceAsStream("/credentials.json");
if (in == null) {
   gmailLog.error("null input stream, credentials missing");
   throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
}
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
            .setDataStoreFactory(new FileDataStoreFactory(new File("tokens")))
            .setAccessType("offline")
            .build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");

The authorization happens on the last line of the code. Then a tokens folder is generated, please click this link to see the file structure.

As you can see, the tokens folder is placed under the root path. I copied the tokens folder to the server at the same location, but still I was asked to redirect. I wonder maybe this is because the StoredCredential file has my machine's information so it doesn't match the server machine.

Does this mean I can never do this on the server without user input? thank you. Also if a GSuite account is absolutely needed, I'm willing to pay and become an enterprise user.

  • 1
    Please edit your question and include your code, and the error message for the Oauth2 solution its probably a pathing issue. Service accounts will only work with gmail if you have a gsuite account and set up domain wide delegation to the domain account. – Linda Lawton - DaImTo Jan 19 '21 at 09:57
  • `Gmail APIs are not meant for service accounts` Not true, you can use service accounts in Gmail API. Even some methods can only be used with service account. Nevertheless, you'll have to provide more information on your current situation, including the code you're working on, in order to help people here to help you. – Iamblichus Jan 19 '21 at 10:56
  • @DaImTo Thanks for the reply, I've edited it, please take another look, really appreciate it. I don't have a gsuite account, do I need one in order to do what I'm trying to do? – Benjamin Li Jan 20 '21 at 03:18
  • @lamblichus can you take another look please? – Benjamin Li Jan 20 '21 at 03:24
  • You need to be a Workspace (formerly G Suite) domain admin in order to use a service account with domain-wide delegation. Since you don't have a Workspace account, therefore, I'm afraid you cannot avoid user interaction. If you're going to get a domain, though, I'd consider providing an answer. – Iamblichus Jan 20 '21 at 10:53
  • @lamblichus Thanks for answering with such detail. I solved it earlier this day after I printed out the working directory of the Java program and moved the /tokens folder to the right spot, the authentication worked without user input(as I did it already on my laptop)! – Benjamin Li Jan 20 '21 at 12:46
  • This will only work for the user for which the tokens were retrieved. Are you always gonna call this for the same user? – Iamblichus Jan 21 '21 at 11:00

1 Answers1

1

AuthorizationCodeInstalledApp is designed for installed applications. This is due to the fact that it opens the authorization window on the machine the code is running on.

Once the user authorizes the application FileDataStoreFactory stores the users credentials (refresh token for authorize("user")) on the machine and then will not need to authorize again as long as the refresh token still works as it can request a new access token or if you change "user" to some other user.

This will not work on a server as there is now way for the user to authorize the code unless they can see the authorization screen on their own machine. What you could do is just copy the credentials file over with the code so that it can find it and it should work the same as it does on your personal machine, but you should monitor it refresh tokens rarely expire but they can so you would need to authorize it again if it does stop working. If this library is created the same as the .net one is then tokens should be a directory some where on your machine with a file in it ending in "user".

web app

Now i am not a java dev but when you say running on a server if you mean as a web application (tbh im not even sure if you can do that with java) then you might need to check around in the library to see if its supported. I dont know this library as well as i know some of the other Google libraries but i think your looking for something like one of these here

You may also want to ask on the issue form if the library even supports it running on a server, remember you would probably need web browser credentials.

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • 2
    Thanks for answering with such detail. I solved it earlier this day after I printed out the working directory of the Java program and moved the /tokens folder to the right spot, the authentication worked without user input(as I did it already on my laptop)! – Benjamin Li Jan 20 '21 at 12:46
  • 1
    I voted this answer but my reputation is below 15 so it did not show... thanks again for your kindness! – Benjamin Li Jan 20 '21 at 12:48
  • if you accept the answer you will get points as well – Linda Lawton - DaImTo Jan 20 '21 at 16:02