Overview
firebase-admin-node로 custom token을 만드는 과정에 impersonate service account를 사용할 수 없는 이슈
issue: https://github.com/firebase/firebase-admin-node/issues/1861
pr: https://github.com/firebase/firebase-admin-node/pull/1862
Contribute Status
[2022–09–05]
아직 accept은 되지 않았으나 소수의 사람들의 니즈가 있는 거 같긴하다. 아마 곧 머지되거나 피드백이 오지 않을까..
Reproduce
- custom token generate 권한이 있는 service-account를 만든다.
필요한 권한은 다음을 참조한다 roles/iam.serviceAccountTokenCreator - 해당 service-account를 이용해 gcloud ADC를 내려받는다.
$ gcloud auth application-default login --impersonate-service-account=<impersonate-service-account>
3. ~/.config/gcloud/application_default_credentials.json 에 해당 내용이 잘 들어갔는지 확인한다. 다음 포맷으로 생성이 될 것이다.
{
"delegates": [],
"service_account_impersonation_url": "",
"source_credentials": {
"client_id": "",
"client_secret": "",
"refresh_token": "",
"type": "authorized_user"
},
"type": "impersonated_service_account"
}
4. firebase-admin-node@10.2.0 를 다운받는다.
$ yarn add firebase-admin-node@10.2.0
5. firebase-admin-node를 실행한다.
import admin from 'firebase-admin';admin.initializeApp({
credential: admin.credential.applicationDefault(),
});
6. 에러 메시지 발생
message: 'Refresh token must contain a "client_id" property.'
How to solve
Cause Analysis
src/app/credential-internal.ts
을 보면, getApplicationDefault
에서 필요한 credential을 받아오는 걸 확인할 수 있다.
우리는 env로 세팅을 해주지 않았기 때문에 아래 refreshToken 방식으로 생성하는 것을 볼 수 있다.
그러나 RefreshTokenCredential
은 아래 포맷을 따르는 걸 전제로 하고 있기에 오류가 날 수 밖에 없다.
firebase-admin-node는 impersonated_service_account
타입을 받아주지 않고 RefreshTokenCredential
로 취급하여 처리하고 있던 것이다.
Solution
Impersonated ServiceAccount를 제대로 사용할 수 있도록 아래와 같이 Credential
을 상속받는 ImpersonatedServiceAccountCredential
을 만들어 준다.
물론, ServiceAccount 값들을 저장하는 ImpersonateServiceAccount
도 만들어 준다.
우리가 원하는 정보는 sourceCredentials에 있으므로 해당 내용을 뽑아서 사용하고, 나머지 access token을 받아오는 과정은 RefreshTokenCredential
과 동일하게 만든다. 이 부분은 google-auth-library-python에서 token을 만드는 과정을 참고했다.
마지막으로 type이 해당 타입일 때 ImpersonatedServiceAccountCredential
을 사용하도록 만든다.
테스트를 추가하고 마무리한다.
해당 내용은 상단 첨부한 PR에 있다.