22

I've been using Parse for 3 months in my android app. Now I want to add email login and social sign ons (Facebook and Google+) in the app. I have successfully added email and fb login and the user can connect both or either one of email or facebook and the app would recognise the user.

e.g. If I login through email, then connect facebook, use the app on another device, login via facebook, the app would know it's the same user and would be customised for me and would show my data. And email also works.

I have added Google+ sign-in for Android but I am not able to connect the user's Google+ credentials with the logged in user.

Parse Users table has an authData field which gets the facebook auth data and would get Twitter as well as both of these sign ons are baked into Parse SDKs.

What should be the best thing to do for Google+? I'm confused about the db design as well as how to connect the user who signed in with Google+?

What if the user just logs in via Google+? How do I make a Parse User and authenticate the user on Parse?

I'm comfortable with cloud code and Android and would really appreciate some sort of help/instructions just pushing me in the correct direction. I have never used OAuth2 and with Parse login for email and Social Sign ons, I don't think I should get into it. But let me know if I'm wrong.

Thanks!

Update: I have read a lot of questions on Parse Questions and have checked out the become method plenty of times (because I kept thinking I'm missing something after reading that). Check this question - I'm currently in the same situation.

I have:
1. Implemented Google+ sign in.
2. Got access token using GoogltAuthUtil.

Stuck with:
3. How to link currently signed in Parse user after the user signs in with Google+?
4. How to create a new Parse User if Google+ was the user's first (and only ) login choice?

Rahul Sainani
  • 2,875
  • 1
  • 28
  • 45
  • Have you solved somehow? – natario May 12 '15 at 20:54
  • I took an approach. Signed in on Google+ on Client and then on Parse in Cloud Code and then used the become on client with the session token of the user. – Rahul Sainani May 14 '15 at 18:04
  • Hi droidster, do u mind sharing it how u make it works? I've stucked for few days yet I still couldn't find the solution to enable G+ sign in in Parse – Cadrick Loh Jul 06 '15 at 07:45
  • Sorry about the late reply @CadrickLoh. I'm logging in the Google+ user on Client as mentioned in the google docs. And then I pass in the data to the cloud and create a new user on the cloud code and pass back the session token to the client so the Parse User (created on the cloud) is on logged in on the device. Unfortunately, I'm not able to use the new sessions feature in Parse with this method. – Rahul Sainani Jul 10 '15 at 12:17
  • Hi @droidster what google+data you saved in parse user?like something google access_token,id_token google plus id, please help i have problem on what kind of data needed to be save in parse to authenticate and validate it. – Cristiana Chavez Aug 26 '15 at 05:36
  • @Cristiana214 Sorry for the late reply. I missed this notification somehow. It doesn't matter what you save. I'm just saving user's basic data. After logging in the user on client, just create a parse user using cloud code and pass back the session id to client to login that parse user. Of course, the disadvantage of this method is that I'm using old sessions. Better look into a way to use new enhanced sessions. Hope this helps. – Rahul Sainani Sep 07 '15 at 10:22
  • @droidster I wonder if we can now create our own ParseWhateverUtils lib, like ParseFacebookUtils, using [logInWithInBackground(String authType, Map authData)](http://parse.com/docs/android/api/com/parse/ParseUser.html#logInWithInBackground(java.lang.String,%20java.util.Map)). It's not well documented neither, I supposed there is something to do server side to register authType. For now I get invalid sessions error, still working on it. Let us know if you have any clue. Thanks :) – frouo Oct 20 '15 at 13:34
  • @Frouo That's a good idea. I could maybe take out some time and work on it, but I can't commit, yet. Check out my comments above for the hack I've been using. The app's running with G+ login for months now. – Rahul Sainani Oct 29 '15 at 13:17

5 Answers5

7

This seems to be similar with How to create a parse _User account from a Android Google token?

Following is my answer in that thread:


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": "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

Community
  • 1
  • 1
Ralphilius
  • 1,696
  • 2
  • 15
  • 26
  • user.getSessionToken() returns null for me, even though i see the session object with a pointer to the user i am using. any idea? – r2DoesInc Apr 09 '16 at 01:35
  • @r2DoesInc please check original answer thread for frequently-updated answer. If you still use parse.com, you need to turn off Revocable Sessions so that it will work. – Ralphilius Apr 09 '16 at 13:16
  • Parse-server does not support revocable sessions. I needed to quert the Sessions for the user, and return the session token that way, – r2DoesInc Apr 09 '16 at 16:56
  • Yes, it's not supported. There is a ticket requesting that feature – Ralphilius Apr 09 '16 at 17:57
  • What if the session is deleted in the Parse DB and a user attempts to login with gmail. The session token would return null and they wont be able to login? – user1686342 Aug 10 '16 at 15:29
  • For parse-server, there should be an adapter that handle the login logic. You can follow the discussion here: https://github.com/ParsePlatform/parse-server/issues/1392 – Ralphilius Aug 10 '16 at 16:01
3

There's a question about this on Parse's questions. It's right here and I'm pretty sure it answers your questions.

https://parse.com/questions/google-plus

It links to the parse blog, that has some workarounds on this.

It says that you can add any login into ParseUser. You would be doing something like this:

Parse.User.become("session-token-here").then(function (user) {
// The current user is now set to user.
}, function (error) {
// The token could not be validated.
});

Another site where you should take a look: https://parse.com/tutorials/adding-third-party-authentication-to-your-web-app

This last one is official and has an example code

Gabriel Jensen
  • 4,052
  • 1
  • 14
  • 14
cristianorbs
  • 642
  • 3
  • 9
  • 16
  • I have gone through the link that's mentioned in Parse Questions and it is a rather vague blog post that doesn't answer many questions. Your second link is for web apps but this question is about Android. – Rahul Sainani Jan 23 '15 at 17:19
  • Hello, from where you get that "Session Token"? is it Google+ one or Parse's Session Token? If it is Parse's, how to get one? Could you answer it in an easy way to use that method ? Thanks in advance – Sai Jithendra Mar 20 '15 at 21:20
  • @SaiJithendra Hi. It's the Google+ one. The method become will link this token to your ParseUser. Although it will only work if you logged in the user on the server side.Otherwise, you should first log in the user and then pass the token to the become method – cristianorbs Mar 23 '15 at 13:57
1
void createNewGPlusUser(final String email, String name) {
        final ParseUser user = new ParseUser();
        user.setUsername(email);
        user.setPassword("my pass");
        user.put("any other variable in User class", "value");
        user.setEmail(email);
        user.put("name", name);
        signInParseUser(user, email);
    }

void signInParseUser(final ParseUser user, final String email) {

        user.signUpInBackground(new SignUpCallback() {
            public void done(ParseException e) {
                if (e == null) {
                    Log.d("TAG", "Created user");
                    // Hooray! Let them use the app now.
                    login(email);
                } else {
                    Log.d("TAG", "Failed Creating user");
                    e.printStackTrace();
                    // Sign up didn't succeed. Look at the ParseException
                    // to figure out what went wrong
                }
            }
        });
    }

void login(final String email) {
        ParseUser.logInInBackground(email, "my pass", new LogInCallback() {
            public void done(ParseUser user, ParseException e) {
                if (user != null) {
                    // Hooray! The user is logged in.
                    Log.d("TAG", "Login successful");
                                    } else {
                                        // Signup failed. Look at the ParseException to see what happened.
                }
            }
        });
    }
Arun Shankar
  • 2,165
  • 14
  • 19
  • Would never advise anyone to use hardcoded passwords, specially on client code. – Rahul Sainani Feb 02 '15 at 12:09
  • Did my post answer the question that you were looking for? Did it help you to create a parse user? This is a sample code – Arun Shankar Feb 02 '15 at 12:26
  • I took a different approach. Signed in on Google+ on Client and then on Parse in Cloud Code and then used the become on client with the session token of the user. But thanks for your answer. – Rahul Sainani Feb 02 '15 at 13:25
  • Hello, It helped me to understand a lot. I have one question, "My Pass" means, how do you get it? Do you generate a random password and store it on Parse? If so, how do you use it again if user sign out from the device and sign in on different device? How to handle those scenarios with a random password. NOTE : My application doesn't want to ask password from the user to enter it. Thanks in advance – Sai Jithendra Mar 20 '15 at 21:23
1

To do so, I have used the following code

  ParseUser.becomeInBackground(ParseUser.getCurrentUser().getSessionToken(), new LogInCallback() {
                    @Override
                    public void done(ParseUser parseUser, ParseException e) {
                        if (parseUser != null) {
                            parseUser.setUsername(userEmail);
//firstName and lastName I am getting from Person class of google plus api
                            parseUser.put("FirstName", firstName);
                            parseUser.put("LastName", lastName);

                            parseUser.saveInBackground();

                            ParseUtils.verifyParseConfiguration(context);
                            ParseUtils.subscribeWithUsername(strEmail);
                            Intent successIntent = new Intent(context, OurServicesActivity.class);
                            startActivity(successIntent);
                            overridePendingTransition(R.animator.fade_in, R.animator.fade_out);
                            finish();
                        } else {
                            Log.e(TAG, e.getMessage());
                            Utilities.showToast(context, "Something occurred");
                        }
                    }
                });

Let me know if it helps or if you have used something else.

Akshay
  • 1,020
  • 6
  • 10
0

Try this

ParseUser.becomeInBackground("session-token-here", new LogInCallback() {
           public void done(ParseUser user, ParseException e) {
                 if (user != null) {
                 // The current user is now set to user.
                 } else {
                  // The token could not be validated.
                 }
}

})

Aditya
  • 145
  • 6
  • Hello, from where you get that "Session Token"? is it Google+ one or Parse's Session Token? If it is Parse's, how to get one? Could you answer it in an easy way to use that method ? Thanks in advance – Sai Jithendra Mar 20 '15 at 21:20
  • Whenever you create a new project in parse, a token is generated. – Aditya Mar 22 '15 at 07:57
  • I head that google is updating it's authentication services. So check it new one is supported in parse or not. – Aditya Mar 22 '15 at 07:58