Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Firebase Admin SDK] Troubles while using Firebase Admin SDK to modify data in Firestore #73

Closed
KevinKons opened this issue Jan 7, 2020 · 2 comments
Assignees
Labels
api: firestore Issues related to the googleapis/java-firestore API. type: question Request for information or clarification. Not an issue.

Comments

@KevinKons
Copy link

I'm using Windows 10 with Java 8 and firebase admin version 6.12.0

I am trying to use the Firebase Admin SDK to add data to Firestore. I am following these documentations: https://firebase.google.com/docs/admin/setup#add_the_sdk and
https://firebase.google.com/docs/database/admin/save-data

The Service account key that I generated was saved as Json file in the root of the project.

This is how my build.gradle dependencies looks like:

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compile group: 'com.google.firebase', name: 'firebase-admin', version: '6.12.0'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

This is how my Main Java class looks like:

public class Main {

    public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
        FirebaseService firebaseService = new FirebaseService();
        firebaseService.initializeFirebaseApp();

        HashMap<String, Object> pharmacies = new HashMap<>();
        pharmacies.put("address", "Rua emídio goulart, 300");

        firebaseService.writeToDb(pharmacies);
    }
}

This is how the class FirebaseService looks like:

import com.google.api.core.ApiFuture;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.WriteResult;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.cloud.FirestoreClient;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.ExecutionException;

public class FirebaseService {

    private Firestore db;

    public void initializeFirebaseApp() throws IOException {
        FileInputStream serviceAccount = new FileInputStream("./ServiceAccountKey.json");

        FirebaseOptions options = new FirebaseOptions.Builder()
                .setCredentials(GoogleCredentials.fromStream(serviceAccount))
                .setDatabaseUrl("https://tests-212aa.firebaseio.com")
                .build();

        FirebaseApp.initializeApp(options);

        db = FirestoreClient.getFirestore();

    }

    public void writeToDb(HashMap data) throws ExecutionException, InterruptedException {
        ApiFuture<WriteResult> future = db.collection("pharmacies").document("farma").set(data);
        System.out.println(future.get().getUpdateTime());
    }
}

This is the stack trace:

Exception in thread "main" java.util.concurrent.ExecutionException: com.google.api.gax.rpc.UnavailableException: io.grpc.StatusRuntimeException: UNAVAILABLE: Credentials failed to obtain metadata
	at com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:552)
	at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:533)
	at com.google.common.util.concurrent.FluentFuture$TrustedFuture.get(FluentFuture.java:84)
	at com.google.common.util.concurrent.ForwardingFuture.get(ForwardingFuture.java:62)
	at com.pharmapp.productregistration.FirebaseService.writeToDb(FirebaseService.java:40)
	at com.pharmapp.productregistration.Main.main(Main.java:17)
Caused by: com.google.api.gax.rpc.UnavailableException: io.grpc.StatusRuntimeException: UNAVAILABLE: Credentials failed to obtain metadata
	at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:69)
	at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:72)
	at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:60)
	at com.google.api.gax.grpc.GrpcExceptionCallable$ExceptionTransformingFuture.onFailure(GrpcExceptionCallable.java:97)
	at com.google.api.core.ApiFutures$1.onFailure(ApiFutures.java:68)
	at com.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:982)
	at com.google.common.util.concurrent.DirectExecutor.execute(DirectExecutor.java:30)
	at com.google.common.util.concurrent.AbstractFuture.executeListener(AbstractFuture.java:1138)
	at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:957)
	at com.google.common.util.concurrent.AbstractFuture.setException(AbstractFuture.java:748)
	at io.grpc.stub.ClientCalls$GrpcFuture.setException(ClientCalls.java:515)
	at io.grpc.stub.ClientCalls$UnaryStreamToFuture.onClose(ClientCalls.java:490)
	at io.grpc.PartialForwardingClientCallListener.onClose(PartialForwardingClientCallListener.java:39)
	at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:23)
	at io.grpc.ForwardingClientCallListener$SimpleForwardingClientCallListener.onClose(ForwardingClientCallListener.java:40)
	at io.grpc.internal.CensusStatsModule$StatsClientInterceptor$1$1.onClose(CensusStatsModule.java:700)
	at io.grpc.PartialForwardingClientCallListener.onClose(PartialForwardingClientCallListener.java:39)
	at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:23)
	at io.grpc.ForwardingClientCallListener$SimpleForwardingClientCallListener.onClose(ForwardingClientCallListener.java:40)
	at io.grpc.internal.CensusTracingModule$TracingClientInterceptor$1$1.onClose(CensusTracingModule.java:399)
	at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:510)
	at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:66)
	at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:630)
	at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$700(ClientCallImpl.java:518)
	at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:692)
	at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:681)
	at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
	at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: io.grpc.StatusRuntimeException: UNAVAILABLE: Credentials failed to obtain metadata
	at io.grpc.Status.asRuntimeException(Status.java:533)
	... 24 more
Caused by: java.io.IOException: Error getting access token for service account: 400 Bad Request
{
  "error": "invalid_grant",
  "error_description": "Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values and use a clock with skew to account for clock differences between systems."
}
	at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:432)
	at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:157)
	at com.google.auth.oauth2.OAuth2Credentials.getRequestMetadata(OAuth2Credentials.java:145)
	at com.google.auth.Credentials.blockingGetToCallback(Credentials.java:112)
	at com.google.auth.Credentials$1.run(Credentials.java:98)
	... 7 more
Caused by: com.google.api.client.http.HttpResponseException: 400 Bad Request
{
  "error": "invalid_grant",
  "error_description": "Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values and use a clock with skew to account for clock differences between systems."
}
	at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1097)
	at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:429)
	... 11 more

The line referenced in the stacktrace as at com.pharmapp.productregistration.FirebaseService.writeToDb(FirebaseService.java:40) is this one System.out.println(future.get().getUpdateTime());

I don't know what is going wrong I am doing everything as the documentation says.

@chingor13 chingor13 transferred this issue from googleapis/google-cloud-java Jan 7, 2020
@yoshi-automation yoshi-automation added the triage me I really want to be triaged. label Jan 8, 2020
@athakor athakor added type: question Request for information or clarification. Not an issue. and removed triage me I really want to be triaged. labels Jan 9, 2020
@dmitry-fa
Copy link
Contributor

The very similar issue: googleapis/google-cloud-python#3100

The root cause: the clock on the local machine is out of sync with the real world.
I managed to reproduce the issue on my local environment. To do that I turned the 'Set time automatically' option off and moved the clock one hour ahead. Then I ran your example and got exactly the same exception.
Moving the clock one hour back made the exception disappear.

@KevinKons
Copy link
Author

Thanks, that solved my problem!

@google-cloud-label-sync google-cloud-label-sync bot added the api: firestore Issues related to the googleapis/java-firestore API. label Jan 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: firestore Issues related to the googleapis/java-firestore API. type: question Request for information or clarification. Not an issue.
Projects
None yet
Development

No branches or pull requests

4 participants