🥶

Firebase Admin v12でcreateSessionCookie時にpermission denied

2025/02/08に公開

現象

firebase authenticationでログインした後にCookieに保存するセッションIDを作成しようとするとpermission deniedが発生。

Cloud Functionsのログ

{
  "error": {
    "code": 403,
    "message": "Caller does not have required permission to use project [PROJECT_ID]. Grant the caller the roles/serviceusage.serviceUsageConsumer role, or a custom role with the serviceusage.services.use permission, by visiting https://console.developers.google.com/iam-admin/iam/project?project=[PROJECT_ID] and then retry. Propagation of the new permission may take a few minutes.",
    "errors": [
      {
        "message": "Caller does not have required permission to use project [PROJECT_ID]. Grant the caller the roles/serviceusage.serviceUsageConsumer role, or a custom role with the serviceusage.services.use permission, by visiting https://console.developers.google.com/iam-admin/iam/project?project=[PROJECT_ID] and then retry. Propagation of the new permission may take a few minutes.",
        "domain": "global",
        "reason": "forbidden"
      }
    ],
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "USER_PROJECT_DENIED",
        "domain": "googleapis.com",
        "metadata": {
          "service": "identitytoolkit.googleapis.com",
          "consumer": "projects/[PROJECT_ID]",
          "containerInfo": "[PROJECT_ID]"
        }
      },
      {
        "@type": "type.googleapis.com/google.rpc.LocalizedMessage",
        "locale": "en-US",
        "message": "Caller does not have required permission to use project [PROJECT_ID]. Grant the caller the roles/serviceusage.serviceUsageConsumer role, or a custom role with the serviceusage.services.use permission, by visiting https://console.developers.google.com/iam-admin/iam/project?project=[PROJECT_ID] and then retry. Propagation of the new permission may take a few minutes."
      },
      {
        "@type": "type.googleapis.com/google.rpc.Help",
        "links": [
          {
            "description": "Google developer console IAM admin",
            "url": "https://console.developers.google.com/iam-admin/iam/project?project=[PROJECT_ID]"
          }
        ]
      }
    ]
  }
}

原因

ログ上では、roles/serviceusage.serviceUsageConsumerロールかserviceusage.services.use 権限を含むカスタムロールを作成しろ

呼び出し元にプロジェクト [PROJECT_ID] を使用するために必要な権限がないのでGoogle Identity Toolkit APIにリクエストを拒否されているようでした。
ログによると、次のいずれかの権限を付与して許可しなさいとのことです。

  • roles/serviceusage.serviceUsageConsumer ロール
    または
  • serviceusage.services.use 権限を含むカスタムロール

なお、firebase deployで自動でfunctionsやhostingなどデプロイしてくれているので、裏側でGoogle Identity Toolkit APIが使われていたのは知らなかったです😅

また、同じアプリケーションなのに以前の組織で発生しなかったのは、2024 年 5 月 3 日以降作成された組織では、自動的なロール付与が無効になったからですね。

解決策

  1. エラーが出ているfirebase functionsで使用されているサービスアカウントを以下コマンドで確認
gcloud functions describe {関数名} --region={リージョン名}

ちなみに、自分は関数名やリージョンはfirebaseコンソールから確認しました。

gcloud functions describe {関数名} --region={リージョン名}

結果例

...
serviceConfig:
  ...
  serviceAccountEmail: 
  ...

ここで、xxxxxxxxxxxx-compute@developer.gserviceaccount.com のサービスアカウントで権限エラーが起きていたということがわかります。

  1. 問題のあるアカウントのロールを確認
gcloud projects get-iam-policy [PROJECT_ID] \
  --flatten="bindings[].members" \
  --filter="bindings.members:xxxxxxxxxxxx-compute@developer.gserviceaccount.com" \
  --format="table(bindings.role)"

例えば、以下のような感じで、roles/serviceusage.serviceUsageConsumerはついていない状態のはずです。

結果例

ROLE
roles/cloudbuild.builds.builder
roles/cloudbuild.workerPoolUser
roles/iam.serviceAccountUser
  1. roles/serviceusage.serviceUsageConsumer ロールの追加
gcloud projects add-iam-policy-binding [PROJECT_ID] \
  --member="serviceAccount:xxxxxxxxxxxx-compute@developer.gserviceaccount.com" \
  --role="roles/serviceusage.serviceUsageConsumer"

追加したら、ロールが正しく付与されたか確認。

gcloud projects get-iam-policy [PROJECT_ID] \
  --flatten="bindings[].members" \
  --filter="bindings.members:xxxxxxxxxxxx-compute@developer.gserviceaccount.com" \
  --format="table(bindings.role)"

結果例

ROLE
...
roles/serviceusage.serviceUsageConsumer

以上で、serviceUsageConsumerが不足していた件は解決なのですが、自分はエラーが別の内容に変わりました。

Permission 'iam.serviceAccounts.signBlob' denied on resource (or it may not exist).;
Please refer to https://firebase.google.com/docs/auth/admin/create-custom-tokens for more details on how to use and troubleshoot this feature.

iam.serviceAccounts.signBlobの権限がないために、Firebase Admin SDK を使用してカスタムトークンを作成する操作が拒否されているそうです。なので、追加の対応が必要です。

  1. roles/iam.serviceAccountTokenCreator ロールの追加

iam.serviceAccounts.signBlob 権限はroles/iam.serviceAccountTokenCreatorのロールに含まれているので、このロールを付与してあげれば解決です。

gcloud projects add-iam-policy-binding [PROJECT_ID] \
  --member="serviceAccount:xxxxxxxxxxxx-compute@developer.gserviceaccount.com" \
  --role="roles/iam.serviceAccountTokenCreator"

追加したら、ロールが正しく付与されたか確認。

gcloud projects get-iam-policy [PROJECT_ID] \
  --flatten="bindings[].members" \
  --filter="bindings.members:xxxxxxxxxxxx-compute@developer.gserviceaccount.com" \
  --format="table(bindings.role)"

結果例

ROLE
...
roles/iam.serviceAccountTokenCreator

以上で解決です。
権限を付与した後、createSessionCookie を再度実行してみてください。正常に動作するはずです。

備考

山ほどネットの記事調べ上げましたが、このエラー解決は、本当に苦労しました。今までロール自動付与で問題起きていなかったので、自動的なロール付与が無効になってからというもの、権限周りのエラーでよく頭悩まされる。
ログイン処理でcreateSessionCookieがこけている際は、ぜひ参考にしてみてください。

Discussion