Skip to content

Commit

Permalink
review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Remek Zajac# committed Apr 29, 2017
1 parent 5484796 commit 7cd169a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 32 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Login on iOS takes the user to a [SafariViewController](https://developer.apple.
### Android
To configure Android, [generate a configuration file here](https://developers.google.com/mobile/add?platform=android&cntapi=signin). Once Google Sign-In is enabled Google will automatically create necessary credentials in Developer Console. There is no need to add the generated google-services.json file into your cordova project.

Make sure you execute the `keytool` steps as explained [here](https://developers.google.com/android/guides/client-auth) or authentication will fail.
Make sure you execute the `keytool` steps as explained [here](https://developers.google.com/drive/android/auth) or authentication will fail (do this for both release and debug keystores).

IMPORTANT:
* The step above, about `keytool`, show 2 types of certificate fingerprints, the **Release** and the **Debug**, when generating the configuration file, it's better to use the **Debug** certificate fingerprint, after that, you have to go on [Google Credentials Manager](https://console.developers.google.com/apis/credentials), and manually create a credential for **OAuth2 client** with your **Release** certificate fingerprint. This is necessary to your application work on both Development and Production releases.
Expand Down Expand Up @@ -148,7 +148,7 @@ function deviceReady() {

The login function walks the user through the Google Auth process. All parameters are optional, however there are a few caveats.

To get an `idToken` on Android, you ***must*** pass in your `webClientId`. On iOS, the `idToken` is included in the sign in result by default.
To get an `idToken` on Android, you ***must*** pass in your `webClientId` (a frequent mistake is to supply Android Client ID). On iOS, the `idToken` is included in the sign in result by default.

To get a `serverAuthCode`, you must pass in your `webClientId` _and_ set `offline` to true. If offline is true, but no webClientId is provided, the `serverAuthCode` will _**NOT**_ be requested.

Expand Down Expand Up @@ -183,6 +183,7 @@ The success callback (second argument) gets a JSON object with the following con
obj.imageUrl // 'http://link-to-my-profilepic.google.com'
obj.idToken // idToken that can be exchanged to verify user identity.
obj.serverAuthCode // Auth code that can be exchanged for an access token and refresh token for offline access
obj.accessToken // OAuth2 access token
```

Additional user information is available by use case. Add the scopes needed to the scopes option then return the info to the result object being created in the `handleSignInResult` and `didSignInForUser` functions on Android and iOS, respectively.
Expand Down
1 change: 0 additions & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@

<framework src="com.google.android.gms:play-services-auth:+" />
<framework src="com.google.android.gms:play-services-identity:+" />
<framework src="com.squareup.okhttp3:okhttp:3.3.1" />

<config-file target="res/xml/config.xml" parent="/*">
<feature name="GooglePlus">
Expand Down
72 changes: 43 additions & 29 deletions src/android/GooglePlus.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import android.content.pm.Signature;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
* Originally written by Eddy Verbruggen (http://github.com/EddyVerbruggen/cordova-plugin-googleplus)
* Forked/Duplicated and Modified by PointSource, LLC, 2016.
Expand All @@ -49,10 +51,10 @@ public class GooglePlus extends CordovaPlugin implements GoogleApiClient.OnConne
public static final String ACTION_DISCONNECT = "disconnect";
public static final String ACTION_GET_SIGNING_CERTIFICATE_FINGERPRINT = "getSigningCertificateFingerprint";

private final static String KAccess_Token = "access_token";
private final static String KTokenExpires = "expires";

private final static String KVerifyTokenUrl = "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=";
private final static String FIELD_ACCESS_TOKEN = "accessToken";
private final static String FIELD_TOKEN_EXPIRES = "expires";
private final static String FIELD_TOKEN_EXPIRES_IN = "expires_in";
private final static String VERIFY_TOKEN_URL = "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=";

//String options/config object names passed in to login and trySilentLogin
public static final String ARGUMENT_WEB_CLIENT_ID = "webClientId";
Expand Down Expand Up @@ -343,8 +345,9 @@ protected Void doInBackground(Void... params) {
JSONObject accessTokenBundle = getAuthToken(
cordova.getActivity(), acct.getAccount(), true
);
result.put(KAccess_Token, accessTokenBundle.get(KAccess_Token));
result.put(KTokenExpires, accessTokenBundle.get(KTokenExpires));
result.put(FIELD_ACCESS_TOKEN, accessTokenBundle.get(FIELD_ACCESS_TOKEN));
result.put(FIELD_TOKEN_EXPIRES, accessTokenBundle.get(FIELD_TOKEN_EXPIRES));
result.put(FIELD_TOKEN_EXPIRES_IN, accessTokenBundle.get(FIELD_TOKEN_EXPIRES_IN));
result.put("email", acct.getEmail());
result.put("idToken", acct.getIdToken());
result.put("serverAuthCode", acct.getServerAuthCode());
Expand Down Expand Up @@ -413,32 +416,43 @@ private JSONObject getAuthToken(Activity activity, Account account, boolean retr
}

private JSONObject verifyToken(String authToken) throws IOException, JSONException {
OkHttpClient client = client = new OkHttpClient.Builder().build();
Request request = new Request.Builder()
.url(KVerifyTokenUrl+authToken)
.get().build();
Response response = client.newCall(request).execute();
/* expecting:
{
"issued_to": "608941808256-43vtfndets79kf5hac8ieujto8837660.apps.googleusercontent.com",
"audience": "608941808256-43vtfndets79kf5hac8ieujto8837660.apps.googleusercontent.com",
"user_id": "107046534809469736555",
"scope": "https://www.googleapis.com/auth/userinfo.profile",
"expires_in": 3595,
"access_type": "offline"
}*/

String stringResponse = response.body().string();
URL url = new URL(VERIFY_TOKEN_URL+authToken);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setInstanceFollowRedirects(true);
String stringResponse = fromStream(
new BufferedInputStream(urlConnection.getInputStream())
);
/* expecting:
{
"issued_to": "608941808256-43vtfndets79kf5hac8ieujto8837660.apps.googleusercontent.com",
"audience": "608941808256-43vtfndets79kf5hac8ieujto8837660.apps.googleusercontent.com",
"user_id": "107046534809469736555",
"scope": "https://www.googleapis.com/auth/userinfo.profile",
"expires_in": 3595,
"access_type": "offline"
}*/

Log.d("AuthenticatedBackend", "token: " + authToken + ", verification: " + stringResponse);
JSONObject jsonResponse = new JSONObject(
stringResponse
);
int expires_in = jsonResponse.getInt("expires_in");
int expires_in = jsonResponse.getInt(FIELD_TOKEN_EXPIRES_IN);
if (expires_in < KAssumeStaleTokenSec) {
throw new IOException("Auth token soon expiring.");
}
jsonResponse.put(KAccess_Token, authToken);
jsonResponse.put(KTokenExpires, expires_in + (System.currentTimeMillis()/1000));
jsonResponse.put(FIELD_ACCESS_TOKEN, authToken);
jsonResponse.put(FIELD_TOKEN_EXPIRES, expires_in + (System.currentTimeMillis()/1000));
return jsonResponse;
}

public static String fromStream(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
reader.close();
return sb.toString();
}
}

0 comments on commit 7cd169a

Please sign in to comment.