25

Error

When calling admin.auth().createCustomToken() I am getting the following error:

Error: The caller does not have permission; Please refer to https://firebase.google.com/docs/auth/admin/create-custom-tokens for more details on how to use and troubleshoot this feature.

The provided documentation leads me to believe that the service account I am initializing the Firebase Admin SDK with does not have sufficient permissions. I don't believe this to be the case, so I want to ask and see if I've missed anything.

Configuration

Firebase Admin SDK is initialized in the backend like so:

admin.initializeApp({
  serviceAccountId: 'firebase-adminsdk-xxxxx@my-project-id.iam.gserviceaccount.com'
});

Technically the value is referenced from an env var, but I have confirmed this value to be correct.

The service account being used has the following roles:

roles/firebase.sdkAdminServiceAgent
roles/iam.serviceAccountTokenCreator

Per the documentation, the required permission for creating custom tokens is iam.serviceAccounts.signBlob. This permission is part of the iam.serviceAccountTokenCreator role as per this output:

❯ gcloud beta iam roles describe roles/iam.serviceAccountTokenCreator
description: Impersonate service accounts (create OAuth2 access tokens, sign blobs
  or JWTs, etc).
etag: AA==
includedPermissions:
- iam.serviceAccounts.get
- iam.serviceAccounts.getAccessToken
- iam.serviceAccounts.getOpenIdToken
- iam.serviceAccounts.implicitDelegation
- iam.serviceAccounts.list
- iam.serviceAccounts.signBlob
- iam.serviceAccounts.signJwt
- resourcemanager.projects.get
- resourcemanager.projects.list
name: roles/iam.serviceAccountTokenCreator
stage: GA
title: Service Account Token Creator

Lastly, the code in question that is erroring out is as follows:

try {
  const loginToken = await admin.auth().createCustomToken(uid);
  return response(200).json({ loginToken });
} catch (err) {
  ...
}

The uid comes from signing in a user via a GoogleUser credential - the provided uid is confirmed to be accurate, and this flow works locally when referencing a JSON key file for the same service account.

Server is running on GKE, in case it could be a cluster permission error.

Any help would be greatly appreciated!

EDIT - RESOLVED Hiranya's answer did the trick - the K8s deployment had been configured with a service account whose original intent was only to enable Cloud SQL Proxy. Giving this service account the serviceAccountTokenCreator role solved the issue.

dubnev
  • 353
  • 3
  • 5

1 Answers1

50

You need to make sure the service account that the SDK is authorized with (not the one specified as serviceAccountId) has the token creator role. This is the service account auto-discovered by Google Application Default Credentials. In case of Cloud Functions this is the service account named {project-name}@appspot.gserviceaccount.com. You need to figure out the equivalent service account for GKE and grant it the token creator role.

Hiranya Jayathilaka
  • 7,180
  • 1
  • 23
  • 34
  • 12
    For me, it only worked when I started try adding the "Service Account Token Creator" role for each one of the members. It seams to did work after adding to myself (the owner) – Alynva Dec 24 '20 at 03:30
  • @AlissonNunes that also worked for me! Thanks a bunch – anonymous-dev Apr 28 '21 at 22:54
  • 1
    So it turns out that GCP doesn't propagate role changes immediately and can take up to a few minutes for the new permissions to be in effect. If you don't immediately see the `{project-name}@appspot.gserviceaccount.com` account with `Service Account Token Creator` working, try waiting several minutes and trying again. (removed prior comment) – bsplosion Jul 08 '21 at 21:09
  • 3
    Tried adding the Service Account Token Creator role to the app role as described above and it did not work, but adding the role to the Owner account worked for me as well. – joed4no Oct 11 '21 at 20:30
  • confirmed it works with @AlissonNunes note. Thanks! – ShinaBR2 Dec 20 '21 at 05:56
  • @bsplosion's suggestion of adding the role to the default App Engine service account fixed this for me. I noticed this error only occurred on deployed Cloud Functions and not when emulated, and I realised I was using a difference service account for local development. – Lachlan McDonald Mar 15 '22 at 11:35
  • For completeness, you can add it from https://console.cloud.google.com/iam-admin/iam?project=YOUR_PROJECT_ID – rafahoro Aug 25 '22 at 17:01