1

I'm trying to build a system where I can access the Firestore database in another Google Cloud project by impersonating a service account that has access to that project's Firestore database using generating short-lived access tokens instead of service account keys for a more secure integration. When I try to use this kind of credential I get the following error:

Must initialize the SDK with a certificate credential or application default credentials to use Cloud Firestore API.

I'm wondering if I'm missing something here because it seems weird to me that it's just impossible to access Firestore with an impersonated account.

Thanks!

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
John Dengis
  • 192
  • 1
  • 8

2 Answers2

1

Just had a similar problem during development. I needed to use a service account to authenticate firebase admin to generate a email sign in link with const link = await auth.generateSignInWithEmailLink(email, actionCodeSettings); I go the error here that Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the identitytoolkit.googleapis.com

My solution is now:

  1. Impersonate the service account, by getting an Impersonated Client:
    const auth = new GoogleAuth();
    const client = await auth.getClient();
    const targetClient = new Impersonated({
      sourceClient: client,
      targetPrincipal: 'myaccount@myproject.iam.gserviceaccount.com',
      lifetime: 3600,
      delegates: [],
      targetScopes: ['https://www.googleapis.com/auth/cloud-platform'],
    });
  1. Extract the Oauth2 credentials
    const credentials = await targetClient.getAccessToken();
  1. Feed the credentials to initializeApp()
    initializeApp({
      credential: {
        getAccessToken: async () => {
          return {
            access_token: credentials.res.data.accessToken,
            expires_in: Date.parse(credentials.res.data.expireTime) / 1000,
          };
        },
      },
    });

Some notes:

  • What I didn't want to do is create a service account key, download it and use that to authenticate (this would have been the easiest way).

  • The contents of getAccessToken() response is not documented and I've pieced it together from looking at the content and tried out the token I've found in there.

  • I think I tried doing something similar before but you get an error when you try to use the Firestore API specifically. Seems like Cloud Firestore only supports service account credentials. – John Dengis Nov 17 '22 at 05:57
  • Some GCP apis are service account only and not accessible with a user account. – Christian van der Leeden Nov 19 '22 at 20:16
  • Right, but you can impersonate service accounts and generate short-lived tokens instead of using a service account key. However, the Firestore API doesn't let you use refresh tokens or access tokens to authenticate. Only service account keys. – John Dengis Nov 25 '22 at 06:18
0

Yes, it is possible to initialize the Firebase Admin SDK with an impersonated service account. The following steps are to be followed:

  1. Using admin SDK and service account initialize Firebase app backend with:
    admin.initializeApp({ 
           credential: admin.credential.cert(service_account_json), 
          })
  1. Obtain authentication token for the user you wish to impersonate:

    const userId = "[impersonating user uid string]" 
    const token = await admin.auth().createCustomToken(userId)
  1. Using frontend Firebase SDK authenticate user with:
    const token = "[token string obtained in step 2]" 
    firebase.auth().signInWithCustomToken(token)
Mousumi Roy
  • 609
  • 1
  • 6
  • That would authenticate the frontend SDK with the impersonated account. I want to authenticate the admin SDK, specifically cloud firestore. – John Dengis Oct 27 '21 at 14:50
  • The Admin SDK also provides a credential which allows you to authenticate with a Google OAuth2 refresh token. Point to note: OAuth 2.0 refresh tokens are not supported for connecting to Cloud Firestore. More details for this can be found in https://firebase.google.com/docs/admin/setup#java_2 – Mousumi Roy Oct 29 '21 at 12:14