How to Avoid redeeming Google Authorization Code every time - google-drive-api

public class image {
private String applicationName;
public image setApplicationName(String applicationName) {
this.applicationName = applicationName;
return this;
}
private static String CLIENT_ID = "***";
private static String CLIENT_SECRET = "***";
private static String REDIRECT_URI = "https://developers.google.com/oauthplayground";
public static void main(String[] args) throws IOException{
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, jsonFactory, CLIENT_ID, CLIENT_SECRET, Arrays.asList(DriveScopes.DRIVE))
.setAccessType("offline")
.setApprovalPrompt("auto").build();
String code = "4/-4JsvGiqNpZ6Ms5dLjLA2QgzgToGAxx_SZTeByBPh_Q";
GoogleTokenResponse response = flow.newTokenRequest(code).setRedirectUri(REDIRECT_URI).execute();
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setClientSecrets(CLIENT_ID, CLIENT_SECRET)
.build()
.setFromTokenResponse(response);
Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential)
.setApplicationName("musik")
.build();
//Insert a file
File body = new File();
body.setTitle("My document");
body.setDescription("A test document");
body.setMimeType("text/plain");
java.io.File fileContent = new java.io.File("document.txt");
FileContent mediaContent = new FileContent("text/plain", fileContent);
File file = service.files().insert(body, mediaContent).execute();
System.out.println("File ID: " + file.getId());
}
}
I am trying to upload file on my drive using Drive Api, everything is working fine except I have to redeem the Google Authorization code every time after using it.
Is there any tweak or method for the above code to not redeem I every time by using any refresh token or access token method?

You need not redeem authorization code every time. You get the authorization code and then refresh and access token once you are authenticated. So Instead you can use refresh token to refresh the access token and then do google drive operations.
Content body should be in this format "client_id=[clientId]&client_secret=[clientSecret]&refresh_token=[RefreshToken]&grant_type=refresh_token" and do a HTTP post method to refresh the access token.

Related

Include a file in an Android application

I used android studio to create a java app. In the project, I created the "assets" folder, and inside I put the json file that I will need to get the credentials for GmailAPI.
AssetFolder
I wish I could access the json file. I have already tried in many ways but every time it tells me that the file is missing.
This is the code:
public class GmailApi {
public Gmail initService(String userId) throws GeneralSecurityException,
IOException {
JacksonFactory jsonFactory = JacksonFactory.getDefaultInstance();
final GoogleCredentials creds = ServiceAccountCredentials.fromStream(new FileInputStream("gmailapi-android.json"))
.createScoped(GmailScopes.GMAIL_SEND);
final GoogleCredentials delegatedCreds = creds.createDelegated("xxx#xxx.com");
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(delegatedCreds);
HttpTransport transport = new NetHttpTransport.Builder().build();
// Construct the gmail object.
Gmail service = new Gmail.Builder(transport, jsonFactory, requestInitializer)
.setApplicationName("gmailapi")
.build();
return service;
}
}
Could anyone help me? What should I put in the path to be able to access the json file?
final GoogleCredentials creds = ServiceAccountCredentials.fromStream(new FileInputStream("gmailapi-android.json"))
Did you try to open the file this way?
AssetManager assetManager = getAssets();
InputStream ims = assetManager.open("gmailapi-android.json");

Service account on Google appengine (java)

How can we setup a service account authorisation with the Google Drive API, so we can act on behalf of a other user within the domain.
The code throws a HTTP ERROR 500 on line 201, see stacktrace below:
URI is not hierarchical
Caused by:
java.lang.IllegalArgumentException: URI is not hierarchical
at java.io.File.<init>(File.java:418)
at com.caase.portal.DriveServlet.getDriveService(DriveServlet.java:201)
at com.caase.portal.DriveServlet.doGet(DriveServlet.java:67)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at com.google.api.client.extensions.servlet.auth.oauth2.AbstractAuthorizationCodeServlet.service(AbstractAuthorizationCodeServlet.java:130)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
See the code mentioned below:
/** Email of the Service Account */
private static final String SERVICE_ACCOUNT_EMAIL = "xxx#developer.gserviceaccount.com";
/** Path to the Service Account's Private Key file */
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "xxx-privatekey.p12";
/**
* Build and returns a Drive service object authorized with the service accounts
* that act on behalf of the given user.
*
* #param userEmail The email of the user.
* #return Drive service object that is ready to make requests.
*/
public static Drive getDriveService(String userEmail) throws GeneralSecurityException,
IOException, URISyntaxException {
URI keyURL;
keyURL = DriveServlet.class.getResource(SERVICE_ACCOUNT_PKCS12_FILE_PATH).toURI();
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(DriveScopes.all())
.setServiceAccountUser(userEmail)
.setServiceAccountPrivateKeyFromP12File(new java.io.File(keyURL))
.build();
Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).build();
return service;
}
The line that throws the error is:
.setServiceAccountPrivateKeyFromP12File(new java.io.File(keyURL))
If I split up the line the error occurs in the new File creation:
new java.io.File(keyURL)
The key file is located in: src/main/resources
Any help is welcome :-)
Moved the resources folder from src/main/resources to src/resources and changed SERVICE_ACCOUNT_PKCS12_FILE_PATH to '/resources/xxx-privatekey.p12'. It works like a charm now!

