Cannot get data from Google Analytics (401 Unauthorized) - java

I try to implement basic data feed example and all I get is just:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized.
But when I use http://code.google.com/apis/analytics/docs/gdata/gdataExplorer.html
It works fine with my Google Analytics account.
It seems I've done everything according to OAuth2 instructions: created client id and client secret, enabled Analytcs API.
Also I've tried to get my profiles and accounts with Analytics Management API but I get the same error. What do I do wrong?
Here is my code (of course I run this code with actual CLIENT_ID, CLIENT_SECRET and TABLE_ID):
public class AnalyticsTest {
private static final String CLIENT_ID = "MY_CLIENT_ID";
private static final String CLIENT_SECRET = "MY_CLIENT_SECRET";
private static final String REDIRECT_URL = "urn:ietf:wg:oauth:2.0:oob";
private static final String APPLICATION_NAME = "test";
private static final String SCOPE = "https://www.googleapis.com/auth/analytics";
// TRIED AS WELL private static final String SCOPE = "https://www.google.com/analytics/feeds";
private static final String TABLE_ID = "MY_TABLE_ID";
public static void main(String[] args) throws IOException {
NetHttpTransport netHttpTransport = new NetHttpTransport();
JacksonFactory jacksonFactory = new JacksonFactory();
// Generate the URL to send the user to grant access.
String authorizationUrl = new GoogleAuthorizationRequestUrl(CLIENT_ID, REDIRECT_URL, SCOPE).build();
// Direct user to the authorization URI.
System.out.println("Go to the following link in your browser:");
System.out.println(authorizationUrl);
// Get authorization code from user.
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("What is the authorization code?");
String authorizationCode = null;
authorizationCode = in.readLine();
// Use the authorization code to get an access token and a refresh
// token.
AccessTokenResponse response = null;
try {
response = new GoogleAccessTokenRequest.GoogleAuthorizationCodeGrant(netHttpTransport, jacksonFactory, CLIENT_ID, CLIENT_SECRET, authorizationCode, REDIRECT_URL).execute();
} catch (IOException ioe) {
ioe.printStackTrace();
}
// Use the access and refresh tokens to get a new
// GoogleAccessProtectedResource.
GoogleAccessProtectedResource googleAccessProtectedResource = new GoogleAccessProtectedResource(response.accessToken, netHttpTransport, jacksonFactory, CLIENT_ID, CLIENT_SECRET, response.refreshToken);
Analytics analytics = Analytics
.builder(netHttpTransport, jacksonFactory)
.setHttpRequestInitializer(googleAccessProtectedResource)
.setApplicationName(APPLICATION_NAME).build();
//System.out.println(analytics.management().accounts().list().execute());
Get apiQuery = analytics.data().ga().get(TABLE_ID, // "ga:" + Profile
// Id.
"2011-09-01", // Start date.
"2011-12-23", // End date.
"ga:visits"); // Metrics.
try {
GaData gaData = apiQuery.execute();
// Success. Do something cool!
} catch (GoogleJsonResponseException e) {
// Catch API specific errors.
e.printStackTrace();
} catch (IOException e) {
// Catch general parsing errors.
e.printStackTrace();
}
}
Here is the stack trace:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
"code" : 401,
"errors" : [ {
"domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "Invalid Credentials",
"reason" : "authError"
} ],
"message" : "Invalid Credentials"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:138)
at com.google.api.client.googleapis.services.GoogleClient.execute(GoogleClient.java:123)
at com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:67)
at com.google.api.services.analytics.Analytics$Data$Ga$Get.execute(Analytics.java:1335)
at voc.AnalyticsTest.main(AnalyticsTest.java:76)

Try changing your scope from this:
private static final String SCOPE = "https://www.googleapis.com/auth/analytics";
to this:
private static final String SCOPE = "https://www.googleapis.com/auth/analytics.readonly";

Related

Is it possible to get access token through azure graph and use it to access azure storage accounts?

For instance I can authenticate through graph api by getaccesstokencredentials(username, password)
Can I use this token to access Azure?
Current we can use usertokencredentials and applicationtokencredentials from management library then once done you can create instance of azure class.
Azure azure = Azure.authenticate(credentials).withdefaultsubscription.
I'm wondering if we can use the token from getaccesstokencredentials instead of usertokentcredentials and applicationtokencredentials
We cannot use the the same access token to call graph api and call api to manage Azure resource. Because the resource url for graph api ishttps://graph.microsoft.com/ but the resource url for Azure management rest api is https://management.azure.com/. For more details, please refer to https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-api-authentication.
Besides, regarding how to use Azure AD to access Azure storage, please refer to the following steps:
Add role assignment to your principal.
Get token.
public static String getToken() throws Exception {
String TENANT_ID = "your tenant id or name, e4c9*-*-*-*-*57fb";
String AUTHORITY = "https://login.microsoftonline.com/" + TENANT_ID;
String CLIENT_ID = "your application id, dc17*-*-*-*a5e7";
String CLIENT_SECRET = "the secret, /pG*32";
String RESOURCE = "https://storage.azure.com/";
String ACCESS_TOKEN = null;
ExecutorService service = Executors.newFixedThreadPool(1);
AuthenticationContext context = null;
try {
context = new AuthenticationContext(AUTHORITY, false, service);
ClientCredential credential = new ClientCredential(CLIENT_ID, CLIENT_SECRET);
Future<AuthenticationResult> future = context.acquireToken(RESOURCE, credential, null);
ACCESS_TOKEN = future.get().getAccessToken();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} finally {
service.shutdown();
}
return ACCESS_TOKEN;
}
Access blob.
public static void main(String[] args) throws Exception {
String token = getToken();
StorageCredentialsToken credentialsToken = new StorageCredentialsToken("storagetest789", token);
CloudBlobClient blobClient = new CloudBlobClient(new URI("https://storagetest789.blob.core.windows.net/"), credentialsToken);
CloudBlobContainer blobContainer = blobClient.getContainerReference("pub");
CloudBlockBlob blockBlob = blobContainer.getBlockBlobReference("test1.txt");
blockBlob.uploadText("mytest");
}
For more details, please refer to https://learn.microsoft.com/en-us/azure/storage/common/storage-auth-aad.

Unable to have concurrent log-ins with Google auth

I have a web app where users have to authenticate using Google sign-in. I do this because I need to grab their email address. When they fill out the fields on the page, all that data is stored in a google sheet alongside their email address (for auditing purposes incase something is askew with the data). Unfortunately what's happening is that if user A signs in, and does some work and at the same time user B logs in, when user A submits data, they will be submitting user B's email address (as does user B). In short, the latest person to log in, that email address is used. There is no database and I'm not storing any cookies. When they refresh the page, they have to re-authenticate. I am using Angular 7 and Java. Here is the code that I used:
ngOnInit() {
gapi.load('auth2', () => {
this.auth2 = gapi.auth2.init({
client_id: 'CLIENT_ID_HERE',
// Scopes to request in addition to 'profile' and 'email'
scope: 'https://www.googleapis.com/auth/spreadsheets'
});
});
}
signInWithGoogle(): void {
this.auth2.grantOfflineAccess().then((authResult) => {
this.authCode = authResult['code'];
this.fetchData();
});
}
authCode is bound to the child component so it can be passed as query param to the java code for google auth.
this.seriesService.submitSeriesData(matchList, this.authToken).subscribe(res => {.....);
The google auth java code is so:
private static final String APPLICATION_NAME = "Google Sheets API Java";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final List<String> SCOPES = Collections.singletonList(SheetsScopes.SPREADSHEETS);
private static final String CLIENT_SECRET_DIR = "/client_secret.json";
private static GoogleTokenResponse tokenResponse = null;
public static String getEmailAddress() throws IOException {
GoogleIdToken idToken = tokenResponse.parseIdToken();
GoogleIdToken.Payload payload = idToken.getPayload();
String email = payload.getEmail();
return email;
}
public static Sheets getSheetsService1(String token, String redirectUri) throws IOException, GeneralSecurityException {
// Exchange auth code for access token
InputStream in = GoogleAuthUtil.class.getResourceAsStream(CLIENT_SECRET_DIR);
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
new NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
"https://www.googleapis.com/oauth2/v4/token",
clientSecrets.getDetails().getClientId(),
clientSecrets.getDetails().getClientSecret(),
token,
redirectUri)
.execute();
String accessToken = tokenResponse.getAccessToken();
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Sheets service = new Sheets.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential)
.setApplicationName("MY APP HERE")
.build();
return service;
}
And the endpoint:
#RequestMapping(value="series/data", method = RequestMethod.POST, consumes="application/json")
public boolean submitSeriesMatchData(#RequestBody(required=true) SubmitStatsDto request) throws IOException, GeneralSecurityException, Exception {
if (service == null) {
service = GoogleAuthUtil.getSheetsService1(request.getToken(), this.redirectUri);
}
......
}
1) User clicks on the google sign in button
2) They select email and auth with google
3) I receive an auth code back and store it in ng.
4) Every REST call is passed said token to auth with google, and every endpoint calls getSheetsService1 which authenticates w/ token. (multiple endpoints, I only showed one above)
5) I get email from that tokenResponse.
Any ideas? This site will not have a database/users/local logins. Thank you.

