Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 553
fadedbee Avatar asked Nov 03 '15 05:11

fadedbee


1 Answers

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:

  1. User authorizes and a token is acquired
  2. 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:

  1. User authorizes and the app gets a token
  2. 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)).
  3. 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.
  4. 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": "[email protected]",
 "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

like image 76
Ralphilius Avatar answered Oct 14 '22 00:10

Ralphilius