How to create a parse _User account from a Android Google token?

android, oauth-2.0, parse-platform

Solution

Note: This answer does not apply to the Open Source Parse Server, as it uses revocable sessions only. Check out parse-server/issues/1392 for further update

Update (Jan-2016):

You need to turn off Revocable Session in order to call `getSessionToken` on `Parse.User`. Go to App Settings >> Users >> Turn off Require revocable sessions. This is not new in 2016, but at the time of giving answer, the author did not know of this change.

I will break into 2 cases for easier to follow: New User and Returning User.

1. New User

The flow is as below:

- User authorizes and a token is acquired

- We create a new user with a random password

You can create a ParseUser using following code inside the `newChooseAccountIntent()` method that return email.

ParseUser user = new ParseUser();
user.setUsername(mEmail);
user.setPassword(randomPassword);
user.setEmail(mEmail);
user.signUpInBackground(new SignUpCallback() {
  public void done(ParseException e) {
    if (e == null) {
      // Hooray! Let them use the app now.
    } else {
      // Sign up didn't succeed. Look at the ParseException
      // to figure out what went wrong
    }
  }
});

2. Returning User

This is the where most of people stuck, as I researched over the Internet. The flow is as below:

- User authorizes and the app gets a token

- We pass this token to Cloud Code to validate. We need to check if this token is signed by Google and if it is meant for us (android-developers (2013)).

- After you can verify that the token is valid, you can query for the user in Cloud Code using `Parse.Cloud.useMasterKey()` method and return the session key by using `getSessionToken()` method on the query result.

- Use the session key to save login state on disk by calling `becomeInBackground` method

To validate the token, you can send `Parse.Cloud.httprequest` to this endpoint: `https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=`. This is instructed in Google Identity Documentation. You will receive data as below:

{
 "iss": "https://accounts.google.com",
 "sub": "110169484474386276334",
 "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "email": "billd1600@gmail.com",
 "at_hash": "X_B3Z3Fi4udZ2mf75RWo3w",
 "email_verified": "true",
 "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "iat": "1433978353",
 "exp": "1433981953"
}

Things need to compare are "aud", "azp" and "email" which are translated as audience, authorized party and email.

To query for the current user on Cloud Code:

var query = new Parse.Query(Parse.User);
query.equalTo("email",mEmail);
query.first({
  success: function(user) {
    // Use user..getSessionToken() to get a session token
  },
  error: function(user, error) {
    //
  },
  useMasterKey: true
});

Note: Make sure you have following scope so that the email will show up when you check on Cloud Code: `https://www.googleapis.com/auth/plus.profile.emails.read`

Problem

I've found some fragments of useful information. http://blog.parse.com/announcements/bring-your-own-login/ shows me how to login an Android app once I have a Parse token. I can successfully obtain a Google token for a phone's Google account. https://developers.google.com/android/guides/http-auth ``` /** * Gets an authentication token from Google and handles any * GoogleAuthException that may occur. */ protected String fetchToken() throws IOException { try { return GoogleAuthUtil.getToken(mActivity, mEmail, mScope); } catch (UserRecoverableAuthException userRecoverableException) { // GooglePlayServices.apk is either old, disabled, or not present // so we need to show the user some UI in the activity to recover. mActivity.handleGoogleException(userRecoverableException); } catch (GoogleAuthException fatalException) { // Some other type of unrecoverable exception has occurred. // Report and log the error as appropriate for your app. } return null; } ``` How can get Parse to use a Google token to create a Parse token? I assume that this will involve writing some Cloud Code, but I'm not clear on what that Cloud Code should do. I think it needs to create or find a new _User for the Google token and return the Parse token. Are there any Parse Cloud Code examples of how to handle Google Android login/signup, or examples of anything other than Faceboook/Twitter?

Original source