Updating file permission to "owner" fails with 500 internal error

for our domain, there's a need to transfer files in a particular folder from one user to an admin account. The admin account has the "writer" role on all the files. Both users are in the same domain.
I'm using domain-wide delegation as the authorization method.
When updating the admin account's permission from "writer" to "owner", the program returns with 500 Internal Error. Any help will be appreciated. Thanks!
public static Drive getDriveService(String userEmail) throws GeneralSecurityException,IOException, URISyntaxException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
Collection<String> scope = new ArrayList<String>();
scope.add(DriveScopes.DRIVE);
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(scope)
.setServiceAccountUser(userEmail)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).build();
return service;
}
public static void main(String[] args) {
try {
Drive userDriveService = getDriveService(ADMIN_ACCT_EMAIL);
ChildList list = userDriveService.children().list(folderId).setQ("not '" + ADMIN_ACCT_EMAIL + "' in owners").execute();
java.util.List<ChildReference> children = list.getItems();
//Simplified for testing
ChildReference child = children.get(0);
String fileId = child.getId();
String permId = userDriveService.permissions().getIdForEmail(ADMIN_ACCT_EMAIL).execute().getId();
Permission perm = userDriveService.permissions().get(fileId, permId).execute();
perm.setRole("owner");
userDriveService.permissions().update(fileId, permId, perm).setTransferOwnership(true).execute();
} catch (GeneralSecurityException | IOException | URISyntaxException e) {
e.printStackTrace();
}
}
Realized that I should have been using the owner's email to get the driveservice. This worked after changing that one line. Thanks.
Drive userDriveService = getDriveService(ORIGINAL_OWNER_EMAIL);

Refresh token and reuse this token to get new access token java

How do I get the refresh token and the access token from the first time authorization code? And, how do I reuse this refresh token to get a new access token to upload to Google Drive using the Java API? This is not a web application. It's in Java Swing code.
We can reuse the refresh token to get new access token by following code
public class OAuthRefreshToken implements CredentialRefreshListener {
public static GoogleCredential getAccessTokenFromRefreshToken( String refreshToken, HttpTransport transport, com.google.api.client.json.JsonFactory jsonFactory, String CLIENT_ID, String CLIENT_SECRET) throws IOException
{
GoogleCredential.Builder credentialBuilder = new GoogleCredential.Builder()
.setTransport(transport).setJsonFactory(jsonFactory)
.setClientSecrets(CLIENT_ID, CLIENT_SECRET);
credentialBuilder.addRefreshListener(new OAuthRefreshToken());
GoogleCredential credential = credentialBuilder.build();
credential.setRefreshToken(refreshToken);
credential.refreshToken();
return credential;
}
#Override
public void onTokenErrorResponse(Credential arg0, TokenErrorResponse arg1)
throws IOException {
// TODO Auto-generated method stub
System.out.println("Error occured !");
System.out.println(arg1.getError());
}
#Override
public void onTokenResponse(Credential arg0, TokenResponse arg1)
throws IOException {
// TODO Auto-generated method stub
System.out.println(arg0.getAccessToken());
System.out.println(arg0.getRefreshToken());
}
}
Here is a solution I recently made up from the basic example in the Google Drive docs and some experimenting:
The IApiKey contains the static strings CLIENT_ID, and so on. ITokenPersistence is an interface which allows to load and save a token (as String). It decouples the persistence mechanism (I used Preferences for an Eclipse e4 RCP application) from the Uploader. This can be as simple as storing the token in a file The IAthorizationManager is an interface which is is used to let the user grant acces and enter the code to create the refresh token. I implemented a Dialog containing a browser widget to grant access and a text box to copy and paste the code to. The custom exception GoogleDriveException hides the API classes from the rest of the code.
public final class Uploader implements IApiKey {
public static final String TEXT_PLAIN = "text/plain";
private final ITokenPersistence tokenManager;
private final IAuthorizationManager auth;
public Uploader(final ITokenPersistence tm, final IAuthorizationManager am) {
this.tokenManager = tm;
this.auth = am;
}
private GoogleCredential createCredentialWithRefreshToken(
final HttpTransport transport,
final JsonFactory jsonFactory,
final String clientId,
final String clientSecret,
final TokenResponse tokenResponse) {
return new GoogleCredential.Builder().setTransport(transport)
.setJsonFactory(jsonFactory)
.setClientSecrets(clientId, clientSecret)
.build()
.setFromTokenResponse(tokenResponse);
}
/**
* Upload the given file to Google Drive.
* <P>
* The name in Google Drive will be the same as the file name.
* #param fileContent a file of type text/plain
* #param description a description for the file in Google Drive
* #return Answer the ID of the uploaded file in Google Drive.
* Answer <code>null</code> if the upload failed.
* #throws IOException
* #throws {#link GoogleDriveException} when a <code>TokenResponseException</code> had been
* intercepted while inserting (uploading) the file.
*/
public String upload(final java.io.File fileContent, final String description) throws IOException, GoogleDriveException {
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
// If we do not already have a refresh token a flow is created to get a refresh token.
// To get the token the user has to visit a web site and enter the code afterwards
// The refresh token is saved and may be reused.
final GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport,
jsonFactory,
CLIENT_ID,
CLIENT_SECRET,
Arrays.asList(DriveScopes.DRIVE))
.setAccessType("offline")
.setApprovalPrompt("auto").build();
final String url = flow.newAuthorizationUrl().setRedirectUri(REDIRECT_URI).build();
final String refreshToken = this.tokenManager.loadRefreshToken();
GoogleCredential credential = null;
if( refreshToken == null ) {
// no token available: get one
String code = this.auth.authorize(url);
GoogleTokenResponse response = flow.newTokenRequest(code).setRedirectUri(REDIRECT_URI).execute();
this.tokenManager.saveRefreshToken(response.getRefreshToken());
credential = this.createCredentialWithRefreshToken(httpTransport, jsonFactory, CLIENT_ID, CLIENT_SECRET, response);
}
else {
// we have a token, if it is expired or revoked by the user the service call (see below) may fail
credential = new GoogleCredential.Builder()
.setJsonFactory(jsonFactory)
.setTransport(httpTransport)
.setClientSecrets(CLIENT_ID, CLIENT_SECRET)
.build();
credential.setRefreshToken(refreshToken);
}
//Create a new authorized API client
final Drive service = new Drive.Builder(httpTransport, jsonFactory, credential)
.setApplicationName(APP_NAME)
.build();
//Insert a file
final File body = new File();
body.setTitle(fileContent.getName());
body.setDescription(description);
body.setMimeType(TEXT_PLAIN);
final FileContent mediaContent = new FileContent(TEXT_PLAIN, fileContent);
try {
final File file = service.files().insert(body, mediaContent).execute();
return ( file != null ) ? file.getId() : null;
} catch (TokenResponseException e) {
e.printStackTrace();
throw new GoogleDriveException(e.getDetails().getErrorDescription(), e.getCause());
}
}
}

