9
votes

My setup:

  • Java backend hosted on Google App Engine containing APIs that were created using Google Cloud Endpoints
  • Mobile client applications containing generated client libraries for the endpoints mentioned above. Also integrated with Firebase for authentication and the database.

My intention is that a user of the mobile client applications will be able to log in to the mobile app using Firebase authentication, then connect to any of the backend APIs, which in turn will do some processing and then read or write data to/from the Firebase database.

To secure the APIs on the server, I think I'll have to use the built-in verifyIdToken() method of the Firebase Server SDK to (see Verifying ID Tokens on Firebase) to decode a user's ID token passed from the client application. As verifyIdToken() runs asynchronously, how would I integrate it with an API method in GAE? I have something similar to the following so far:

@ApiMethod(name = "processAndSaveToDB", httpMethod = "post")
    public Response processAndSaveToDB(@Named("token") String token) {

        Response response = new Response();           

        // Check if the user is authenticated first
        FirebaseAuth.getInstance().verifyIdToken(idToken)
            .addOnSuccessListener(new OnSuccessListener() {
                @Override
                public void onSuccess(FirebaseToken decodedToken) {
                    String uid = decodedToken.getUid();

                    // do bulk of processAndSaveToDB() method

                })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(Exception e) {

                    // throw unauthorized exception

            });

    return response;
}
1
Have you achieved this using App Engine Flexible Environment or App Engine Standard Environment?gbhall

1 Answers

8
votes

As this authentication task is running asynchronously in task queue, you can wait until that task is ended and continue in synchronous way, optionally you can add listeners onSuccess, onFailure and onComplete.

Task<FirebaseToken> authTask = FirebaseAuth.getInstance().verifyIdToken(idToken)
.addOnSuccessListener(new OnSuccessListener() {
        @Override
        public void onSuccess(Object tr) {//do smtg }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(Exception excptn) {//do smtg }
    }).addOnCompleteListener(new OnCompleteListener() {
        @Override
        public void onComplete(Task task) {//do smtg }
    });
    try {
        Tasks.await(authTask);
    } catch(ExecutionException | InterruptedException e ){
        //handle error
    }
    FirebaseToken decodedToken = authTask.getResult();