Get user profile from GoogleIdToken

I'm trying to do this:
https://developers.google.com/identity/sign-in/web/backend-auth#calling-the-tokeninfo-endpoint
I copy pasted the Java code from the example, with my CLIENT_ID, but I can't get any more information than user id, email and email verified. idTokenString verifies OK. Have anyone else got this to work?
I asked for these in OAuth 2.0 Playground:
https://www.googleapis.com/auth/plus.login
https://www.googleapis.com/auth/plus.me
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/userinfo.profile
https://www.googleapis.com/auth/plus.moments.write
https://www.googleapis.com/auth/plus.profile.agerange.read
https://www.googleapis.com/auth/plus.profile.language.read
https://www.googleapis.com/auth/plus.circles.members.read
I guess the user.profile is the one i need only?
This is my code:
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
.setAudience(Arrays.asList(CLIENT_ID))
.setIssuer("accounts.google.com")
.build();
GoogleIdToken idToken = verifier.verify(idTokenString);
System.out.println("SUCCESS!");
System.out.println(idToken);
if (idToken != null) {
GoogleIdToken.Payload payload = idToken.getPayload();
// Print user identifier
String userId = payload.getSubject();
System.out.println("User ID: " + userId);
// Get profile information from payload
String email = payload.getEmail();
boolean emailVerified = payload.getEmailVerified();
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
// Use or store profile information
// ...
System.out.println(email);
System.out.println(emailVerified);
System.out.println(name);
System.out.println(pictureUrl);
System.out.println(locale);
System.out.println(familyName);
System.out.println(givenName);
} else {
System.out.println("Invalid ID token.");
}
} catch (GeneralSecurityException | IOException e) {
System.out.println("ERRRRO! Invalid ID token.");
}
Using: java-api-client 1.20.0
I encountered the same issue today using com.google.api-client:google-api-client:1.22.0
But I was able to solve it.
Problem
When trying to get id token from OAuth2 playground I've noticed that there is this request
POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
The Google library has hard coded TOKEN_SERVER_URL in GoogleOAuthConstants with value https://accounts.google.com/o/oauth2/token
Fix
To fix it I've created following class
public class GoogleAuthorizationCodeTokenV4Request extends GoogleAuthorizationCodeTokenRequest {
public GoogleAuthorizationCodeTokenV4Request(HttpTransport transport, JsonFactory jsonFactory, String clientId, String
clientSecret, String code, String redirectUri) {
super(transport, jsonFactory, "https://www.googleapis.com/oauth2/v4/token", clientId, clientSecret,
code, redirectUri);
}
}
And then just invoke it instead the original GoogleAuthorizationCodeTokenRequest
return new GoogleAuthorizationCodeTokenV4Request(new NetHttpTransport(), JacksonFactory.getDefaultInstance(),
clientId, secret, authToken, callBack)
.execute();
With profile scope all information (picture, names, ...) are in id_token

