0

The server I am operating is being used to generate Firebase tokens and to read and write values from firebase, I use REST APIs with a different type of token which has different UID prefix.

However, since many features have been added to the server, I decided to use Firebase java library and now migrating the previous code that was written for REST APIs.

The question is, how can I use Firebase Java library with tokens omitting authentication process?

Authentication process runs asynchronously so it can be applied to client application but not to server.

What if it fails authentication? or what if it takes too much time?

The previous code just used auth token for every request like this:

https://abcd.firebaseio.com/ns/blahblah/event?auth=token

So it doesn't need any authentication process.

Hope you understand my poor English. Thanks!

2 Answers2

1

According to the Firebase documentation for authentication server-side processes, there are three ways to authenticate:

  1. Using a Firebase app secret
  2. Using a secure JWT with the optional admin claim set to true
  3. Using a secure JWT designed to give access to only the pieces of data a server needs to touch

You are currently getting a secure JWT from your authentication server, so you are using option 2 or 3.

The alternative is to use the so-called app secret of you Firebase application. You can find this value in the Dashboard of the application and it can serve as a drop-in replacement for the current token.

However I highly recommend against this approach. Jenny wrote up a pretty exhaustive list of reasons against it here: https://stackoverflow.com/a/29240941

Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks for your kind answer. However, my question is, how can I avoid authentication process when I use Firebase Java library? For example, I don't want to do the following thing on server-side: ref.addAuthStateListener(new Firebase.AuthStateListener() { ....... – Steve Seungduk Kim Jun 26 '15 at 00:17
  • If I use REST APIs, there is no need to do it. just adding auth param is enough to authenticate. – Steve Seungduk Kim Jun 26 '15 at 00:19
  • The REST API starts a (largely) synchronous and stateless operation, so it takes the auth token as a parameter to that request. The Java SDK builds a stateful connection so that it can synchronize data, so it perform authentication as a separate step in there. If you prefer the synchronicity of the REST API, I'm quite sure you can fire HTTP requests from Java too. – Frank van Puffelen Jun 26 '15 at 00:34
  • So you mean to say, using REST API is less efficient than using Java SDK because it repeats some extra works for every connection that is not needed if I use Java SDK? If then, now I understand how I should go. – Steve Seungduk Kim Jun 26 '15 at 04:09
  • I didn't say anything about efficiency. I merely explained one of the reasons the REST API and the Java SDK use a different approach to authentication. – Frank van Puffelen Jun 26 '15 at 04:16
  • If you have code that requires that the connection is authenticated, put that code in an AuthDtateListener. See https://www.firebase.com/docs/android/guide/user-auth.html#section-monitoring-authentication – Frank van Puffelen Jun 26 '15 at 04:17
0

You can't replace the whole authentication process with just a secret using the Java Client Library. You need to generate a JWT. Authentication lasts for 24 hours, so you can save the generated JWT until it fails, or you just authenticate again prior to 24 hours, and keep that JWT again.

In order to handle the fact that authentication is an asynchronous process you'd also have to use a CountdownLatch or a Semaphore to prevent your program from exiting before the authentication process receives a response from Firebase.

CountdownLatch

A synchronisation aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.security.token.TokenGenerator;

import java.util.concurrent.CountDownLatch;

public class Main {

    public static void main(String[] args) {

        Map<String, Object> payload = new HashMap<String, Object>();
        payload.put("uid", "uniqueId1");
        payload.put("some", "arbitrary");
        payload.put("data", "here");
        TokenGenerator tokenGenerator = new TokenGenerator("<YOUR_FIREBASE_SECRET>");
        String token = tokenGenerator.createToken(payload);

        Firebase fb = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
        CountDownLatch done = new CountDownLatch(1);

        fb.authWithCustomToken(token, new Firebase.AuthResultHandler() {
            @Override
            public void onAuthenticationError(FirebaseError error) {
                System.err.println("Login Failed! " + error.getMessage());
                done.countDown();
            }
            @Override
            public void onAuthenticated(AuthData authData) {
                System.out.println("Login Succeeded!");
                // Save your JWT to keep using it for 24 hours
                done.countDown();
            }
        });

        done.await();
    }

}

Semaphore

It is used to control the number of concurrent threads that are using a resource. You could think of it as tickets to use a resource. You set the number of tickets available when you create it, and when acquire() is called with no tickets left, your process will wait for one to become available (on a release() call). On this code it is being created with zero "tickets" available:

import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.security.token.TokenGenerator;

import java.util.concurrent.Semaphore;

public class Main {

    public static void main(String[] args) {

        Map<String, Object> payload = new HashMap<String, Object>();
        payload.put("uid", "uniqueId1");
        payload.put("some", "arbitrary");
        payload.put("data", "here");
        TokenGenerator tokenGenerator = new TokenGenerator("<YOUR_FIREBASE_SECRET>");
        String token = tokenGenerator.createToken(payload);

        Firebase fb = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
        Semaphore semaphore = new Semaphore(0);

        fb.authWithCustomToken(token, new Firebase.AuthResultHandler() {
            @Override
            public void onAuthenticationError(FirebaseError error) {
                System.err.println("Login Failed! " + error.getMessage());
                semaphore.release();
            }
            @Override
            public void onAuthenticated(AuthData authData) {
                System.out.println("Login Succeeded!");
                // Save your JWT to keep using it for 24 hours
                semaphore.release();
            }
        });

        semaphore.acquire();
    }

}
Caio Iglesias
  • 594
  • 9
  • 24
  • What is 'TokenGenerator' ? – littleAlien Jul 12 '16 at 21:23
  • Firebase uses JWT for authentication. You need to generate a token in order to connect to Firebase's backend using a [server helper library](https://www.firebase.com/docs/web/guide/login/custom.html#section-token-generation), in this case [https://github.com/firebase/firebase-token-generator-java](https://github.com/firebase/firebase-token-generator-java) – Caio Iglesias Jul 12 '16 at 21:26