Ad

How To Use Firebase Admin SDK In Spring MVC

I don't understand how to configurate Firebase Admin in my Spring MVC Rest service. I need token verification. For tests I was using this in my controller:

@RequestMapping(value = "/test", method = RequestMethod.GET)
@ResponseBody
public  List<Subscription> getTest(@RequestHeader("token") String idToken) throws FirebaseAuthException {

    String DATABASE_URL = "https://name.firebaseio.com/";

    try {
        ClassLoader classLoader = getClass().getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream("token.json");

        FirebaseOptions options = new FirebaseOptions.Builder()
        .setCredentials( GoogleCredentials.fromStream(inputStream))
                .setDatabaseUrl(DATABASE_URL)
                .build();
        FirebaseApp.initializeApp(options);
    } catch (IOException e) {
        e.printStackTrace();
        System.out.println("Error loading database");
    }


        FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
        String uid = decodedToken.getUid();

       return service.getAll();
}

But it return java.lang.IllegalStateException: FirebaseApp name [DEFAULT] already exists! when I send more than one request.

My problem, that I don't understand how to make verification for each requests.

I use Model Service Repository Controller

Ad

Answer

Right now your code tries to initialize FirebaseApp for each request. This is not needed, and in fact not allowed (as shown by the error message). The simplest fix is to check if the FirebaseApp is already initialized with:

if (FirebaseApp.getApps().isEmpty()) {
    String DATABASE_URL = "https://name.firebaseio.com/";
    try {
        ClassLoader classLoader = getClass().getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream("token.json");

        FirebaseOptions options = new FirebaseOptions.Builder()
        .setCredentials( GoogleCredentials.fromStream(inputStream))
                .setDatabaseUrl(DATABASE_URL)
                .build();
        FirebaseApp.initializeApp(options);
    } catch (IOException e) {
        e.printStackTrace();
        System.out.println("Error loading database");
    }
}
FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
String uid = decodedToken.getUid();

return service.getAll();

But this still checks for the FirebaseApp every call, and honestly just makes the code of this method bigger than needed. So it's probably better to tie into the lifecycle of the controller, and run the code that initializes FirebaseApp only when the controller gets created. I'm not knowledgeable enough on Spring to answer how to do that, but this article shows some promising approaches.

Ad
source: stackoverflow.com
Ad