Facing Issue While Integrating Google Login Button With Java Application

I am working on Hybris Technology. It is nothing but the Java only. So I am trying to Integrate Google Login Button with my Java Application.
I am following this tutorial. Here is my code What I am doing
Front Part --
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
</script>
<script type="text/javascript">
(function () {
var po = document.createElement('script');
po.type = 'text/javascript';
po.async = true;
po.src = 'https://plus.google.com/js/client:plusone.js?onload=start';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
<div id="signinButton">
<span class="g-signin" data-scope="https://www.googleapis.com/auth/plus.login"
data-clientid="*****************************"
data-redirecturi="postmessage"
data-accesstype="offline"
data-cookiepolicy="single_host_origin"
data-callback="signInCallback">
</span>
</div>
<div id="result"></div>
<script type="text/javascript">
function signInCallback(authResult) {
if (authResult['code']) {
// Hide the sign-in button now that the user is authorized, for example:
$('#signinButton').attr('style', 'display: none');
// Send the code to the server
$.ajax({
type: 'GET',
url: '/store/en/login/lnregister',
contentType: 'application/octet-stream; charset=utf-8',
success: function(result) {
// Handle or verify the server response if necessary.
// Prints the list of people that the user has allowed the app to know
// to the console.
console.log(result);
if (result['profile'] && result['people']){
$('#results').html('Hello ' + result['profile']['displayName'] + '. You successfully made a server side call to people.get and people.list');
} else {
$('#results').html('Failed to make a server-side call. Check your configuration and console.');
}
},
processData: false,
data: authResult['code']
});
} else if (authResult['error']) {
// There was an error.
// Possible error codes:
// "access_denied" - User denied access to your app
// "immediate_failed" - Could not automatially log in the user
// console.log('There was an error: ' + authResult['error']);
}
}
</script>
Here I am using ajax to call my controller function lnregister.
#RequestMapping(value = "/lnregister", method = RequestMethod.GET)
public String doLnRegister(#RequestHeader(value = "referer", required = false) final String referer, final RegisterForm form,
final BindingResult bindingResult, final Model model, final HttpServletRequest request,
final HttpServletResponse response, final RedirectAttributes redirectModel) throws CMSItemNotFoundException
{
final Gson gson = new Gson();
final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
final String APPLICATION_NAME = "HybrisProject";
final HttpTransport TRANSPORT = new HttpTransport()
{
#Override
protected final LowLevelHttpRequest buildRequest(final String arg0, final String arg1) throws IOException
{
// YTODO Auto-generated method stub
return null;
}
};
final String CLIENT_ID = "************************";
final String CLIENT_SECRET = "*******************";
// Create a state token to prevent request forgery.
// Store it in the session for later validation.
final String state = new BigInteger(130, new SecureRandom()).toString(32);
request.getSession().setAttribute("state", state);
// Read index.html into memory, and set the Client ID,
// Token State, and Application Name in the HTML before serving it.
try
{
return new Scanner(new File("index.html"), "UTF-8").useDelimiter("\\A").next()
.replaceAll("[{]{2}\\s*CLIENT_ID\\s*[}]{2}", CLIENT_ID).replaceAll("[{]{2}\\s*STATE\\s*[}]{2}", state)
.replaceAll("[{]{2}\\s*APPLICATION_NAME\\s*[}]{2}", APPLICATION_NAME);
}
catch (final FileNotFoundException e2)
{
// YTODO Auto-generated catch block
e2.printStackTrace();
}
if (!request.getParameter("state").equals(request.getSession().getAttribute("state")))
{
response.setStatus(401);
gson.toJson("Invalid state parameter.");
}
final String gPlusId = request.getParameter("gplus_id");
String code = null;
try
{
code = request.getReader().toString();
}
catch (final IOException e1)
{
// YTODO Auto-generated catch block
e1.printStackTrace();
}
try
{
// Upgrade the authorization code into an access and refresh token.
final GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(TRANSPORT, JSON_FACTORY, CLIENT_ID,
CLIENT_SECRET, code, "postmessage").execute();
// Create a credential representation of the token data.
final GoogleCredential credential = new GoogleCredential.Builder().setJsonFactory(JSON_FACTORY).setTransport(TRANSPORT)
.setClientSecrets(CLIENT_ID, CLIENT_SECRET).build().setFromTokenResponse(tokenResponse);
// Check that the token is valid.
final Oauth2 oauth2 = new Oauth2.Builder(TRANSPORT, JSON_FACTORY, credential).build();
final Tokeninfo tokenInfo = oauth2.tokeninfo().setAccessToken(credential.getAccessToken()).execute();
// If there was an error in the token info, abort.
if (tokenInfo.containsKey("error"))
{
response.setStatus(401);
return gson.toJson(tokenInfo.get("error").toString());
}
// Make sure the token we got is for the intended user.
if (!tokenInfo.getUserId().equals(gPlusId))
{
response.setStatus(401);
return gson.toJson("Token's user ID doesn't match given user ID.");
}
// Make sure the token we got is for our app.
if (!tokenInfo.getIssuedTo().equals(CLIENT_ID))
{
response.setStatus(401);
return gson.toJson("Token's client ID does not match app's.");
}
// Store the token in the session for later use.
request.getSession().setAttribute("token", tokenResponse.toString());
return gson.toJson("Successfully connected user.");
}
catch (final TokenResponseException e)
{
response.setStatus(500);
return gson.toJson("Failed to upgrade the authorization code.");
}
catch (final IOException e)
{
response.setStatus(500);
return gson.toJson("Failed to read token data from Google. " + e.getMessage());
}
}
Here my Question is Am I going in right direction. Is it a proper way to connect java application with Google Login API. My Front View is working fine. When I click on google+ button, request also going to my controller. But There in backend side I am getting error. I am not pasting this error bacause error like NullPointerException or like that.
My Question is I am going in a proper way or not. If It is not, then what is the right way. Please help me.
You are making this very hard for yourself, and re-implementing too much.
Read http://krams915.blogspot.se/2011/02/spring-security-3-openid-login-with_13.html
You just need to ensure your Provider and UserDetailsService do what you need.

Java Google Plus Access via oAuth 2.0

I tried many different things to access a google Account in order to read out profile-data, but it failed every time.
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
"code" : 401,
"errors" : [ {
"domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "Invalid Credentials",
"reason" : "authError"
} ],
"message" : "Invalid Credentials"
}
I tried to access via following code
#SuppressWarnings("deprecation")
public static GoogleAccessProtectedResource connect(String CLIENT_ID,String CLIENT_SECRET,String SCOPE,String CALLBACK_URL,HttpTransport TRANSPORT,JsonFactory JSON_FACTORY) throws IOException{
// Generate the URL to which we will direct users
String authorizeUrl = new GoogleAuthorizationRequestUrl(CLIENT_ID,
CALLBACK_URL, SCOPE).build();
System.out.println("Paste this url in your browser: " + authorizeUrl);
// Wait for the authorization code
System.out.println("Type the code you received here: ");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String authorizationCode = in.readLine();
// Exchange for an access and refresh token
GoogleAuthorizationCodeGrant authRequest = new GoogleAuthorizationCodeGrant(TRANSPORT,
JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, authorizationCode, CALLBACK_URL);
authRequest.useBasicAuthorization = false;
AccessTokenResponse authResponse = authRequest.execute();
String accessToken = authResponse.accessToken;
GoogleAccessProtectedResource access = new GoogleAccessProtectedResource(accessToken,
TRANSPORT, JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, authResponse.refreshToken);
HttpRequestFactory rf = TRANSPORT.createRequestFactory(access);
System.out.println("Access token: " + authResponse.accessToken);
// Make an authenticated request
GenericUrl shortenEndpoint = new GenericUrl("https://www.googleapis.com/urlshortener/v1/url");
String requestBody =
"{\"longUrl\":\"http://farm6.static.flickr.com/5281/5686001474_e06f1587ff_o.jpg\"}";
HttpRequest request = rf.buildPostRequest(shortenEndpoint,
ByteArrayContent.fromString("application/json", requestBody));
HttpResponse shortUrl = request.execute();
BufferedReader output = new BufferedReader(new InputStreamReader(shortUrl.getContent()));
System.out.println("Shorten Response: ");
for (String line = output.readLine(); line != null; line = output.readLine()) {
System.out.println(line);
}
// Refresh a token (SHOULD ONLY BE DONE WHEN ACCESS TOKEN EXPIRES)
//access.refreshToken();
//System.out.println("Original Token: " + accessToken + " New Token: " + access.getAccessToken());
return access;
}
Then i want to access my account
public static void getData1(String accessToken, String clientId, String clientSecret, String refreshToken) throws IOException{
// Set up the HTTP transport and JSON factory
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
// Set up OAuth 2.0 access of protected resources
// using the refresh and access tokens, automatically
// refreshing the access token when it expires
GoogleAccessProtectedResource requestInitializer =
new GoogleAccessProtectedResource(accessToken, httpTransport,
jsonFactory, clientId, clientSecret, refreshToken);
// Set up the main Google+ class
Plus plus = Plus.builder(httpTransport, jsonFactory)
.setHttpRequestInitializer(requestInitializer)
.build();
// Make a request to access your profile and display it to console
Person profile = plus.people().get("[myID]").execute();
System.out.println("ID: " + profile.getId());
System.out.println("Name: " + profile.getDisplayName());
System.out.println("Image URL: " + profile.getImage().getUrl());
System.out.println("Profile URL: " + profile.getUrl());
}
Following main method should work afterwards: CLIENT_ID and CLIENT_SECRET are created
public static void main(String[] args) throws IOException {
GoogleAccessProtectedResource access1=Connection.connect(CLIENT_ID, CLIENT_SECRET, SCOPE, CALLBACK_URL, TRANSPORT, JSON_FACTORY);
//refresh
String token= access1.getAccessToken();
access1.refreshToken();
String refreshed=access1.getAccessToken();
//get data
Connection.getData1(token, CLIENT_ID, CLIENT_SECRET, refreshed);
}
This is my Data...
private static final String SCOPE = "https://www.googleapis.com/auth/urlshortener";
private static final String CALLBACK_URL = "urn:ietf:wg:oauth:2.0:oob";
private static final HttpTransport TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
// FILL THESE IN WITH YOUR VALUES FROM THE API CONSOLE
private static final String CLIENT_ID = "[myID].apps.googleusercontent.com";
private static final String CLIENT_SECRET = "[myID]";
Now there is a bad Request Exception thrown
Exception in thread "main" com.google.api.client.http.HttpResponseException: 400 Bad Request
{
"error" : "invalid_client"
}
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:900)
at com.google.api.client.auth.oauth2.draft10.AccessTokenRequest.executeUnparsed(AccessTokenRequest.java:472)
at com.google.api.client.auth.oauth2.draft10.AccessTokenRequest.execute(AccessTokenRequest.java:486)
at Connection.connect(Connection.java:78)
at Connection.main(Connection.java:50)
This is hopefully pretty easy to fix.
You're using a SCOPE string of:
https://www.googleapis.com/auth/urlshortener
This is the scope for the URL Shortener (goo.gl) API, not the Google+ APIs. Instead you should probably try using the profile scope for Google+
https://www.googleapis.com/auth/plus.me
Documentation here:
https://developers.google.com/+/api/oauth
Above, it looks like you're using [myID] to reference two different types of ID:
In the below statement, the myID should be your Google+ profile ID (copied/pasted from the URL for your Google+ profile or instead use the string 'me' to represent the currently authorized user):
Person profile = plus.people().get("[myID]").execute();
However, for the CLIENT_ID, you should be using the values from your project in code.google.com/apis/console.

Categories