- There are lot of samples, but they use OAuth1. This is more complex way and support will be turned off soon.
- I was looking for some framework or libraries to help me. Of course I found, but they were hard to understand and again OAuth1 related.
- Tell to Google what services you want to use in Google API console. From console you will get client_id, client_secret and redirect_uri parameters.
- Construct URL and show it to your application user. By clicking this link user will be forwarded to Google and he will need to allow to use resources your applications requires.
- After user allows (or not) he will be forwarded back to your page (redirect_uri you speified in step 1). If user allowed access you - will receive code as URL parameter.
- Exchange code to access_token.
- Start using resources you asked passing access_token.
Constructing URL:
public URI getLink() { List<NameValuePair> qparams = new ArrayList<NameValuePair>(); qparams.add(new BasicNameValuePair("client_id", "your client id from step 1")); qparams.add(new BasicNameValuePair("response_type", "code")); qparams.add(new BasicNameValuePair("redirect_uri", "it should the the same as you filled for Google (case sensitive)")); //param scope - here you tell Google what services your application wants to access. In this example I want to access Gmail, User email and User profile qparams.add(new BasicNameValuePair("scope", "https://mail.google.com/ https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile")); try { return URIUtils.createURI("https", "accounts.google.com", -1, "/o/oauth2/auth", URLEncodedUtils.format(qparams, "UTF-8"), null); } catch (URISyntaxException e) { log.error("Error creating URL", e); } return null; }
Exchanging code to access_token:
public Token getToken(String code) { try { Scheme httpsScheme = new Scheme("https", 443, new EasySSLSocketFactory()); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(httpsScheme); ClientConnectionManager cm = new BasicClientConnectionManager(schemeRegistry); HttpClient httpClient = new DefaultHttpClient(cm); List<NameValuePair> qparams = new ArrayList<NameValuePair>(); qparams.add(new BasicNameValuePair("code", code)); //The code google sent to application after user allowed access to his recources qparams.add(new BasicNameValuePair("client_id", "your client id from step 1")); qparams.add(new BasicNameValuePair("client_secret", "your client secret from step 1")); qparams.add(new BasicNameValuePair("redirect_uri", "your redirect uri from step 1")); qparams.add(new BasicNameValuePair("grant_type", "authorization_code")); HttpPost httppost = new HttpPost("https://accounts.google.com/o/oauth2/token"); httppost.setEntity(new UrlEncodedFormEntity(qparams)); log.debug("executing request to get token:" + httppost.getRequestLine()); HttpResponse response = httpClient.execute(httppost); HttpEntity entity = response.getEntity(); log.debug("response status:" + response.getStatusLine()); ContentType contentType = ContentType.getOrDefault(entity); if (contentType.getMimeType().equals("application/json")) { String responseStr = IOUtils.toString(entity.getContent()); log.debug("parsing json response:"+responseStr); return new Gson().fromJson(responseStr, Token.class); } EntityUtils.consume(entity); httppost.releaseConnection(); httpClient.getConnectionManager().shutdown(); } catch (Exception e) { log.error("Error retrieving token", e); } return null; } public class Token { String access_token; String token_type; Integer expires_in; Date requestedOn = new Date(); //TODO: you need to add getters and setters @Override public String toString() { return String.format("requested_on:%s,token_type:%s,expires_in:%d,access_token:%s", requestedOn, token_type, expires_in, access_token); } }
And finally - lets get User information:
public User getUserInfo(Token token) { try { Scheme httpsScheme = new Scheme("https", 443, new EasySSLSocketFactory()); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(httpsScheme); ClientConnectionManager cm = new BasicClientConnectionManager(schemeRegistry); HttpClient httpClient = new DefaultHttpClient(cm); HttpGet httpget = new HttpGet("https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + token.getAccess_token()); log.debug("executing request:" + httpget.getRequestLine()); HttpResponse response = httpClient.execute(httpget); HttpEntity entity = response.getEntity(); log.debug("response status:" + response.getStatusLine()); ContentType contentType = ContentType.getOrDefault(entity); if (contentType.getMimeType().equals("application/json")) { String responseStr = IOUtils.toString(entity.getContent()); log.debug("parsing json response:"+responseStr); return new Gson().fromJson(responseStr, User.class); } EntityUtils.consume(entity); httpget.releaseConnection(); httpClient.getConnectionManager().shutdown(); } catch (Exception e) { log.error("Error retrieving User", e); } return null; } public class User { String id; String email; String name; String picture; String gender; String locale; //TODO: you need to add getters and setters @Override public String toString() { return String.format("id:%s,name:%s,email:%s,gender:%d,locale:%s", id, name, email, gender, locale); } }
PS:
In my code I am using EasySSLSocketFactory which accepts all SSL certificates. This is OK for testing purpose, but you should definitely chance it in production.
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.conn.scheme.SchemeLayeredSocketFactory; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.security.SecureRandom; import java.security.cert.X509Certificate; public class EasySSLSocketFactory implements SchemeLayeredSocketFactory { private SSLContext sslcontext = null; private Log log = LogFactory.getLog(EasySSLSocketFactory.class); private static SSLContext createEasySSLContext() throws IOException { SSLContext context = null; try { context = SSLContext.getInstance("SSL"); context.init(null, new TrustManager[]{new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } }}, new SecureRandom()); } catch (Exception e) { throw new IOException(e.getMessage()); } return context; } private SSLContext getSSLContext() throws IOException { if (this.sslcontext == null) { this.sslcontext = createEasySSLContext(); } return this.sslcontext; } public Socket createLayeredSocket(Socket socket, String s, int i, HttpParams httpParams) throws IOException { log.debug("createLayeredSocket"); return getSSLContext().getSocketFactory().createSocket(); } public Socket createSocket(HttpParams httpParams) throws IOException { log.debug("createSocket"); log.debug(Thread.currentThread().getStackTrace()); return getSSLContext().getSocketFactory().createSocket(); } public Socket connectSocket(Socket sock, InetSocketAddress remoteAddress, InetSocketAddress localAddress, HttpParams params) throws IOException { int connTimeout = HttpConnectionParams.getConnectionTimeout(params); int soTimeout = HttpConnectionParams.getSoTimeout(params); SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket(params)); if (localAddress != null) { // we need to bind explicitly sslsock.bind(localAddress); } sslsock.connect(remoteAddress, connTimeout); sslsock.setSoTimeout(soTimeout); return sslsock; } public boolean isSecure(Socket socket) throws IllegalArgumentException { return true; } }
To make things easier here are my Maven dependencies:
<!-- Apache HTTP commons --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.2-beta1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.2-beta1</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>1.3.2</version> </dependency> <!-- GSon --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.1</version> </dependency>
No comments:
Post a Comment