This is what i have:
static AccessToken accessToken = new DefaultFacebookClient().obtainExtendedAccessToken("<my app id>", "<my app secret>");
static FacebookClient client = new DefaultFacebookClient();
public static void main(String args[]) {
System.out.print("Enter Your Status: ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String status= null;
try {
userName = br.readLine();
System.out.println("..........");
} catch (IOException ioe) {
System.out.println("!");
System.exit(1);
}
FacebookType publishMessageResponse =
client.publish("me/feed", FacebookType.class,
Parameter.with("message", status));
So first line gets the token and stores it as type AccessToken but what good does that do to me because next line i need to provide the access token as a string and i can't convert it. Any Help?
First of all don't confuse app token with user token (more info)
To get user token you have to
Provide a way for user to authenticate against Facebook (more info) and receive "code" - an encrypted string unique to each login request.
Get the user token using this code.
You can get user token with pure RestFB the following way:
private FacebookClient.AccessToken getFacebookUserToken(String code, String redirectUrl) throws IOException {
String appId = "YOUR_APP_ID";
String secretKey = "YOUR_SECRET_KEY";
WebRequestor wr = new DefaultWebRequestor();
WebRequestor.Response accessTokenResponse = wr.executeGet(
"https://graph.facebook.com/oauth/access_token?client_id=" + appId + "&redirect_uri=" + redirectUrl
+ "&client_secret=" + secretKey + "&code=" + code);
return DefaultFacebookClient.AccessToken.fromQueryString(accessTokenResponse.getBody());
}
The call is simple:
FacebookClient.AccessToken token = getFacebookUserToken(code, redirectUrl);
String accessToken = token.getAccessToken();
Date expires = token.getExpires();
In addition to what Jack said about AccessToken.getAccessToken() returning the string value of accessToken, you can avoid instantiating DefaultFacebookClient twice by extending DefaultFacebookClient like this:
import com.restfb.DefaultFacebookClient;
public class LoggedInFacebookClient extends DefaultFacebookClient {
public LoggedInFacebookClient(String appId, String appSecret) {
AccessToken accessToken = this.obtainAppAccessToken(appId, appSecret);
this.accessToken = accessToken.getAccessToken();
}
}
Try the following code:
AccessToken accessToken = new DefaultFacebookClient().obtainAppAccessToken(appid,appsecret);
String token=accessToken.getAccessToken();
Per restfb.FacebookClient.AccessToken, you should be able to call accessToken.getAccessToken() -- that should return the String you are looking for.
This will work
AccessToken accessToken = new DefaultFacebookClient().obtainAppAccessToken("XXXX", "XXXX");
String token=accessToken.getAccessToken();
DefaultFacebookClient facebookClient = new DefaultFacebookClient(token);
Related
I have the following Setup:
Keycloak 9.0.0 running on port 8180
Spring Boot server application running on port 8080
Demo client application using CxfTypeSafeClientBuilder to access server service
The Keycloak - Spring Boot interaction is working fine and I can receive tokens from Keycloak and the demo service is validating the token if I pass it as Authorization header.
How should I configure the CxfTypeSafeClientBuilder / RestClientBuilder to handle the JWT tokens I get from the Keycloak instance? Do I have to build my own ClientResponseFilter, if so how to handle expired tokens?
Are there any existing implementations / standards I didn't find?
JAX-RS webservice interface:
#Path("/demo")
public interface IDemoService {
#GET
#Path("/test")
String test();
}
Simple Spring Security configuration:
http.cors().and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.sessionAuthenticationStrategy(sessionAuthenticationStrategy()).and().authorizeRequests().antMatchers("/**")
.authenticated();
EDIT: new workaround to get initial access- and refresh token from server:
AccessTokenResponse tokens = AuthUtil.getAuthTokens("http://localhost:8180/auth", "share-server", "test", "test", "share-server-service-login");
String accessToken = tokens.getToken();
String refreshToken = tokens.getRefreshToken();
Client doing service calls until the token expires:
URI apiUri = new URI("http://localhost:8080/services/");
RestClientBuilder client = new CxfTypeSafeClientBuilder().baseUri(apiUri).register(new TokenFilter(accessToken, refreshToken));
IDemoService service = client.build(IDemoService.class);
for (int i = 0; i < 200; i++) {
System.out.println("client: " + new Date() + " " + service.test());
Thread.sleep(10000);
}
TokenFilter which works until the access-token expires:
public static class TokenFilter implements ClientRequestFilter, ClientResponseFilter {
private String accessToken;
private String refreshToken;
public TokenFilter(String accessToken, String refreshToken) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}
#Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
if (responseContext.getStatus() == 401 && "invalid_token".equals(responseContext.getStatusInfo().getReasonPhrase())) {
// maybe handle send the refresh token... probalby should be handled earlier using the 'expires' value
}
}
#Override
public void filter(ClientRequestContext requestContext) throws IOException {
if (accessToken != null && !accessToken.isEmpty()) {
requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, "Bearer" + " " + accessToken);
}
}
}
Found a better solution with only dependencies on keycloak-authz-client:
String serverUrl = "http://localhost:8180/auth";
String realm = "share-server";
String clientId = "share-server-service-login";
String clientSecret = "e70752a6-8910-4043-8926-03661f43398c";
String username = "test";
String password = "test";
Map<String, Object> credentials = new HashMap<>();
credentials.put("secret", clientSecret);
Configuration configuration = new Configuration(serverUrl, realm, clientId, credentials, null);
AuthzClient authzClient = AuthzClient.create(configuration);
AuthorizationResource authorizationResource = authzClient.authorization(username, password);
URI apiUri = new URI("http://localhost:8080/services/");
RestClientBuilder client = new CxfTypeSafeClientBuilder().baseUri(apiUri).register(new TokenFilter(authorizationResource));
IDemoService service = client.build(IDemoService.class);
for (int i = 0; i < 200; i++) {
System.out.println("client: " + new Date() + " " + service.test());
Thread.sleep(10000);
}
authorizationResource.authorize() will use org.keycloak.authorization.client.util.TokenCallable.call() in the background which validates the token expiration time and automatically refreshes the token if necessary.
so String accessToken = authorize.getToken(); will always be the current valid token.
#Priority(Priorities.AUTHENTICATION)
public static class TokenFilter implements ClientRequestFilter {
private AuthorizationResource authorizationResource;
public TokenFilter(AuthorizationResource authorizationResource) {
this.authorizationResource = authorizationResource;
}
#Override
public void filter(ClientRequestContext requestContext) throws IOException {
AuthorizationResponse authorize = authorizationResource.authorize();
String accessToken = authorize.getToken();
System.out.println(accessToken);
if (accessToken != null && !accessToken.isEmpty()) {
requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, "Bearer" + " " + accessToken);
}
}
}
I found a solution which automatically refreshes the access token but now I have a dependency to keycloak-client-registration-cli (which is actually intended to provide a console).
There might be better solutions with a less heavy dependencies.
Currently no handling if login fails or other exception handling implemented.
String serverUrl = "http://localhost:8180/auth";
String realm = "share-server";
String clientId = "share-server-service-login";
String username = "test";
String password = "test";
// initial token after login
AccessTokenResponse token = AuthUtil.getAuthTokens(serverUrl, realm, username, password, clientId);
String accessToken = token.getToken();
String refreshToken = token.getRefreshToken();
ConfigData configData = new ConfigData();
configData.setRealm(realm);
configData.setServerUrl(serverUrl);
RealmConfigData realmConfigData = configData.sessionRealmConfigData();
realmConfigData.setClientId(clientId);
realmConfigData.setExpiresAt(System.currentTimeMillis() + token.getExpiresIn() * 1000);
realmConfigData.setRefreshExpiresAt(System.currentTimeMillis() + token.getRefreshExpiresIn() * 1000);
realmConfigData.setToken(accessToken);
realmConfigData.setRefreshToken(refreshToken);
ConfigUtil.setupInMemoryHandler(configData);
URI apiUri = new URI("http://localhost:8080/services/");
RestClientBuilder client = new CxfTypeSafeClientBuilder().baseUri(apiUri).register(new TokenFilter(configData));
IDemoService service = client.build(IDemoService.class);
for (int i = 0; i < 200; i++) {
System.out.println("client: " + new Date() + " " + service.test());
Thread.sleep(10000);
}
Filter which automatically refreshes the access token if expired using AuthUtil.ensureToken(configData):
#Priority(Priorities.AUTHENTICATION)
public static class TokenFilter implements ClientRequestFilter {
private ConfigData configData;
public TokenFilter(ConfigData configData) {
this.configData = configData;
}
#Override
public void filter(ClientRequestContext requestContext) throws IOException {
String accessToken = AuthUtil.ensureToken(configData);
if (accessToken != null && !accessToken.isEmpty()) {
requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, "Bearer" + " " + accessToken);
}
}
}
More generic solution using Apache CXF OAuth2 (cxf-rt-rs-security-oauth2), without ClientRequestFilter.
The BearerAuthSupplier automatically handles refreshTokens and receives new accessTokens.
String serverUrl = "http://localhost:8180/auth";
String realm = "share-server";
String clientId = "share-server-service-login";
String clientSecret = "e70752a6-8910-4043-8926-03661f43398c";
String username = "test";
String password = "test";
String tokenUri = serverUrl + "/realms/" + realm + "/protocol/openid-connect/token";
Consumer consumer = new Consumer(clientId);
ResourceOwnerGrant grant = new ResourceOwnerGrant(username, password);
ClientAccessToken initial = OAuthClientUtils.getAccessToken(tokenUri, consumer, grant, true);
BearerAuthSupplier supplier = new BearerAuthSupplier();
supplier.setAccessToken(initial.getTokenKey());
supplier.setRefreshToken(initial.getRefreshToken());
supplier.setConsumer(consumer);
supplier.setAccessTokenServiceUri(tokenUri);
HTTPConduitConfigurer httpConduitConfigurer = new HTTPConduitConfigurer() {
#Override
public void configure(String name, String address, HTTPConduit c) {
c.setAuthSupplier(supplier);
}
};
Bus bus = BusFactory.getThreadDefaultBus();
bus.setExtension(httpConduitConfigurer, HTTPConduitConfigurer.class);
URI apiUri = new URI("http://localhost:8080/services/");
RestClientBuilder client = new CxfTypeSafeClientBuilder().baseUri(apiUri);
IDemoService service = client.build(IDemoService.class);
for (int i = 0; i < 200; i++) {
System.out.println("client: " + new Date() + " " + service.test());
Thread.sleep(5 * 60 * 1000);
}
Instead of login in with username and password (ResourceOwnerGrant) also possible to use client credentials with ClientCredentialsGrant.
ClientCredentialsGrant grant = new ClientCredentialsGrant();
grant.setClientId(clientId);
grant.setClientSecret(clientSecret);
We are trying to connect to webservice (from Java) that has ADFS SAML authentication.
All the examples I have seen, use Basic Authentication over HTTPS. (I am just using HttpsURLConnection to make a request for now, not using anything like Axis or JAX-WS)
I am not sure how to approach ADFS SAML authentication. Here's what I understand so far (don't know much about SAML):
I make one request, pass username/password and get the
authentication token back
Save the authentication token
Pass the token as some SOAP attribute in my calls where I invoke an
actual operation on the webservice
No idea under which attribute would I put this authentication token though
Is my above approach correct? If so, is there some library that I can use that does all this?
If not how can I go about doing this manually?
Please let me know if there are other or better ways of going about this.
If you are trying to build native app then can use below code. i has tried to use power bi rest apis. once you gets token you can use that in api calls.
public class PublicClient {
private final static String AUTHORITY = "https://login.microsoftonline.com/common";
private final static String CLIENT_ID = "XXXX-xxxx-xxx-xxx-xxxX";
private final static String RESOURCE = "https://analysis.windows.net/powerbi/api";
public static void main(String args[]) throws Exception {
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
System.out.print("Enter username: ");
String username = br.readLine();
System.out.print("Enter password: ");
String password = br.readLine();
AuthenticationResult result = getAccessTokenFromUserCredentials(
username, password);
System.out.println("Access Token - " + result.getAccessToken());
System.out.println("Refresh Token - " + result.getRefreshToken());
System.out.println("ID Token Expires on - " + result.getExpiresOn());
}
}
private static AuthenticationResult getAccessTokenFromUserCredentials(
String username, String password) throws Exception {
AuthenticationContext context = null;
AuthenticationResult result = null;
ExecutorService service = null;
try {
service = Executors.newFixedThreadPool(1);
context = new AuthenticationContext(AUTHORITY, false, service);
Future<AuthenticationResult> future = context.acquireToken(
RESOURCE, CLIENT_ID, username, password, null);
result = future.get();
} finally {
service.shutdown();
}
if (result == null) {
throw new ServiceUnavailableException(
"authentication result was null");
}
return result;
}
}
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
Here I want to get all contacts mail id of a person.
This code is redirecting to google site and after getting token and varifier it is returning status code and body which is printing on console.
I want to display response.getBody()(all maial contacts of a person) in jsp page.
How to do this?
public class googleOaoth extends ActionSupport {
private static final String NETWORK_NAME = "Google";
private static final String AUTHORIZE_URL = "https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token=";
private static final String PROTECTED_RESOURCE_URL = "https://www.google.com/m8/feeds/contacts/default/full";
private static final String SCOPE = "https://www.google.com/m8/feeds";
OAuthService service = new ServiceBuilder().provider(GoogleApi.class).apiKey("www.mysite").apiSecret("****").scope(SCOPE).callback("http://mysite/mypage").build();
Token requestToken;
private String url;
private String oauth_verifier;
private String oauth_token;
public String getOauth_verifier() {
return oauth_verifier;
}
public Token getRequestToken() {
return requestToken;
}
public void setRequestToken(Token requestToken) {
this.requestToken = requestToken;
}
public void setOauth_verifier(String oauth_verifier) {
this.oauth_verifier = oauth_verifier;
}
Map session = ActionContext.getContext().getSession();
//method which redirect to google page
public String LoginToGoogle() {
System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
System.out.println();
// Obtain the Request Token
System.out.println("Fetching the Request Token...");
setRequestToken(service.getRequestToken());
System.out.println("Got the Request Token!");
System.out.println("(if your curious it looks like this: " + getRequestToken() + " )");
System.out.println();
session.put("googleAccessToken", getRequestToken());
System.out.println("Now go and authorize Scribe here:");
setUrl(AUTHORIZE_URL + getRequestToken().getToken());
System.out.println(AUTHORIZE_URL + getRequestToken().getToken());
return "redirect";
}
//after getting varification code this method will show body and res_code
public String acceptToken() {
System.out.println("And paste the verifier here");
System.out.print(">>");
Verifier verifier = new Verifier(getOauth_verifier());
System.out.println();
// Trade the Request Token and Verfier for the Access Token
System.out.println("Trading the Request Token for an Access Token...");
//System.out.println("varifier : " + getOauth_verifier());
// System.out.println("token :" + getOauth_token());
//requestToken = service.getRequestToken();
setRequestToken((Token) session.get("googleAccessToken"));
System.out.println("token " + getRequestToken());
Token accessToken = service.getAccessToken(getRequestToken(), verifier);//requestToken
System.out.println("Got the Access Token!");
System.out.println("(if your curious it looks like this: " + accessToken + " )");
System.out.println();
// Now let's go and ask for a protected resource!
System.out.println("Now we're going to access a protected resource...");
OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
service.signRequest(accessToken, request);
request.addHeader("GData-Version", "3.0");
Response response = request.send();
System.out.println("Got it! Lets see what we found...");
System.out.println();
System.out.println(response.getCode());
System.out.println(response.getBody());
System.out.println();
System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
return SUCCESS;
}
Inside your action method create variable (e.g. respBody) with public getters/setters and assign response body to it.
respBody = response.getBody();
Then in JSP you can show it using <s:property> tag.
<s:property value="respBody"/>
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.