简体   繁体   中英

How do I add both Facebook Login and Email registration to my Google Cloud Endpoints App (Java)?

So I have an app which uses Google App Engine and Google Cloud Endpoints as it's backend in Java. I'm currently working on User authentication and here is what I'm trying to do:

When user first opens the app, they'll have option to either "Login through Facebook" or signup using their email address. Then this data would be stored in a user object and after registration would direct them to the app homepage. It will be saved in their preferences so that they don't need to login every time they open the app (if ever).

Now I heard you can use a custom authenticator for Facebook, but there's not much documentation regarding this. How can I get the email registration and Facebook Login options to be implemented with Google Cloud Endpoint's Authenticator? Or should I make a different approach?

Thanks.

My approach is using the Facebook login method (Facebook SDK for Android). The Facebook authentication process returns (on success) an object from which I can get the user's email then I save it in my Endpoints class using Datastore API. To check if user already logged in I chose the SharedPreferences approach with GSON library to parse objects into JSON String and save them in the prefs.

Links and my sample codes below :

Regarding the Authenticator I found this SO answer

More info about Facebook login method

Saving custom objects in SharedPreferences

Getting user's email through Facebook auth

 private void onSessionStateChange(Session session, SessionState state, Exception exception) {
        if (state.isOpened()) {
            if (isSessionCalled == false) {
                Log.i(TAG, "Logged in...");
                System.out.println("Token=" + session.getAccessToken());

                new Request(
                        session,
                        "/me",
                        null,
                        HttpMethod.GET,
                        new Request.Callback() {
                            public void onCompleted(Response response) {
                                if (response != null) {
                                    GraphObject object = response.getGraphObject();
                                    String email = (String) object.getProperty("email");
                                    Log.i(TAG, "user email : " + email);
                                    String firstName = (String) object.getProperty("first_name");
                                    String lastName = (String) object.getProperty("last_name");
                                    mUserTask = new UserAsyncTask();
                                    mUserTask.execute(email);
                                }

                            }

                        }
                ).executeAsync();

                isSessionCalled = true;
            }
            else {
                Log.w(TAG, "session called twice");
            }

            }

        else if (state.isClosed()) {
            Log.i(TAG, "Logged out...");
        }
    }

Storing the user in my backend :

@ApiMethod(name = "storeUserModel")
    public UserModel storeUserModel(UserModel userModel) throws UserAlreadyExistsException, UserNotFoundException {
        logger.info("inside storeUser");
        String email = userModel.getEmail();
        UserModel checkUser = getUserModel(email);
        logger.info("after getUserModel with email " + email);

        if (checkUser == null) {
            logger.info("inside checkUser is NULL");
            DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
            Transaction txn = datastoreService.beginTransaction();
            try {
                Entity userEntity = new Entity(UserModel.class.getSimpleName(), email);
                userEntity.setProperty("nickname", userModel.getNickname());

                // TODO save the pheromones with the key of userEntity
                datastoreService.put(userEntity);
                txn.commit();
                storePheromoneList(userModel.getPheromoneList(), userEntity.getKey(), datastoreService);
            } finally {
                if (txn.isActive()) {
                    logger.severe("rolled back with email : " +  email);
                    txn.rollback();
                }
            }
        }
        else {
            throw new UserAlreadyExistsException();
        }
        return userModel;

    }

A class that triggers calls to my backend

public class EndpointsServer implements Server {

    private static final String TAG = "EndpointsServer";

    final UserModelApi userEndpointsApi;

    public EndpointsServer() {
        UserModelApi.Builder builder = new UserModelApi.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
                .setRootUrl("http://10.0.2.2:8080/_ah/api/")
                .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
                    @Override
                    public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
                        abstractGoogleClientRequest.setDisableGZipContent(true);
                    }
                });

        userEndpointsApi = builder.build();

    }

    @Override
    public User getUser(String email)  {
        User  user = null;
        try {
            Log.d(TAG, "in getUser with email " +email);
            // get user from db
            UserModel userModel = userEndpointsApi.getUserModel(email).execute();

            if (userModel != null) {
                Log.d(TAG, "user != null with email " + email);
                user = new User(userModel);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return user;
    } 
}

Storing user on successful login :

String userString = gson.toJson(user, User.class);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(USER_KEY, userString);
editor.commit();

There's more to it like another client side class to build the api call to the backend and lots of other details. I can post it if you want.

I can't speak on Java but I started with Python by looking at this repo on Github: https://github.com/loudnate/appengine-endpoints-auth-example

This shows you an example on how to write a custom authenticator with Facebook Login. Writing your own authentication I think you should be able to find some examples. The only thing you need to do after is to use the same User entity.

And I suggest you do some reading on how OAUTH 2.0 works so you don't get too confused on the task you need to do.

Basically:

  • On your client side, whether web or android, get a facebook access token, sends it to your endpoint service. Exchange for a access token of your own. At the same time, create your User object in datastore and associate the access token.
  • Then all your subsequent request should use this access token to get access to your endpoint backend. (Do a user check on your endpoint API method.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM