001    package com.khubla.pragmatach.plugin.google;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    
006    import net.sf.json.JSONObject;
007    import net.sf.json.JSONSerializer;
008    
009    import org.apache.http.HttpEntity;
010    import org.apache.http.HttpResponse;
011    import org.apache.http.NameValuePair;
012    import org.apache.http.client.HttpClient;
013    import org.apache.http.client.entity.UrlEncodedFormEntity;
014    import org.apache.http.client.methods.HttpGet;
015    import org.apache.http.client.methods.HttpPost;
016    import org.apache.http.impl.client.BasicResponseHandler;
017    import org.apache.http.impl.client.DefaultHttpClient;
018    import org.apache.http.message.BasicNameValuePair;
019    import org.apache.http.protocol.HTTP;
020    import org.apache.http.util.EntityUtils;
021    
022    import com.khubla.pragmatach.framework.api.PragmatachException;
023    import com.khubla.pragmatach.framework.api.Response;
024    import com.khubla.pragmatach.framework.application.Application;
025    import com.khubla.pragmatach.plugin.freemarker.FreemarkerController;
026    
027    /**
028     * @author tome
029     *         <p>
030     *         https://developers.google.com/accounts/docs/OAuth2WebServer
031     *         </p>
032     */
033    public class GoogleLoginController extends FreemarkerController {
034       /**
035        * code
036        */
037       private String code;
038       /**
039        * state
040        */
041       private String state;
042       /**
043        * google client ID
044        */
045       private String clientid;
046       /**
047        * google client secret
048        */
049       private String clientsecret;
050       /**
051        * redirect URL
052        */
053       private final String redirectURL;
054       /**
055        * access token
056        */
057       private String accessToken;
058       /**
059        * scopes to ask for
060        */
061       private static final String[] SCOPES = { "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email" };
062       /**
063        * Google user id
064        */
065       private String id;
066       /**
067        * Google user name
068        */
069       private String name;
070       /**
071        * Google user given name
072        */
073       private String given_name;
074       /**
075        * Google user family name
076        */
077       private String family_name;
078       /**
079        * Google email
080        */
081       private String email;
082    
083       /**
084        * ctor
085        */
086       public GoogleLoginController(String redirectURL) throws PragmatachException {
087          this.redirectURL = redirectURL;
088          clientid = Application.getConfiguration().getParameter("google.clientid");
089          clientsecret = Application.getConfiguration().getParameter("google.clientsecret");
090       }
091    
092       public Response doLogin() throws PragmatachException {
093          final String sessionID = getRequest().getSession().getId();
094          if (sessionID != getRequest().getSession().getId()) {
095             throw new PragmatachException("CSRF Exception");
096          }
097          accessToken = getGoogleAccessToken(code);
098          getUserInfo(accessToken);
099          return super.render();
100       }
101    
102       public String getAccessToken() {
103          return accessToken;
104       }
105    
106       public String getClientid() {
107          return clientid;
108       }
109    
110       public String getClientsecret() {
111          return clientsecret;
112       }
113    
114       public String getCode() {
115          return code;
116       }
117    
118       public String getEmail() {
119          return email;
120       }
121    
122       public String getFamily_name() {
123          return family_name;
124       }
125    
126       public String getGiven_name() {
127          return given_name;
128       }
129    
130       /**
131        * request a token from the Google code
132        */
133       @SuppressWarnings("deprecation")
134       private String getGoogleAccessToken(String googleCode) throws PragmatachException {
135          final String token = null;
136          if ((googleCode != null) && !"".equals(googleCode)) {
137             final String redirectUrl = getApplicationURL() + "/plugins/google/dologin";
138             final String newUrl = "https://accounts.google.com/o/oauth2/token?client_id=" + clientid + "&redirect_uri=" + redirectUrl + "&client_secret=" + clientsecret + "&code=" + googleCode;
139             final HttpClient httpclient = new DefaultHttpClient();
140             try {
141                final HttpPost httppost = new HttpPost(newUrl);
142                final List<NameValuePair> nvps = new ArrayList<NameValuePair>();
143                nvps.add(new BasicNameValuePair("code", code));
144                nvps.add(new BasicNameValuePair("client_id", clientid));
145                nvps.add(new BasicNameValuePair("client_secret", clientsecret));
146                nvps.add(new BasicNameValuePair("redirect_uri", redirectUrl));
147                nvps.add(new BasicNameValuePair("grant_type", "authorization_code"));
148                httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
149                final HttpResponse httpResponse = httpclient.execute(httppost);
150                if (httpResponse.getStatusLine().getStatusCode() == 200) {
151                   final HttpEntity httpEntity = httpResponse.getEntity();
152                   final String jsonBody = EntityUtils.toString(httpEntity);
153                   final JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(jsonBody);
154                   final String access_token = jsonObject.getString("access_token");
155                   jsonObject.getString("expires_in");
156                   jsonObject.getString("token_type");
157                   return access_token;
158                } else {
159                   System.out.println(httpResponse.getStatusLine().getReasonPhrase());
160                }
161             } catch (final Exception e) {
162                throw new PragmatachException("Exception in getGoogleAccessToken", e);
163             } finally {
164                httpclient.getConnectionManager().shutdown();
165             }
166          }
167          return token;
168       }
169    
170       /**
171        * get the auth URL to POST to
172        */
173       public String getGoogleAuthURL() {
174          final String sessionId = getRequest().getSession().getId();
175          final String redirectUrl = getApplicationURL() + "/plugins/google/dologin";
176          final String returnValue = "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=" + clientid + "&redirect_uri=" + redirectUrl + "&state=" + sessionId + "&scope="
177                + getScopes();
178          return returnValue;
179       }
180    
181       public String getId() {
182          return id;
183       }
184    
185       public String getName() {
186          return name;
187       }
188    
189       public String getRedirectURL() {
190          return redirectURL;
191       }
192    
193       private String getScopes() {
194          String ret = "";
195          for (final String s : SCOPES) {
196             ret += s + " ";
197          }
198          return ret;
199       }
200    
201       public String getState() {
202          return state;
203       }
204    
205       /**
206        * get the user info
207        */
208       private void getUserInfo(String accessToken) throws PragmatachException {
209          HttpClient httpclient = new DefaultHttpClient();
210          try {
211             final String newUrl = "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + accessToken;
212             httpclient = new DefaultHttpClient();
213             final HttpGet httpget = new HttpGet(newUrl);
214             final BasicResponseHandler responseHandler = new BasicResponseHandler();
215             final String responseBody = httpclient.execute(httpget, responseHandler);
216             final JSONObject json = (JSONObject) JSONSerializer.toJSON(responseBody);
217             id = json.getString("id");
218             name = json.getString("name");
219             given_name = json.getString("given_name");
220             family_name = json.getString("family_name");
221             email = json.getString("email");
222          } catch (final Exception e) {
223             throw new PragmatachException("Exception in getUserInfo", e);
224          } finally {
225             httpclient.getConnectionManager().shutdown();
226          }
227       }
228    
229       public void setAccessToken(String accessToken) {
230          this.accessToken = accessToken;
231       }
232    
233       public void setClientid(String clientid) {
234          this.clientid = clientid;
235       }
236    
237       public void setClientsecret(String clientsecret) {
238          this.clientsecret = clientsecret;
239       }
240    
241       public void setCode(String code) {
242          this.code = code;
243       }
244    
245       public void setEmail(String email) {
246          this.email = email;
247       }
248    
249       public void setFamily_name(String family_name) {
250          this.family_name = family_name;
251       }
252    
253       public void setGiven_name(String given_name) {
254          this.given_name = given_name;
255       }
256    
257       public void setId(String id) {
258          this.id = id;
259       }
260    
261       public void setName(String name) {
262          this.name = name;
263       }
264    
265       public void setState(String state) {
266          this.state = state;
267       }
268    }