A refresh token is required for so called OfflineCredentials. These are credentials, that can be used by applications, which are not running in a browser (e.g. desktop applications or some batch processing without UI) and therefore cannot perform an OAuth2 flow.
Please have a look at Using OAuth 2.0 to Access Google APIs
- Refresh the access token, if necessary.
Access tokens have limited lifetimes. If your application needs access to a Google API beyond the lifetime of a single access token, it can obtain a refresh token. A refresh token allows your application to obtain new access tokens.
Note: Save refresh tokens in secure long-term storage and continue to use them as long as they remain valid. Limits apply to the number of refresh tokens that are issued per client-user combination, and per user across all clients, and these limits are different. If your application requests enough refresh tokens to go over one of the limits, older refresh tokens stop working.
Some more information to Offline Access!
In Java, it will look like this:
import com.google.api.ads.common.lib.auth.OfflineCredentials;
import com.google.api.ads.common.lib.auth.OfflineCredentials.Api;
import com.google.api.ads.common.lib.auth.OfflineCredentials.ForApiBuilder;
import com.google.api.ads.common.lib.exception.OAuthException;
import com.google.api.ads.common.lib.exception.ValidationException;
import com.google.api.client.auth.oauth2.Credential;
// ...
// Generate offline credentials
// With a previously created OAuth2 refresh token (see API examples)
ForApiBuilder forApiBuilder = new OfflineCredentials.Builder().forApi(Api.ADWORDS);
forApiBuilder.withClientSecrets(clientId, clientSecret);
forApiBuilder.withRefreshToken(refreshToken);
Credential credential = null;
try {
credential = forApiBuilder.build().generateCredential();
} catch (OAuthException e) {
throw new Exception("The given credential could not be refreshed: " + e.getMessage());
} catch (ValidationException e) {
throw new Exception("Client ID, client secret or refresh token are not valid: " + e.getMessage());
}
// Build session
// ...
The refresh token need to be passed to the credential builder in addition to the client ID and the client secret. With the valid OfflineCredentials you are now able to build a new session for a specific Google API.
Regarding your third question: See the accepted answer of following question
Here the source code, which shows how to obtain a refresh token for Google AdWords (see scope) once via commandline. The client ID and the client secret must be passed as commandline arguments.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.PropertiesConfiguration;
import com.google.api.ads.common.lib.auth.GoogleClientSecretsBuilder;
import com.google.api.ads.common.lib.auth.GoogleClientSecretsBuilder.Api;
import com.google.api.ads.common.lib.auth.GoogleClientSecretsBuilder.GoogleClientSecretsForApiBuilder;
import com.google.api.ads.common.lib.exception.ValidationException;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.common.collect.Lists;
// ...
private static final String SCOPE = "https://adwords.google.com/api/adwords";
// This callback URL will allow you to copy the token from the success screen
private static final String CALLBACK_URL = "urn:ietf:wg:oauth:2.0:oob";
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.err.println("Please provide client ID and secret as commandline arguments!");
System.err.println("If you do not have a client ID or secret, please create one in the API console: https://code.google.com/apis/console#access");
System.exit(1);
}
GoogleClientSecrets clientSecrets = null;
try {
Configuration configuration = new PropertiesConfiguration();
configuration.setProperty("api.adwords.clientId", args[0]);
configuration.setProperty("api.adwords.clientSecret", args[1]);
GoogleClientSecretsForApiBuilder googleClientSecretsForApiBuilder = new GoogleClientSecretsBuilder().forApi(Api.ADWORDS);
googleClientSecretsForApiBuilder.from(configuration);
clientSecrets = googleClientSecretsForApiBuilder.build();
} catch (ValidationException e) {
System.err.println("Invalid client ID or secret!");
System.exit(1);
}
// Get the OAuth2 credential
Credential credential = getOAuth2Credential(clientSecrets);
System.out.printf("Your refresh token is: %s\n", credential.getRefreshToken());
}
}
private static Credential getOAuth2Credential(GoogleClientSecrets clientSecrets) throws Exception {
/*
* Set the access type to offline so that the token can be refreshed. By
* default, the library will automatically refresh tokens when it can, but
* this can be turned off by setting api.adwords.refreshOAuth2Token=false
*/
GoogleAuthorizationCodeFlow authorizationFlow = new GoogleAuthorizationCodeFlow.Builder(new NetHttpTransport(), new JacksonFactory(), clientSecrets, Lists.newArrayList(SCOPE)).setAccessType("offline").build();
String authorizeUrl = authorizationFlow.newAuthorizationUrl().setRedirectUri(CALLBACK_URL).build();
System.out.println("Paste this url in your browser: \n" + authorizeUrl + '\n');
// Wait for the authorization code
System.out.println("Type the code you received here: ");
String authorizationCode = new BufferedReader(new InputStreamReader(System.in)).readLine();
// Authorize the OAuth2 token
GoogleAuthorizationCodeTokenRequest tokenRequest = authorizationFlow.newTokenRequest(authorizationCode);
tokenRequest.setRedirectUri(CALLBACK_URL);
GoogleTokenResponse tokenResponse = tokenRequest.execute();
// Create the OAuth2 credential
GoogleCredential credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport()).setJsonFactory(new JacksonFactory()).setClientSecrets(clientSecrets).build();
// Set authorized credentials
credential.setFromTokenResponse(tokenResponse);
return credential;
}
The code is originally from a Goolge AdWords API example. My version is not reading from a configuration file, because I didn't want to store the client ID and secret in some resource file (which I forgot to remove later on). That's why the values are passed as arguments to the program.