I am trying to run sample code from Google Quickstart for Java on an Android emulator, but the code falls on this line
return new AuthorizationCodeInstalledApp(flow, receier).authorize("user");
It turned out that Android does not support AuthorizationCodeInstalledApp class, so you need to manually catch the URL address for authorization, open it in the browser and then put the result in the Credential object. I am familiar with Java superficially, so I don't really know how I can implement that.
Can you please tell how this can be done?
From this thread, Charan M uses this piece of code to get credential and service:
mCredential = GoogleAccountCredential.usingOAuth2(getApplicationContext(), Arrays.asList(SCOPES)).setBackOff(new ExponentialBackOff());
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.gmail.Gmail.Builder(
transport, jsonFactory, credential)
.setApplicationName(mContext.getResources().getString(R.string.app_name))
.build();
Do note that you can't run this code on the main thread since it involves network operations. They also provided a github project as a guide in integrating, in their case, Gmail API into their Android project.
Related
So here is the problem: Ive recently made this post.
Solution I've mentionned worked for one token and one API but when I tried to handle two APIs with two token (gmail and Sheets API) it failed.
So what I'm trying to do now is make the two work so I told myself "Hey let's create a service account". Even if I don't really understand the differences between both methods. Service account seems to prevent from having a consent screen (Am I right?).
I've crawled the web for answers but all of them seems to fail.
I've refreshed token, used GoogleCredential instead of Credential, created new key etc... one thing though I didn't tried is to use Gsuite account I'm using a basic account.
So now I'm at the point where I've created a new p12 file and instantly I get the 401 error. I will share my code for a better understanding.
my mail class
public class mailService {
private static final String APPLICATION_NAME = "AHS";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final String TOKENS_DIRECTORY_PATH = "tokens";
//I've added sheet scope as it is activated in my project
private static final Collection<String> SCOPES = Arrays.asList(GmailScopes.GMAIL_SEND, GmailScopes.GMAIL_LABELS, SheetsScopes.SPREADSHEETS);
private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException, GeneralSecurityException {
File sa = new File("WEB-INF/mykeyfile.p12");
Credential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(
"myapp#appspot.gserviceaccount.com")
.setServiceAccountScopes(SCOPES)
.setServiceAccountPrivateKeyFromP12File(sa)
.setServiceAccountUser("myemailadress#gmail.com")
.build();
//credential.refreshToken();
return (credential);
}
public static Gmail getService() throws GeneralSecurityException, IOException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
/*Gmail service = new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build();*/
Gmail service = new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, null)
.setHttpRequestInitializer(getCredentials(HTTP_TRANSPORT)).setApplicationName(APPLICATION_NAME).build();
return (service);
}
...
So to give you a better understanding, I'm creating a web app using Angular and Google app engine. I wan't to use Gmail API to send mail from my account, also I'm using sheets API to read/write from/to a spreadsheet. Just to be clear I have a secret file for the google-sign-in (for the user of the web app) but there this is server side code and I don't wan't user to see a consent screen.
I'm also asking myself if I need to use gcloud in order to activate service account.
I'm running (for the moment) my server locally using Eclipse and google app engine plugin.
if you need other code or precisions for better understanding of the problem let me know
Gmail dosent support service accounts unless its a gsuite account and you set up domain wide deligation.
If you check the documentation you will only see information about using Oauth2 not server account this is because Google only documents things that are supported not those that aren't.
Sheets does support service accounts just remembered that you need to pre-authorization on the service a account. That is done via sharing the sheet with the service account like you would any other user using the service accounts email address.
Hi all,
The current situation is as follows:
I currently have a google cloud project. The account that I log into the google cloud project with can also log into a DoubleClick bid Manager account. My aim is to use the DoubleClick Bid Manager api to retrieve certain buckets stored by DBM and save them in my separate google cloud project.
So far i can access the public buckets (gdbm-public) and pull and download the data, however when I try to access the partner specific buckets the same way, i.e. (gdbm-201032-201843) I get a status code 403.
Upon Reading the documentation here, I have discovered that I need to add a google group to the DBM partner information On DBM itself. However when i try to add a google group and save the changes i get an error saying the changes cannot be saved.
This is where i authenticate:
return new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("<service_account_i_cant_show_here>")
.setServiceAccountScopes(Collections.singleton(StorageScopes.DEVSTORAGE_READ_ONLY))
.setServiceAccountPrivateKeyFromP12File(new File("secret-privatekey.p12"))
.build();
I then try to access the bucket like this:
String bucketName = "gdbm-201032-201843";
GoogleCredential credentials = getCredentials();
Storage storage = new Storage(HTTP_TRANSPORT, JSON_FACTORY, credentials);
Storage.Objects.List listObjects = storage.objects().list(bucketName);
Objects objects;
do {
objects = listObjects.execute();
for (StorageObject object : objects.getItems()) {
System.out.println(object);
}
listObjects.setPageToken(objects.getNextPageToken());
} while (null != objects.getNextPageToken());
More specifically, listObjects.execute() is where the 403 is thrown.
The areas I am trying to edit are Log Read Google Group and Log Management Google Group in the partner itself.
Any help greatly appreciated, thanks!
I think i have a solution, I used a different means of authentication as found here.
Using the linked class i entered in my google cloud project client credentials and the user that i log into both the google cloud project, and DBM.
I also changed the scope to "https://www.googleapis.com/auth/cloud-platform" however i am not 100% sure this had an effect on the outcome.
Code example:
// Scopes for the OAuth token
private static final Set<String> SCOPES =
ImmutableSet.of("https://www.googleapis.com/auth/cloud-platform");
public static Credential getUserCredential() throws Exception {
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
JSON_FACTORY,
new InputStreamReader(SecurityUtilities.class.
getResourceAsStream("/client_secret.json")));
dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
// set up authorization code flow.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(dataStoreFactory)
.build();
// authorize and get credentials.
return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver())
.authorize("<Personal user account>");
So instead of using a service account i used a personal account.
I am developing an Android app to connect to my Google Tasks and show them in a ListView.
I tried to follow step by step some tutorial such as https://developers.google.com/google-apps/tasks/oauth-and-tasks-on-android but none of those works.
I tried to download the google-api-services-tasks-v1-1.1.0-beta.jar and all the jars inicated in that tutorial, and after importing all the necessary libraries it just didn't work, and when i try to get my tasks after the connection i just get nulls.
I found out that i could use Oauth2.0 for the authentication and to access to the tasks API, to get my clientID ecc., so i created an account on the Google API's Console and created my OAuth clientID.
After that I try to authenticate with this code
HttpTransport transport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
String clientId = "myID";
String clientSecret = "mySecret";
String redirectUrl = "https://localhost/oauth2callback";
Iterable<String> scope ="https://www.googleapis.com/auth/tasks";
String authorizationUrl = new GoogleAuthorizationCodeRequestUrl(clientId, redirectUrl, scope)
.build();
String code="Code";
GoogleTokenResponse response = new GoogleAuthorizationCodeTokenRequest(transport, jsonFactory,
clientId, clientSecret, code, redirectUrl).execute();
GoogleAccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(
response.getAccessToken(), transport, jsonFactory, clientId, clientSecret,
response.getRefreshToken());
Tasks service = new Tasks(transport, jsonFactory, accessProtectedResource);
AccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(accessToken);
Tasks service = new Tasks(transport, new JacksonFactory(), accessProtectedResource);
service.accessKey="MyKey";
service.setApplicationName("GTasks");
I don't get any error but after creating this service I tried to get my tasklists but nothing happened and i didn't get any result.
When I tried to Log the content of the List of tasklists i just got an empty list "{}".
I suspect that this could be because of the old version of the libraries that i found, but even when i tried to use the latest versions it didn't work and i got the same results.
I'm really confused.
Every tutorial I found recommends a different version of the libraries and a different strategy. I really don't know wich one should I follow.
The Tasks API is REALLY confusing.
I, like you, was trying without success to roll my own authentication. I've found it way easier to modify the sample provided by google-api-java-client. This sample simply lists the tasks from the "default" task list.
You'll need to download and install the GDT plugin for Eclipse, and then use it to install the Google APIs you want to use.
Once you have the sample working, you can do more with it by looking here for the different functions to use. For example, to request all the tasks in the "Default" task list use this line:
client.tasks().list("#default").setFields("items/title").execute().getItems();
To update a task:
client.tasks().update("#default", task.getId(), task).execute();
And so on.
i would like to upload videos on youtube from my java web application:
I want to receive (server side) my authToken and form-action so to upload a video.
I've created a new google/youtube account
I've created a youtube channel in my account
i've created a new project in my google console api as a Service Account
Now i'm trying to implement my code with oAuth 2.0.
I've got the accessToken but, when i try to call the service getFormUploadToken(url, object) the response is always the same "NoLinkedYoutubeAccount error 401".
i've also verified the account by the google support page http://www.youtube.com/my_account_unlink but it's seems ok.
Does anybody have an idea about this problem?
This is my code:
HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
JsonFactory JSON_FACTORY = new JacksonFactory();
String accessToken = "";
GoogleCredential credential = null;
credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(CLIENT_EMAIL)
.setServiceAccountScopes("http://gdata.youtube.com")
.setServiceAccountPrivateKeyFromP12File(new File(PRIVATE_KEY_PATH))
.build();
credential.refreshToken();
accessToken = credential.getAccessToken();
YouTubeService service = new YouTubeService(CLIENT_ID, DEV_KEY);
service.setAuthSubToken(accessToken, null);
VideoEntry newEntry = new YouTubeMediaGroup mg = newEntry.getOrCreateMediaGroup();
mg.setTitle(new MediaTitle());
mg.getTitle().setPlainTextContent("My Test Movie");
URL uploadUrl = new URL("http://gdata.youtube.com/action/GetUploadToken");
FormUploadToken token = service.getFormUploadToken(uploadUrl, newEntry);
Thanks a lot,
Albert III
As the error say, you have not linked the account credential to youtube.
You can solve that problem:
- Connecting with the account used on the app in www.youtube.com
- Trying to upload a video
- Setting name and surname when youtube ask, and process to link to gmail.
Done!!! I tried before using my app to upload the video using Firefox.
You can't associate a YouTube channel with a Service Account, and you're trying to upload under the context of the Service Account.
Instead of using Service Accounts, you should go through the OAuth 2 flow and authorize access while logged in to the browser using the account that you actually want to upload into.
I understand the benefits of using Service Accounts, but YouTube is not set up to work with them at this time.
If you have created youtube account and if has been linked to your google account, then make sure you create your own channel in your youtube.
This will allow the API to upload videos to your created channel.
Hope it helps.
I would like to impersonate a user and add files to the users Google Drive on their behalf from a server process. I've setup a service account and can successfully access the Drive as the service account adding and listing files, etc. using the following code:
/** Global instance of the HTTP transport. */
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
public static void main(String[] args) {
try {
GoogleCredential credential =
new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("XXXXX#developer.gserviceaccount.com")
.setServiceAccountScopes(DriveScopes.DRIVE)
.setServiceAccountPrivateKeyFromP12File(new File("c:/junk/key.p12"))
.build();
Drive drive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).build();
drive.files().list().execute();
} catch (Exception e) {
e.printStackTrace();
}
This works, however only returns files that are associated to what I assume is associated with the service accounts drive (?).
According to the JavaDoc, GoogleCredential can also be used to impersonate a user by adding the service account users email address as follows:
GoogleCredential credential =
new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("XXXXX#developer.gserviceaccount.com")
.setServiceAccountScopes(DriveScopes.DRIVE)
.setServiceAccountPrivateKeyFromP12File(new File("c:/junk/key.p12"))
.setServiceAccountUser("usera#domain.com") //<-- impersonate user a
.build();
However, when executing this code, the following exception is thrown:
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "access_denied"
}
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:103)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:303)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:323)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:340)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:508)
at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:260)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:796)
at com.google.api.client.googleapis.json.GoogleJsonResponseException.execute(GoogleJsonResponseException.java:198)
at com.google.api.client.googleapis.services.GoogleClient.executeUnparsed(GoogleClient.java:237)
at com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:207)
at com.google.api.services.drive.Drive$Files$List.execute(Drive.java:1071)
Am I missing a step or configuration setting?
Thanks,
David
I found a similar question as mine: Can a Google Apps Admin manage users files with Drive SDK? to mine which has helped me figure out the answer.
The cPanel documentation is a little misleading as it refers to enabling the consumer key and then adding the domain to the Manage API client access screen. This appears to be valid for the gdata api and not the new Google Drive api. By adding the client id as suggested in the other question and granting access to the Drive scope I'm now able to impersonate a user.
Get your admin to add scopes to xxxxx.apps.googleusercontent.com via admin panel:
I added the following to work on spreadsheets:
https://www.googleapis.com/auth/drive
https://docs.google.com/feeds
https://spreadsheets.google.com/feeds