Google Drive API Upload returns File ID/Title but document does not exist in Drive

I have followed the examples given on the Google Drive SDK site for Authorization via Service Accounts (https://developers.google.com/drive/service-accounts) and to insert a file (https://developers.google.com/drive/v2/reference/files/insert). I have managed to get it working using the Client ID/Client secret with oauth2 but need automation so want to use the private key.
My issue is I am given a file id, Title, Description & MIME type in return e.g. File ID: %s0B6ysbMIcH3AGWHJPRmZUTVZZMnM, Title: My document, Description: A test document, MIME type: text/plain but the document does -not- exist in Drive and no errors are returned.
I have been work on this for 2 days without success and would really appreciate any assistance. I have looked on-line and the examples I have found are similar to the below. I have tried multiple Google accounts (one a company Google Apps & another a normal gmail account with the same result).
The code (with the account info changed) :
public class AutoGoogleDrive {
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "/home/jsmith/Java/11111111111111111111111111-privatekey.p12";
private static final String SERVICE_ACCOUNT_EMAIL = "1111111111111#developer.gserviceaccount.com";
public static Drive getDriveService() throws GeneralSecurityException,
IOException, URISyntaxException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(DriveScopes.DRIVE_FILE)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).build();
return service;
}
public static void main(String[] args) throws IOException {
Drive service = null;
try {
service = getDriveService();
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Insert a text file
File body = new File();
body.setTitle("My document");
body.setDescription("A test document");
body.setMimeType("text/plain");
// File's content.
java.io.File fileContent = new java.io.File("/home/jsmith/document.txt");
FileContent mediaContent = new FileContent("text/plain", fileContent);
try {
File file = service.files().insert(body, mediaContent).execute();
// Uncomment the following line to print the File ID.
System.out.println("File ID: %s" + file.getId());
System.out.println("Title: " + file.getTitle());
System.out.println("Description: " + file.getDescription());
System.out.println("MIME type: " + file.getMimeType());
} catch (IOException e) {
System.out.println("An error occured: " + e);
}
}
}
Thanks,
Joe Smith
When using service accounts, the inserted file will be added to the application's Drive account for which there's no Drive UI. Those files are only available through the API.