Вопрос

How can I authenticate programmatically to Google? Now that ClientLogin (https://developers.google.com/accounts/docs/AuthForInstalledApps) is deprecated, how can we perform a programmatic authentication to Google with OAuth2?

With ClientLogin we could perform a post to https://www.google.com/accounts/ClientLogin with email and password parameters and obtain the authentication token.

With OAuth2 i can't find a solution!

#

My app is a java background process. I saw, following this link: developers.google.com/accounts/docs/OAuth2InstalledApp#refresh, how to obtain a new access token using a refreshed token.

The problem is that I can't find a java example about how to instantiate an Analytics object (for example) to perform a query when I have a new valid access token

This is my code that returns a 401 Invalid credentials when invoke the "execute()":

public class Test {

static final String client_id = "MY_CLIENT_ID";
static final String client_secret = "MY_SECRET";
static final String appName = "MY_APP";

private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();

static String access_token = "xxxx";
static String refreshToken = "yyyyy";

public static void main (String args[]){

    try {

        GoogleCredential credential = 
            new GoogleCredential.Builder()
                .setTransport(HTTP_TRANSPORT)
                .setJsonFactory(JSON_FACTORY)
                .setClientSecrets(client_id, client_secret).build();
        credential.setAccessToken(access_token);
        credential.setRefreshToken(refreshToken);
        //GoogleCredential
        Analytics analytics = Analytics.builder(HTTP_TRANSPORT, JSON_FACTORY)
            .setApplicationName(appName)
            .setHttpRequestInitializer(credential)
            .build();

        Accounts accounts = analytics.management().accounts().list().execute();
    } catch (Exception e) {
        e.printStackTrace();
    } 
}

What is the problem?

Это было полезно?

Решение

Check the OAuth 2 flow for Installed Application:

https://developers.google.com/accounts/docs/OAuth2InstalledApp

It still requires the user to authenticate with a browser the first time, but then you can store the refresh token and use it for subsequent requests.

For alternative solutions, check the Device flow or Service Accounts, they are explained in the same documentation set.

Другие советы

I found the Google Java client to be overly complex and poorly documented. Here's plain and simple Servlet example with Google Oauth2. For a background process you'll need to request access_type=offline. As others have mentioned you need the user to do a one time authorization. After that you can request refresh tokens as google tokens expire in an hour.

Although I appreciate that the OP was originally targeting the OAuth2InstalledApp approach, I would like to point out a working solution using the OAuth2WebServer approach. They don't differ significantly and this worked for me. I have found the google OAuth library to be pretty good as it will handle most of the OAuth dance for you and it makes it easy to refresh the access token. The solution below depends on using a pre-obtained refresh token.

As the accepted answer states, to get OAuth authentication working (even for a Java background process) where the request relies upon access to user data

requires the user to authenticate with a browser the first time, but then you can store the refresh token and use it for subsequent requests.

From previous comments by the OP I see the following

So I followed OAuth2 for Web Server Applications (here offline access is documented) but I have still problems.
1) I perform the first request via browser and I obtain autenticaton code for offline access
2) I perform a java post of the authentication code and obtain acces token and refresh token

The approach I used is more like

1) I perform the first request via a browser and obtain the refresh token for offline access
2) In java I provide the refresh token to the library and the library will obtain the access token etc

specifically, using the google-api-java-client library the code is quite straightforward and note that I haven't set an access token as the OP did, as I am calling credential.refreshToken(); elsewhere. (I check if I have a valid access token already and if not call refresh prior to the API call)

  private Credential generateCredentialWithUserApprovedToken() throws IOException,
      GeneralSecurityException {
    JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    InputStreamReader inputStreamReader =
        new InputStreamReader(jsonFileResourceForClient.getInputStream());
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(jsonFactory, inputStreamReader);
    return new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(jsonFactory)
        .setClientSecrets(clientSecrets).build().setRefreshToken(REFRESH_TOKEN);
  }

Note this covers step 2 of my approach, and the REFRESH_TOKEN mentioned in step 1 can be obtained as explained below.

First there is a prior set up of a web app creating an OAuth 2.0 client ID on the Google console for Credentials where you end up with a downloaded json file which will be read into the GoogleClientSecrets object.

i.e.

enter image description here

Make sure you add the Google playground callback uri into Authorized redirect URIs

enter image description here

Then you have your client id and the client secret ready for the playground and you can also download the json which you can pull into your Java code.

enter image description here

The REFRESH_TOKEN is obtained by sending a request to the google oauth playground with the following configuration. Note that prior to Step 1 and selecting your scope you should go to settings to check that you are providing you own credentials and add your client id and secret just below that

enter image description here

Note that the Access type is Offline, which corresponds to this.

There is also a nice explanation on grabbing the refresh token here https://www.youtube.com/watch?v=hfWe1gPCnzc

That is enough to get going and is a one time set up!

Regarding refresh tokens you should be aware of their lifecycle as discussed in the docs here

In the oauthplayground you will see this

enter image description here

but on point 4 of the docs here it says this

enter image description here

Hmmm.

Also for reference see How do I authorise an app (web or installed) without user intervention? (canonical ?)

For applications that authenticate on behalf of themselves (i.e., to another application, traditionally by signing into a role account using a shared password), the OAuth2 alternative to ClientLogin offered by Google is Service Accounts:

https://developers.google.com/accounts/docs/OAuth2ServiceAccount

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top