Skip to content

Instantly share code, notes, and snippets.

@gkhays
Last active August 29, 2015 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gkhays/7d65bc62bf15121187b5 to your computer and use it in GitHub Desktop.
Save gkhays/7d65bc62bf15121187b5 to your computer and use it in GitHub Desktop.
Working with Google APIs
clientId=Enter Client ID
package com.netiq;
import java.awt.Desktop;
import java.awt.Desktop.Action;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Properties;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
public class GoogleAuthCode {
public static final String APPLICATION_JSON = "application/json";
public static final String AUTHORIZATION = "Authorization";
public static final String CONTENT_TYPE = "Content-Type";
public static final String ACCOUNT_CHOOSER_URL = "https://accounts.google.com/AccountChooser?service=lso&continue=";
public static final String REDIRECT_URI = "http://localhost/Callback";
public static final String OAUTH_URL = "https://accounts.google.com/o/oauth2/auth?";
public static final String SCOPE = "https://www.googleapis.com/auth/admin.directory.user";
private static String _clientId = null;
/**
* <pre>
GET https://accounts.google.com/o/oauth2/auth?
scope=https://www.googleapis.com/auth/admin.directory.user&
redirect_uri=https://localhost/Callback&
response_type=code&
client_id=430723156037-c3149idj1vhnqaotri5o5qem9prmm1hd.apps.googleusercontent.com&
access_type=offline
* </pre>
* @param redirectUri
* @return
* @throws UnsupportedEncodingException
*/
private static String getAuthUri(String redirectUri)
throws UnsupportedEncodingException {
String responseType = "code";
String accessType = "offline";
StringBuilder uriBuilder = new StringBuilder(OAUTH_URL);
uriBuilder.append("response_type=").append(responseType).append("&");
uriBuilder.append("scope=").append(URLEncoder.encode(SCOPE, "UTF-8"))
.append("&");
uriBuilder.append("redirect_uri=")
.append(URLEncoder.encode(redirectUri, "UTF-8")).append("&");
uriBuilder.append("client_id=").append(_clientId).append("&");
uriBuilder.append("accessType=").append(accessType);
return uriBuilder.toString();
}
private static void getProperties() throws IOException {
Properties prop = loadPropertiesAsResource();
_clientId = prop.getProperty("clientId");
}
private static void invokeBrowser(String url) throws IOException {
if (Desktop.isDesktopSupported()) {
Desktop deskTop = Desktop.getDesktop();
if (deskTop.isSupported(Action.BROWSE)) {
System.out.println("Attempting to browse to " + url + " ...");
deskTop.browse(URI.create(url));
}
}
}
/**
* @see <a
* href="http://stackoverflow.com/questions/333363/loading-a-properties-file-from-java-package">Loading
* a properties file from Java package</a>
* @return
* @throws IOException
*/
private static Properties loadPropertiesAsResource() throws IOException {
Properties prop = new Properties();
InputStream in = GoogleAuthCode.class
.getResourceAsStream("client.properties");
prop.load(in);
in.close();
return prop;
}
/**
* Authenticate to Google Apps using OAuth 2.
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
getProperties();
// Google will call me back at the redirect URL. Set up a listener.
LocalServerReceiver receiver = new LocalServerReceiver();
String redirectUri = receiver.getRedirectUri();
System.out.println("Local receiver listening on port "
+ receiver.getPort());
// Make sure to grant the token as an admin user. In my case,
// ghays@accessreview.net.
System.out.println("(1) Request authentication using OAuth 2.");
String authUri = getAuthUri(redirectUri);
System.out.println("Making request to authorization URI: "
+ authUri.toString());
System.out.println("Redirect URI: " + redirectUri);
// (1) Authorize
Client client = Client.create();
WebResource wr = client.resource(authUri);
ClientResponse response = wr.header(CONTENT_TYPE, APPLICATION_JSON)
.get(ClientResponse.class);
int status = response.getStatus();
System.out.println("HTTP Response Status: " + status);
// Launch the Google Account Chooser. Of the form:
// https://accounts.google.com/AccountChooser?service=lso&continue=[authorizeurl]
//
// See http://stackoverflow.com/questions/14384354/force-google-account-chooser
String chooserUri = ACCOUNT_CHOOSER_URL + URLEncoder.encode(authUri, "UTF-8");
invokeBrowser(chooserUri);
// Receive authorization code.
System.out.println("Waiting for the code...");
String code = receiver.waitForCode();
receiver.stop(); // TODO - Put this in a try/finally.
System.out.println("Google authorization code: " + code);
// TODO - Can we persist the authorization code?
}
/**
* <pre>
2015-04-30 16:57:08.322:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
2015-04-30 16:57:08.323:INFO::jetty-6.1.26
2015-04-30 16:57:08.346:INFO::Started SocketConnector@localhost:14975
Local receiver listening on port 14975
(1) Request authentication using OAuth 2.
Making request to authorization URI: https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.user&redirect_uri=http%3A%2F%2Flocalhost%3A14975%2FCallback&client_id=430723156037-c3149idj1vhnqaotri5o5qem9prmm1hd.apps.googleusercontent.com&accessType=offline
Redirect URI: http://localhost:14975/Callback
HTTP Response Status: 200
Attempting to browse to https://accounts.google.com/AccountChooser?service=lso&continue=https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Fauth%3Fresponse_type%3Dcode%26scope%3Dhttps%253A%252F%252Fwww.googleapis.com%252Fauth%252Fadmin.directory.user%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A14975%252FCallback%26client_id%3D430723156037-c3149idj1vhnqaotri5o5qem9prmm1hd.apps.googleusercontent.com%26accessType%3Doffline ...
Waiting for the code...
2015-04-30 16:57:15.034:INFO::Stopped SocketConnector@localhost:14975
Google authorization code: 4/5BIHWBuGQWLoOjjcrSMR8L8GnySSea1q9QkNBHl0gUU.AkyzX7Xet3UaPm8kb2vw2M0D2qoYmgI
* </pre>
*/
}
package org.gkh.test;
import java.awt.Desktop;
import java.awt.Desktop.Action;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Properties;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
public class GoogleToken {
public static final String APPLICATION_ENCODED = "application/x-www-form-urlencoded";
public static final String APPLICATION_JSON = "application/json";
public static final String AUTHORIZATION = "Authorization";
public static final String CONTENT_TYPE = "Content-Type";
public static final String ACCOUNT_CHOOSER_URL = "https://accounts.google.com/AccountChooser?service=lso&continue=";
public static final String REDIRECT_URI = "http://localhost/Callback";
public static final String OAUTH_URL = "https://accounts.google.com/o/oauth2/auth?";
public static final String SCOPE = "https://www.googleapis.com/auth/admin.directory.user";
private static String _clientId = null;
private String _redirectUri = null;
private String _scope = null;
private LocalServerReceiver _receiver = null;
private Client _client = null;
private WebResource _webResource = null;
private ClientResponse _response = null;
// Discussions on whether or not to throw an exception in a constructor. The
// guidance is to not produce a partially constructed object that may be
// subclassed and abused.
// http://stackoverflow.com/questions/6086334/is-it-good-practice-to-make-the-constructor-throw-an-exception
// http://stackoverflow.com/questions/1371369/can-constructors-throw-exceptions-in-java/1373419#1373419
// http://stackoverflow.com/questions/7532078/java-exception-in-constructors-problematic-or-not
// http://www.oracle.com/technetwork/java/seccodeguide-139067.html#7
public GoogleToken(String scope, String propertyFileName) throws IOException {
_scope = scope;
init(propertyFileName);
}
public GoogleToken() throws IOException {
_scope = SCOPE;
init(null);
}
public String connect() throws IOException {
String authUri = getAuthUri();
System.out.println("Making request to authorization URI: "
+ authUri.toString());
System.out.println("Redirect URI: " + _redirectUri);
// (1) Authorize
_client = Client.create();
_webResource = _client.resource(authUri);
_response = _webResource.header(CONTENT_TYPE, APPLICATION_JSON).get(
ClientResponse.class);
int status = _response.getStatus();
System.out.println("HTTP Response Status: " + status);
String code = null;
if (status == 200) {
// Launch the Google Account Chooser. Of the form:
// https://accounts.google.com/AccountChooser?service=lso&continue=[authorizeurl]
// See http://stackoverflow.com/questions/14384354/force-google-account-chooser
String chooserUri = ACCOUNT_CHOOSER_URL
+ URLEncoder.encode(authUri, "UTF-8");
invokeBrowser(chooserUri);
// Receive authorization code.
System.out.println("Waiting for the code...");
code = _receiver.waitForCode();
_receiver.stop(); // TODO - Put this in a try/finally.
System.out.println("Google authorization code: " + code);
}
// TODO - Can we persist the authorization code?
return code;
}
public JSONObject exchangeCodeForToken(String code) throws JSONException,
UnsupportedEncodingException {
String OAUTH_TOKEN_URL = "www.googleapis.com/oauth2/v3/token";
String clientSecret = "WA5hqvXVh8pnvjrbCbkHmCIC";
String tokenUrl = "https://" + OAUTH_TOKEN_URL;
StringBuilder payloadBuilder = new StringBuilder("code=").append(code);
payloadBuilder.append("&client_id=").append(_clientId);
payloadBuilder.append("&client_secret=").append(clientSecret);
payloadBuilder.append("&redirect_uri=").append(
URLEncoder.encode(_redirectUri, "UTF-8"));
payloadBuilder.append("&grant_type=").append("authorization_code");
payloadBuilder.append("&access_type=").append("offline");
System.out.println("(2) Exchange authorization code for a token.");
System.out.println("Making request to " + tokenUrl);
_webResource = _client.resource(tokenUrl);
_response = _webResource.header(CONTENT_TYPE, APPLICATION_ENCODED)
.entity(payloadBuilder.toString()).post(ClientResponse.class);
int status = _response.getStatus();
JSONObject jsonResponse = null;
if (status == 200) {
jsonResponse = _response.getEntity(JSONObject.class);
System.out.println("Response Status: " + status);
System.out.println("Token:\n" + jsonResponse.toString(2));
}
return jsonResponse;
}
/**
* <pre>
GET https://accounts.google.com/o/oauth2/auth?
scope=https://www.googleapis.com/auth/admin.directory.user&
redirect_uri=https://localhost/Callback&
response_type=code&
client_id=430723156037-c3149idj1vhnqaotri5o5qem9prmm1hd.apps.googleusercontent.com&
access_type=offline
* </pre>
* @return
* @throws UnsupportedEncodingException
*/
private String getAuthUri()
throws UnsupportedEncodingException {
String responseType = "code";
String accessType = "offline";
StringBuilder uriBuilder = new StringBuilder(OAUTH_URL);
uriBuilder.append("response_type=").append(responseType).append("&");
uriBuilder.append("scope=").append(URLEncoder.encode(SCOPE, "UTF-8"))
.append("&");
uriBuilder.append("redirect_uri=")
.append(URLEncoder.encode(_redirectUri, "UTF-8")).append("&");
uriBuilder.append("client_id=").append(_clientId).append("&");
uriBuilder.append("accessType=").append(accessType);
return uriBuilder.toString();
}
private void getProperties(String fileName) throws IOException {
Properties prop = null;
if (fileName == null) {
prop = loadPropertiesAsResource();
} else {
prop = loadPropertiesAsResource(fileName);
}
_clientId = prop.getProperty("clientId");
}
private void init(String pfn) throws IOException {
if (pfn != null) {
getProperties(pfn);
} else {
getProperties(null);
}
// Google will call me back at the redirect URL. Set up a listener.
_receiver = new LocalServerReceiver();
_redirectUri = _receiver.getRedirectUri();
System.out.println("Local receiver listening on port "
+ _receiver.getPort());
// Make sure to grant the token as an admin user. In my case,
// ghays@accessreview.net.
System.out.println("(1) Request authentication using OAuth 2.");
}
private void invokeBrowser(String url) throws IOException {
if (Desktop.isDesktopSupported()) {
Desktop deskTop = Desktop.getDesktop();
if (deskTop.isSupported(Action.BROWSE)) {
System.out.println("Attempting to browse to " + url + " ...");
deskTop.browse(URI.create(url));
}
}
}
/**
* @see <a
* href="http://stackoverflow.com/questions/333363/loading-a-properties-file-from-java-package">Loading
* a properties file from Java package</a>
* @return
* @throws IOException
*/
private Properties loadPropertiesAsResource() throws IOException {
Properties prop = new Properties();
InputStream in = GoogleToken.class
.getResourceAsStream("client.properties");
prop.load(in);
in.close();
return prop;
}
private Properties loadPropertiesAsResource(String name) throws IOException {
Properties prop = new Properties();
InputStream in = GoogleToken.class
.getResourceAsStream(name);
prop.load(in);
in.close();
return prop;
}
/**
* Authenticate to Google Apps using OAuth 2.
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
GoogleToken authCode = new GoogleToken();
authCode.connect();
}
/**
* This is what the Google account chooser URI looks like.
*
* <pre>
https://accounts.google.com/AccountChooser?service=lso&continue=https%3A%2F%2Faccounts.google.com%2Fo
%2Foauth2%2Fauth%3Fresponse_type%3Dcode%26scope%3Dhttps%3A%2F%2Fwww.googleapis.com%2Fauth
%2Fadmin.directory.user%26redirect_uri%3Dhttp%3A%2F%2Flocalhost%3A14539%2FCallback%26client_id
%3D430723156037-c3149idj1vhnqaotri5o5qem9prmm1hd.apps.googleusercontent.com%26accessType%3Doffline%26hl
%3Den%26from_login%3D1%26as%3D-c695002fd5825cf&btmpl=authsub&hl=en
* </pre>
*/
/**
* <pre>
2015-04-30 16:57:08.322:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
2015-04-30 16:57:08.323:INFO::jetty-6.1.26
2015-04-30 16:57:08.346:INFO::Started SocketConnector@localhost:14975
Local receiver listening on port 14975
(1) Request authentication using OAuth 2.
Making request to authorization URI: https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.user&redirect_uri=http%3A%2F%2Flocalhost%3A14975%2FCallback&client_id=430723156037-c3149idj1vhnqaotri5o5qem9prmm1hd.apps.googleusercontent.com&accessType=offline
Redirect URI: http://localhost:14975/Callback
HTTP Response Status: 200
Attempting to browse to https://accounts.google.com/AccountChooser?service=lso&continue=https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Fauth%3Fresponse_type%3Dcode%26scope%3Dhttps%253A%252F%252Fwww.googleapis.com%252Fauth%252Fadmin.directory.user%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A14975%252FCallback%26client_id%3D430723156037-c3149idj1vhnqaotri5o5qem9prmm1hd.apps.googleusercontent.com%26accessType%3Doffline ...
Waiting for the code...
2015-04-30 16:57:15.034:INFO::Stopped SocketConnector@localhost:14975
Google authorization code: 4/5BIHWBuGQWLoOjjcrSMR8L8GnySSea1q9QkNBHl0gUU.AkyzX7Xet3UaPm8kb2vw2M0D2qoYmgI
* </pre>
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment