firebase-admin 12.7.0 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/lib/app/core.d.ts +1 -2
- package/lib/app/core.js +1 -1
- package/lib/app/credential-factory.d.ts +1 -2
- package/lib/app/credential-factory.js +5 -6
- package/lib/app/credential-internal.d.ts +37 -35
- package/lib/app/credential-internal.js +194 -294
- package/lib/app/credential.d.ts +1 -1
- package/lib/app/credential.js +1 -1
- package/lib/app/firebase-app.d.ts +1 -1
- package/lib/app/firebase-app.js +1 -1
- package/lib/app/firebase-namespace.d.ts +1 -1
- package/lib/app/firebase-namespace.js +1 -1
- package/lib/app/index.d.ts +1 -1
- package/lib/app/index.js +1 -1
- package/lib/app/lifecycle.d.ts +1 -1
- package/lib/app/lifecycle.js +6 -6
- package/lib/app-check/app-check-api-client-internal.d.ts +1 -1
- package/lib/app-check/app-check-api-client-internal.js +1 -1
- package/lib/app-check/app-check-api.d.ts +1 -1
- package/lib/app-check/app-check-api.js +1 -1
- package/lib/app-check/app-check-namespace.d.ts +1 -1
- package/lib/app-check/app-check-namespace.js +1 -1
- package/lib/app-check/app-check.d.ts +1 -1
- package/lib/app-check/app-check.js +1 -1
- package/lib/app-check/index.d.ts +1 -1
- package/lib/app-check/index.js +3 -3
- package/lib/app-check/token-generator.d.ts +1 -1
- package/lib/app-check/token-generator.js +3 -3
- package/lib/app-check/token-verifier.d.ts +1 -1
- package/lib/app-check/token-verifier.js +1 -1
- package/lib/auth/action-code-settings-builder.d.ts +1 -1
- package/lib/auth/action-code-settings-builder.js +1 -1
- package/lib/auth/auth-api-request.d.ts +1 -1
- package/lib/auth/auth-api-request.js +3 -4
- package/lib/auth/auth-config.d.ts +1 -1
- package/lib/auth/auth-config.js +3 -3
- package/lib/auth/auth-namespace.d.ts +1 -1
- package/lib/auth/auth-namespace.js +1 -1
- package/lib/auth/auth.d.ts +1 -1
- package/lib/auth/auth.js +1 -1
- package/lib/auth/base-auth.d.ts +1 -1
- package/lib/auth/base-auth.js +3 -3
- package/lib/auth/identifier.d.ts +1 -1
- package/lib/auth/identifier.js +5 -6
- package/lib/auth/index.d.ts +1 -1
- package/lib/auth/index.js +3 -3
- package/lib/auth/project-config-manager.d.ts +1 -1
- package/lib/auth/project-config-manager.js +1 -1
- package/lib/auth/project-config.d.ts +1 -1
- package/lib/auth/project-config.js +1 -1
- package/lib/auth/tenant-manager.d.ts +1 -1
- package/lib/auth/tenant-manager.js +1 -1
- package/lib/auth/tenant.d.ts +1 -1
- package/lib/auth/tenant.js +1 -1
- package/lib/auth/token-generator.d.ts +1 -2
- package/lib/auth/token-generator.js +3 -3
- package/lib/auth/token-verifier.d.ts +1 -1
- package/lib/auth/token-verifier.js +5 -5
- package/lib/auth/user-import-builder.d.ts +1 -2
- package/lib/auth/user-import-builder.js +3 -3
- package/lib/auth/user-record.d.ts +1 -1
- package/lib/auth/user-record.js +1 -1
- package/lib/credential/index.d.ts +1 -1
- package/lib/credential/index.js +1 -1
- package/lib/data-connect/data-connect-api-client-internal.d.ts +1 -1
- package/lib/data-connect/data-connect-api-client-internal.js +1 -1
- package/lib/data-connect/data-connect-api.d.ts +1 -1
- package/lib/data-connect/data-connect-api.js +1 -1
- package/lib/data-connect/data-connect.d.ts +1 -1
- package/lib/data-connect/data-connect.js +1 -1
- package/lib/data-connect/index.d.ts +1 -1
- package/lib/data-connect/index.js +3 -3
- package/lib/database/database-namespace.d.ts +1 -1
- package/lib/database/database-namespace.js +1 -1
- package/lib/database/database.d.ts +1 -2
- package/lib/database/database.js +1 -1
- package/lib/database/index.d.ts +1 -1
- package/lib/database/index.js +4 -4
- package/lib/default-namespace.d.ts +1 -1
- package/lib/default-namespace.js +1 -1
- package/lib/eventarc/cloudevent.d.ts +1 -1
- package/lib/eventarc/cloudevent.js +1 -1
- package/lib/eventarc/eventarc-client-internal.d.ts +1 -1
- package/lib/eventarc/eventarc-client-internal.js +1 -1
- package/lib/eventarc/eventarc-utils.d.ts +1 -1
- package/lib/eventarc/eventarc-utils.js +3 -3
- package/lib/eventarc/eventarc.d.ts +1 -1
- package/lib/eventarc/eventarc.js +1 -1
- package/lib/eventarc/index.d.ts +1 -1
- package/lib/eventarc/index.js +3 -3
- package/lib/extensions/extensions-api-client-internal.d.ts +1 -1
- package/lib/extensions/extensions-api-client-internal.js +1 -1
- package/lib/extensions/extensions-api.d.ts +1 -1
- package/lib/extensions/extensions-api.js +1 -1
- package/lib/extensions/extensions.d.ts +1 -1
- package/lib/extensions/extensions.js +1 -1
- package/lib/extensions/index.d.ts +1 -1
- package/lib/extensions/index.js +3 -3
- package/lib/firebase-namespace-api.d.ts +1 -1
- package/lib/firebase-namespace-api.js +1 -1
- package/lib/firestore/firestore-internal.d.ts +1 -1
- package/lib/firestore/firestore-internal.js +3 -3
- package/lib/firestore/firestore-namespace.d.ts +1 -1
- package/lib/firestore/firestore-namespace.js +1 -1
- package/lib/firestore/index.d.ts +1 -1
- package/lib/firestore/index.js +4 -4
- package/lib/functions/functions-api-client-internal.d.ts +1 -1
- package/lib/functions/functions-api-client-internal.js +3 -2
- package/lib/functions/functions-api.d.ts +1 -1
- package/lib/functions/functions-api.js +1 -1
- package/lib/functions/functions.d.ts +1 -1
- package/lib/functions/functions.js +1 -1
- package/lib/functions/index.d.ts +1 -1
- package/lib/functions/index.js +3 -3
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/installations/index.d.ts +1 -1
- package/lib/installations/index.js +3 -3
- package/lib/installations/installations-namespace.d.ts +1 -1
- package/lib/installations/installations-namespace.js +1 -1
- package/lib/installations/installations-request-handler.d.ts +1 -1
- package/lib/installations/installations-request-handler.js +1 -1
- package/lib/installations/installations.d.ts +1 -1
- package/lib/installations/installations.js +1 -1
- package/lib/instance-id/index.d.ts +1 -1
- package/lib/instance-id/index.js +3 -3
- package/lib/instance-id/instance-id-namespace.d.ts +1 -1
- package/lib/instance-id/instance-id-namespace.js +1 -1
- package/lib/instance-id/instance-id.d.ts +1 -1
- package/lib/instance-id/instance-id.js +1 -1
- package/lib/machine-learning/index.d.ts +1 -1
- package/lib/machine-learning/index.js +3 -3
- package/lib/machine-learning/machine-learning-api-client.d.ts +1 -1
- package/lib/machine-learning/machine-learning-api-client.js +3 -3
- package/lib/machine-learning/machine-learning-namespace.d.ts +1 -1
- package/lib/machine-learning/machine-learning-namespace.js +1 -1
- package/lib/machine-learning/machine-learning-utils.d.ts +1 -1
- package/lib/machine-learning/machine-learning-utils.js +1 -1
- package/lib/machine-learning/machine-learning.d.ts +1 -1
- package/lib/machine-learning/machine-learning.js +1 -1
- package/lib/messaging/index.d.ts +2 -2
- package/lib/messaging/index.js +3 -3
- package/lib/messaging/messaging-api-request-internal.d.ts +2 -12
- package/lib/messaging/messaging-api-request-internal.js +4 -40
- package/lib/messaging/messaging-api.d.ts +8 -94
- package/lib/messaging/messaging-api.js +1 -1
- package/lib/messaging/messaging-errors-internal.d.ts +1 -1
- package/lib/messaging/messaging-errors-internal.js +3 -4
- package/lib/messaging/messaging-internal.d.ts +1 -1
- package/lib/messaging/messaging-internal.js +4 -3
- package/lib/messaging/messaging-namespace.d.ts +2 -22
- package/lib/messaging/messaging-namespace.js +1 -1
- package/lib/messaging/messaging.d.ts +3 -149
- package/lib/messaging/messaging.js +2 -539
- package/lib/project-management/android-app.d.ts +1 -1
- package/lib/project-management/android-app.js +1 -1
- package/lib/project-management/app-metadata.d.ts +1 -1
- package/lib/project-management/app-metadata.js +1 -1
- package/lib/project-management/index.d.ts +1 -1
- package/lib/project-management/index.js +3 -3
- package/lib/project-management/ios-app.d.ts +1 -1
- package/lib/project-management/ios-app.js +1 -1
- package/lib/project-management/project-management-api-request-internal.d.ts +1 -1
- package/lib/project-management/project-management-api-request-internal.js +3 -3
- package/lib/project-management/project-management-namespace.d.ts +1 -1
- package/lib/project-management/project-management-namespace.js +1 -1
- package/lib/project-management/project-management.d.ts +1 -1
- package/lib/project-management/project-management.js +1 -1
- package/lib/remote-config/condition-evaluator-internal.d.ts +1 -1
- package/lib/remote-config/condition-evaluator-internal.js +6 -14
- package/lib/remote-config/index.d.ts +1 -1
- package/lib/remote-config/index.js +3 -3
- package/lib/remote-config/internal/value-impl.d.ts +1 -1
- package/lib/remote-config/internal/value-impl.js +1 -1
- package/lib/remote-config/remote-config-api-client-internal.d.ts +1 -1
- package/lib/remote-config/remote-config-api-client-internal.js +1 -1
- package/lib/remote-config/remote-config-api.d.ts +1 -1
- package/lib/remote-config/remote-config-api.js +1 -1
- package/lib/remote-config/remote-config-namespace.d.ts +1 -1
- package/lib/remote-config/remote-config-namespace.js +1 -1
- package/lib/remote-config/remote-config.d.ts +1 -1
- package/lib/remote-config/remote-config.js +1 -1
- package/lib/security-rules/index.d.ts +1 -1
- package/lib/security-rules/index.js +3 -3
- package/lib/security-rules/security-rules-api-client-internal.d.ts +1 -1
- package/lib/security-rules/security-rules-api-client-internal.js +1 -1
- package/lib/security-rules/security-rules-internal.d.ts +1 -1
- package/lib/security-rules/security-rules-internal.js +1 -1
- package/lib/security-rules/security-rules-namespace.d.ts +1 -1
- package/lib/security-rules/security-rules-namespace.js +1 -1
- package/lib/security-rules/security-rules.d.ts +1 -2
- package/lib/security-rules/security-rules.js +1 -1
- package/lib/storage/index.d.ts +1 -1
- package/lib/storage/index.js +4 -4
- package/lib/storage/storage-namespace.d.ts +1 -1
- package/lib/storage/storage-namespace.js +1 -1
- package/lib/storage/storage.d.ts +1 -1
- package/lib/storage/storage.js +1 -1
- package/lib/storage/utils.d.ts +1 -1
- package/lib/storage/utils.js +2 -3
- package/lib/utils/api-request.d.ts +1 -5
- package/lib/utils/api-request.js +23 -8
- package/lib/utils/crypto-signer.d.ts +1 -2
- package/lib/utils/crypto-signer.js +3 -3
- package/lib/utils/deep-copy.d.ts +1 -1
- package/lib/utils/deep-copy.js +3 -4
- package/lib/utils/error.d.ts +1 -1
- package/lib/utils/error.js +1 -1
- package/lib/utils/index.d.ts +2 -2
- package/lib/utils/index.js +19 -16
- package/lib/utils/jwt.d.ts +1 -2
- package/lib/utils/jwt.js +5 -5
- package/lib/utils/validator.d.ts +1 -2
- package/lib/utils/validator.js +20 -21
- package/package.json +14 -13
- package/CHANGELOG.md +0 -4
- package/lib/messaging/batch-request-internal.d.ts +0 -55
- package/lib/messaging/batch-request-internal.js +0 -127
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! firebase-admin
|
|
1
|
+
/*! firebase-admin v13.0.0 */
|
|
2
2
|
"use strict";
|
|
3
3
|
/*!
|
|
4
4
|
* @license
|
|
@@ -17,37 +17,84 @@
|
|
|
17
17
|
* limitations under the License.
|
|
18
18
|
*/
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.
|
|
20
|
+
exports.ImpersonatedServiceAccountCredential = exports.RefreshTokenCredential = exports.ServiceAccountCredential = exports.ApplicationDefaultCredential = void 0;
|
|
21
|
+
exports.isApplicationDefault = isApplicationDefault;
|
|
22
|
+
exports.getApplicationDefault = getApplicationDefault;
|
|
21
23
|
const fs = require("fs");
|
|
22
|
-
const
|
|
23
|
-
const path = require("path");
|
|
24
|
+
const google_auth_library_1 = require("google-auth-library");
|
|
24
25
|
const error_1 = require("../utils/error");
|
|
25
|
-
const api_request_1 = require("../utils/api-request");
|
|
26
26
|
const util = require("../utils/validator");
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
27
|
+
const SCOPES = [
|
|
28
|
+
'https://www.googleapis.com/auth/cloud-platform',
|
|
29
|
+
'https://www.googleapis.com/auth/firebase.database',
|
|
30
|
+
'https://www.googleapis.com/auth/firebase.messaging',
|
|
31
|
+
'https://www.googleapis.com/auth/identitytoolkit',
|
|
32
|
+
'https://www.googleapis.com/auth/userinfo.email',
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Implementation of ADC that uses google-auth-library-nodejs.
|
|
36
|
+
*/
|
|
37
|
+
class ApplicationDefaultCredential {
|
|
38
|
+
constructor(httpAgent) {
|
|
39
|
+
this.googleAuth = new google_auth_library_1.GoogleAuth({
|
|
40
|
+
scopes: SCOPES,
|
|
41
|
+
clientOptions: {
|
|
42
|
+
transporterOptions: {
|
|
43
|
+
agent: httpAgent,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async getAccessToken() {
|
|
49
|
+
if (!this.authClient) {
|
|
50
|
+
this.authClient = await this.googleAuth.getClient();
|
|
51
|
+
}
|
|
52
|
+
await this.authClient.getAccessToken();
|
|
53
|
+
const credentials = this.authClient.credentials;
|
|
54
|
+
this.quotaProjectId = this.authClient.quotaProjectId;
|
|
55
|
+
return populateCredential(credentials);
|
|
56
|
+
}
|
|
57
|
+
async getProjectId() {
|
|
58
|
+
if (!this.projectId) {
|
|
59
|
+
this.projectId = await this.googleAuth.getProjectId();
|
|
60
|
+
}
|
|
61
|
+
return Promise.resolve(this.projectId);
|
|
62
|
+
}
|
|
63
|
+
getQuotaProjectId() {
|
|
64
|
+
if (!this.quotaProjectId) {
|
|
65
|
+
this.quotaProjectId = this.authClient?.quotaProjectId;
|
|
66
|
+
}
|
|
67
|
+
return this.quotaProjectId;
|
|
68
|
+
}
|
|
69
|
+
async isComputeEngineCredential() {
|
|
70
|
+
if (!this.authClient) {
|
|
71
|
+
this.authClient = await this.googleAuth.getClient();
|
|
72
|
+
}
|
|
73
|
+
return Promise.resolve(this.authClient instanceof google_auth_library_1.Compute);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* getIDToken returns a OIDC token from the compute metadata service
|
|
77
|
+
* that can be used to make authenticated calls to audience
|
|
78
|
+
* @param audience the URL the returned ID token will be used to call.
|
|
79
|
+
*/
|
|
80
|
+
async getIDToken(audience) {
|
|
81
|
+
if (await this.isComputeEngineCredential()) {
|
|
82
|
+
return this.authClient.fetchIdToken(audience);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Credentials type should be Compute Engine Credentials.');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async getServiceAccountEmail() {
|
|
89
|
+
if (this.accountId) {
|
|
90
|
+
return Promise.resolve(this.accountId);
|
|
91
|
+
}
|
|
92
|
+
const { client_email: clientEmail } = await this.googleAuth.getCredentials();
|
|
93
|
+
this.accountId = clientEmail ?? '';
|
|
94
|
+
return Promise.resolve(this.accountId);
|
|
41
95
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
})();
|
|
45
|
-
const GCLOUD_CREDENTIAL_SUFFIX = 'gcloud/application_default_credentials.json';
|
|
46
|
-
const GCLOUD_CREDENTIAL_PATH = configDir && path.resolve(configDir, GCLOUD_CREDENTIAL_SUFFIX);
|
|
47
|
-
const REFRESH_TOKEN_HOST = 'www.googleapis.com';
|
|
48
|
-
const REFRESH_TOKEN_PATH = '/oauth2/v4/token';
|
|
49
|
-
const ONE_HOUR_IN_SECONDS = 60 * 60;
|
|
50
|
-
const JWT_ALGORITHM = 'RS256';
|
|
96
|
+
}
|
|
97
|
+
exports.ApplicationDefaultCredential = ApplicationDefaultCredential;
|
|
51
98
|
/**
|
|
52
99
|
* Implementation of Credential that uses a service account.
|
|
53
100
|
*/
|
|
@@ -57,12 +104,13 @@ class ServiceAccountCredential {
|
|
|
57
104
|
*
|
|
58
105
|
* @param serviceAccountPathOrObject - Service account json object or path to a service account json file.
|
|
59
106
|
* @param httpAgent - Optional http.Agent to use when calling the remote token server.
|
|
60
|
-
* @param implicit - An
|
|
107
|
+
* @param implicit - An optional boolean indicating whether this credential was implicitly discovered from the
|
|
61
108
|
* environment, as opposed to being explicitly specified by the developer.
|
|
62
109
|
*
|
|
63
110
|
* @constructor
|
|
64
111
|
*/
|
|
65
112
|
constructor(serviceAccountPathOrObject, httpAgent, implicit = false) {
|
|
113
|
+
this.serviceAccountPathOrObject = serviceAccountPathOrObject;
|
|
66
114
|
this.httpAgent = httpAgent;
|
|
67
115
|
this.implicit = implicit;
|
|
68
116
|
const serviceAccount = (typeof serviceAccountPathOrObject === 'string') ?
|
|
@@ -71,43 +119,24 @@ class ServiceAccountCredential {
|
|
|
71
119
|
this.projectId = serviceAccount.projectId;
|
|
72
120
|
this.privateKey = serviceAccount.privateKey;
|
|
73
121
|
this.clientEmail = serviceAccount.clientEmail;
|
|
74
|
-
this.httpClient = new api_request_1.HttpClient();
|
|
75
|
-
}
|
|
76
|
-
getAccessToken() {
|
|
77
|
-
const token = this.createAuthJwt_();
|
|
78
|
-
const postData = 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3A' +
|
|
79
|
-
'grant-type%3Ajwt-bearer&assertion=' + token;
|
|
80
|
-
const request = {
|
|
81
|
-
method: 'POST',
|
|
82
|
-
url: `https://${GOOGLE_AUTH_TOKEN_HOST}${GOOGLE_AUTH_TOKEN_PATH}`,
|
|
83
|
-
headers: {
|
|
84
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
85
|
-
},
|
|
86
|
-
data: postData,
|
|
87
|
-
httpAgent: this.httpAgent,
|
|
88
|
-
};
|
|
89
|
-
return requestAccessToken(this.httpClient, request);
|
|
90
122
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
issuer: this.clientEmail,
|
|
109
|
-
algorithm: JWT_ALGORITHM,
|
|
110
|
-
});
|
|
123
|
+
getGoogleAuth() {
|
|
124
|
+
if (this.googleAuth) {
|
|
125
|
+
return this.googleAuth;
|
|
126
|
+
}
|
|
127
|
+
const { auth, client } = populateGoogleAuth(this.serviceAccountPathOrObject, this.httpAgent);
|
|
128
|
+
this.googleAuth = auth;
|
|
129
|
+
this.authClient = client;
|
|
130
|
+
return this.googleAuth;
|
|
131
|
+
}
|
|
132
|
+
async getAccessToken() {
|
|
133
|
+
const googleAuth = this.getGoogleAuth();
|
|
134
|
+
if (this.authClient === undefined) {
|
|
135
|
+
this.authClient = await googleAuth.getClient();
|
|
136
|
+
}
|
|
137
|
+
await this.authClient.getAccessToken();
|
|
138
|
+
const credentials = this.authClient.credentials;
|
|
139
|
+
return populateCredential(credentials);
|
|
111
140
|
}
|
|
112
141
|
}
|
|
113
142
|
exports.ServiceAccountCredential = ServiceAccountCredential;
|
|
@@ -154,71 +183,6 @@ class ServiceAccount {
|
|
|
154
183
|
}
|
|
155
184
|
}
|
|
156
185
|
}
|
|
157
|
-
/**
|
|
158
|
-
* Implementation of Credential that gets access tokens from the metadata service available
|
|
159
|
-
* in the Google Cloud Platform. This authenticates the process as the default service account
|
|
160
|
-
* of an App Engine instance or Google Compute Engine machine.
|
|
161
|
-
*/
|
|
162
|
-
class ComputeEngineCredential {
|
|
163
|
-
constructor(httpAgent) {
|
|
164
|
-
this.httpClient = new api_request_1.HttpClient();
|
|
165
|
-
this.httpAgent = httpAgent;
|
|
166
|
-
}
|
|
167
|
-
getAccessToken() {
|
|
168
|
-
const request = this.buildRequest(GOOGLE_METADATA_SERVICE_TOKEN_PATH);
|
|
169
|
-
return requestAccessToken(this.httpClient, request);
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* getIDToken returns a OIDC token from the compute metadata service
|
|
173
|
-
* that can be used to make authenticated calls to audience
|
|
174
|
-
* @param audience the URL the returned ID token will be used to call.
|
|
175
|
-
*/
|
|
176
|
-
getIDToken(audience) {
|
|
177
|
-
const request = this.buildRequest(`${GOOGLE_METADATA_SERVICE_IDENTITY_PATH}?audience=${audience}`);
|
|
178
|
-
return requestIDToken(this.httpClient, request);
|
|
179
|
-
}
|
|
180
|
-
getProjectId() {
|
|
181
|
-
if (this.projectId) {
|
|
182
|
-
return Promise.resolve(this.projectId);
|
|
183
|
-
}
|
|
184
|
-
const request = this.buildRequest(GOOGLE_METADATA_SERVICE_PROJECT_ID_PATH);
|
|
185
|
-
return this.httpClient.send(request)
|
|
186
|
-
.then((resp) => {
|
|
187
|
-
this.projectId = resp.text;
|
|
188
|
-
return this.projectId;
|
|
189
|
-
})
|
|
190
|
-
.catch((err) => {
|
|
191
|
-
const detail = (err instanceof api_request_1.RequestResponseError) ? getDetailFromResponse(err.response) : err.message;
|
|
192
|
-
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, `Failed to determine project ID: ${detail}`);
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
getServiceAccountEmail() {
|
|
196
|
-
if (this.accountId) {
|
|
197
|
-
return Promise.resolve(this.accountId);
|
|
198
|
-
}
|
|
199
|
-
const request = this.buildRequest(GOOGLE_METADATA_SERVICE_ACCOUNT_ID_PATH);
|
|
200
|
-
return this.httpClient.send(request)
|
|
201
|
-
.then((resp) => {
|
|
202
|
-
this.accountId = resp.text;
|
|
203
|
-
return this.accountId;
|
|
204
|
-
})
|
|
205
|
-
.catch((err) => {
|
|
206
|
-
const detail = (err instanceof api_request_1.RequestResponseError) ? getDetailFromResponse(err.response) : err.message;
|
|
207
|
-
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, `Failed to determine service account email: ${detail}`);
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
buildRequest(urlPath) {
|
|
211
|
-
return {
|
|
212
|
-
method: 'GET',
|
|
213
|
-
url: `http://${GOOGLE_METADATA_SERVICE_HOST}${urlPath}`,
|
|
214
|
-
headers: {
|
|
215
|
-
'Metadata-Flavor': 'Google',
|
|
216
|
-
},
|
|
217
|
-
httpAgent: this.httpAgent,
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
exports.ComputeEngineCredential = ComputeEngineCredential;
|
|
222
186
|
/**
|
|
223
187
|
* Implementation of Credential that gets access tokens from refresh tokens.
|
|
224
188
|
*/
|
|
@@ -235,28 +199,30 @@ class RefreshTokenCredential {
|
|
|
235
199
|
* @constructor
|
|
236
200
|
*/
|
|
237
201
|
constructor(refreshTokenPathOrObject, httpAgent, implicit = false) {
|
|
202
|
+
this.refreshTokenPathOrObject = refreshTokenPathOrObject;
|
|
238
203
|
this.httpAgent = httpAgent;
|
|
239
204
|
this.implicit = implicit;
|
|
240
|
-
|
|
241
|
-
RefreshToken.
|
|
242
|
-
:
|
|
243
|
-
this.httpClient = new api_request_1.HttpClient();
|
|
205
|
+
(typeof refreshTokenPathOrObject === 'string') ?
|
|
206
|
+
RefreshToken.validateFromPath(refreshTokenPathOrObject)
|
|
207
|
+
: RefreshToken.validateFromJSON(refreshTokenPathOrObject);
|
|
244
208
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
|
|
209
|
+
getGoogleAuth() {
|
|
210
|
+
if (this.googleAuth) {
|
|
211
|
+
return this.googleAuth;
|
|
212
|
+
}
|
|
213
|
+
const { auth, client } = populateGoogleAuth(this.refreshTokenPathOrObject, this.httpAgent);
|
|
214
|
+
this.googleAuth = auth;
|
|
215
|
+
this.authClient = client;
|
|
216
|
+
return this.googleAuth;
|
|
217
|
+
}
|
|
218
|
+
async getAccessToken() {
|
|
219
|
+
const googleAuth = this.getGoogleAuth();
|
|
220
|
+
if (this.authClient === undefined) {
|
|
221
|
+
this.authClient = await googleAuth.getClient();
|
|
222
|
+
}
|
|
223
|
+
await this.authClient.getAccessToken();
|
|
224
|
+
const credentials = this.authClient.credentials;
|
|
225
|
+
return populateCredential(credentials);
|
|
260
226
|
}
|
|
261
227
|
}
|
|
262
228
|
exports.RefreshTokenCredential = RefreshTokenCredential;
|
|
@@ -265,31 +231,32 @@ class RefreshToken {
|
|
|
265
231
|
* Tries to load a RefreshToken from a path. Throws if the path doesn't exist or the
|
|
266
232
|
* data at the path is invalid.
|
|
267
233
|
*/
|
|
268
|
-
static
|
|
234
|
+
static validateFromPath(filePath) {
|
|
269
235
|
try {
|
|
270
|
-
|
|
236
|
+
RefreshToken.validateFromJSON(JSON.parse(fs.readFileSync(filePath, 'utf8')));
|
|
271
237
|
}
|
|
272
238
|
catch (error) {
|
|
273
239
|
// Throw a nicely formed error message if the file contents cannot be parsed
|
|
274
240
|
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse refresh token file: ' + error);
|
|
275
241
|
}
|
|
276
242
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
copyAttr(
|
|
280
|
-
copyAttr(
|
|
281
|
-
copyAttr(
|
|
243
|
+
static validateFromJSON(json) {
|
|
244
|
+
const creds = { clientId: '', clientSecret: '', refreshToken: '', type: '' };
|
|
245
|
+
copyAttr(creds, json, 'clientId', 'client_id');
|
|
246
|
+
copyAttr(creds, json, 'clientSecret', 'client_secret');
|
|
247
|
+
copyAttr(creds, json, 'refreshToken', 'refresh_token');
|
|
248
|
+
copyAttr(creds, json, 'type', 'type');
|
|
282
249
|
let errorMessage;
|
|
283
|
-
if (!util.isNonEmptyString(
|
|
250
|
+
if (!util.isNonEmptyString(creds.clientId)) {
|
|
284
251
|
errorMessage = 'Refresh token must contain a "client_id" property.';
|
|
285
252
|
}
|
|
286
|
-
else if (!util.isNonEmptyString(
|
|
253
|
+
else if (!util.isNonEmptyString(creds.clientSecret)) {
|
|
287
254
|
errorMessage = 'Refresh token must contain a "client_secret" property.';
|
|
288
255
|
}
|
|
289
|
-
else if (!util.isNonEmptyString(
|
|
256
|
+
else if (!util.isNonEmptyString(creds.refreshToken)) {
|
|
290
257
|
errorMessage = 'Refresh token must contain a "refresh_token" property.';
|
|
291
258
|
}
|
|
292
|
-
else if (!util.isNonEmptyString(
|
|
259
|
+
else if (!util.isNonEmptyString(creds.type)) {
|
|
293
260
|
errorMessage = 'Refresh token must contain a "type" property.';
|
|
294
261
|
}
|
|
295
262
|
if (typeof errorMessage !== 'undefined') {
|
|
@@ -313,67 +280,63 @@ class ImpersonatedServiceAccountCredential {
|
|
|
313
280
|
* @constructor
|
|
314
281
|
*/
|
|
315
282
|
constructor(impersonatedServiceAccountPathOrObject, httpAgent, implicit = false) {
|
|
283
|
+
this.impersonatedServiceAccountPathOrObject = impersonatedServiceAccountPathOrObject;
|
|
316
284
|
this.httpAgent = httpAgent;
|
|
317
285
|
this.implicit = implicit;
|
|
318
|
-
|
|
319
|
-
ImpersonatedServiceAccount.
|
|
320
|
-
:
|
|
321
|
-
this.httpClient = new api_request_1.HttpClient();
|
|
286
|
+
(typeof impersonatedServiceAccountPathOrObject === 'string') ?
|
|
287
|
+
ImpersonatedServiceAccount.validateFromPath(impersonatedServiceAccountPathOrObject)
|
|
288
|
+
: ImpersonatedServiceAccount.validateFromJSON(impersonatedServiceAccountPathOrObject);
|
|
322
289
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
|
|
290
|
+
getGoogleAuth() {
|
|
291
|
+
if (this.googleAuth) {
|
|
292
|
+
return this.googleAuth;
|
|
293
|
+
}
|
|
294
|
+
const { auth, client } = populateGoogleAuth(this.impersonatedServiceAccountPathOrObject, this.httpAgent);
|
|
295
|
+
this.googleAuth = auth;
|
|
296
|
+
this.authClient = client;
|
|
297
|
+
return this.googleAuth;
|
|
298
|
+
}
|
|
299
|
+
async getAccessToken() {
|
|
300
|
+
const googleAuth = this.getGoogleAuth();
|
|
301
|
+
if (this.authClient === undefined) {
|
|
302
|
+
this.authClient = await googleAuth.getClient();
|
|
303
|
+
}
|
|
304
|
+
await this.authClient.getAccessToken();
|
|
305
|
+
const credentials = this.authClient.credentials;
|
|
306
|
+
return populateCredential(credentials);
|
|
338
307
|
}
|
|
339
308
|
}
|
|
340
309
|
exports.ImpersonatedServiceAccountCredential = ImpersonatedServiceAccountCredential;
|
|
341
310
|
/**
|
|
342
|
-
* A
|
|
311
|
+
* A helper class to validate the properties necessary to use impersonated service account credentials.
|
|
343
312
|
*/
|
|
344
313
|
class ImpersonatedServiceAccount {
|
|
345
314
|
/*
|
|
346
315
|
* Tries to load a ImpersonatedServiceAccount from a path. Throws if the path doesn't exist or the
|
|
347
316
|
* data at the path is invalid.
|
|
348
317
|
*/
|
|
349
|
-
static
|
|
318
|
+
static validateFromPath(filePath) {
|
|
350
319
|
try {
|
|
351
|
-
|
|
320
|
+
ImpersonatedServiceAccount.validateFromJSON(JSON.parse(fs.readFileSync(filePath, 'utf8')));
|
|
352
321
|
}
|
|
353
322
|
catch (error) {
|
|
354
323
|
// Throw a nicely formed error message if the file contents cannot be parsed
|
|
355
324
|
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse impersonated service account file: ' + error);
|
|
356
325
|
}
|
|
357
326
|
}
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
if (sourceCredentials) {
|
|
361
|
-
copyAttr(this, sourceCredentials, 'clientId', 'client_id');
|
|
362
|
-
copyAttr(this, sourceCredentials, 'clientSecret', 'client_secret');
|
|
363
|
-
copyAttr(this, sourceCredentials, 'refreshToken', 'refresh_token');
|
|
364
|
-
copyAttr(this, sourceCredentials, 'type', 'type');
|
|
365
|
-
}
|
|
327
|
+
static validateFromJSON(json) {
|
|
328
|
+
const { client_id: clientId, client_secret: clientSecret, refresh_token: refreshToken, type } = json['source_credentials'];
|
|
366
329
|
let errorMessage;
|
|
367
|
-
if (!util.isNonEmptyString(
|
|
330
|
+
if (!util.isNonEmptyString(clientId)) {
|
|
368
331
|
errorMessage = 'Impersonated Service Account must contain a "source_credentials.client_id" property.';
|
|
369
332
|
}
|
|
370
|
-
else if (!util.isNonEmptyString(
|
|
333
|
+
else if (!util.isNonEmptyString(clientSecret)) {
|
|
371
334
|
errorMessage = 'Impersonated Service Account must contain a "source_credentials.client_secret" property.';
|
|
372
335
|
}
|
|
373
|
-
else if (!util.isNonEmptyString(
|
|
336
|
+
else if (!util.isNonEmptyString(refreshToken)) {
|
|
374
337
|
errorMessage = 'Impersonated Service Account must contain a "source_credentials.refresh_token" property.';
|
|
375
338
|
}
|
|
376
|
-
else if (!util.isNonEmptyString(
|
|
339
|
+
else if (!util.isNonEmptyString(type)) {
|
|
377
340
|
errorMessage = 'Impersonated Service Account must contain a "source_credentials.type" property.';
|
|
378
341
|
}
|
|
379
342
|
if (typeof errorMessage !== 'undefined') {
|
|
@@ -382,33 +345,17 @@ class ImpersonatedServiceAccount {
|
|
|
382
345
|
}
|
|
383
346
|
}
|
|
384
347
|
/**
|
|
385
|
-
* Checks if the given credential was loaded via the application default credentials mechanism.
|
|
386
|
-
* includes all ComputeEngineCredential instances, and the ServiceAccountCredential and RefreshTokenCredential
|
|
387
|
-
* instances that were loaded from well-known files or environment variables, rather than being explicitly
|
|
388
|
-
* instantiated.
|
|
348
|
+
* Checks if the given credential was loaded via the application default credentials mechanism.
|
|
389
349
|
*
|
|
390
350
|
* @param credential - The credential instance to check.
|
|
391
351
|
*/
|
|
392
352
|
function isApplicationDefault(credential) {
|
|
393
|
-
return credential instanceof
|
|
394
|
-
(credential instanceof
|
|
395
|
-
(credential instanceof RefreshTokenCredential && credential.implicit) ||
|
|
396
|
-
(credential instanceof ImpersonatedServiceAccountCredential && credential.implicit);
|
|
353
|
+
return credential instanceof ApplicationDefaultCredential ||
|
|
354
|
+
(credential instanceof RefreshTokenCredential && credential.implicit);
|
|
397
355
|
}
|
|
398
|
-
exports.isApplicationDefault = isApplicationDefault;
|
|
399
356
|
function getApplicationDefault(httpAgent) {
|
|
400
|
-
|
|
401
|
-
return credentialFromFile(process.env.GOOGLE_APPLICATION_CREDENTIALS, httpAgent, false);
|
|
402
|
-
}
|
|
403
|
-
// It is OK to not have this file. If it is present, it must be valid.
|
|
404
|
-
if (GCLOUD_CREDENTIAL_PATH) {
|
|
405
|
-
const credential = credentialFromFile(GCLOUD_CREDENTIAL_PATH, httpAgent, true);
|
|
406
|
-
if (credential)
|
|
407
|
-
return credential;
|
|
408
|
-
}
|
|
409
|
-
return new ComputeEngineCredential(httpAgent);
|
|
357
|
+
return new ApplicationDefaultCredential(httpAgent);
|
|
410
358
|
}
|
|
411
|
-
exports.getApplicationDefault = getApplicationDefault;
|
|
412
359
|
/**
|
|
413
360
|
* Copies the specified property from one object to another.
|
|
414
361
|
*
|
|
@@ -427,89 +374,42 @@ function copyAttr(to, from, key, alt) {
|
|
|
427
374
|
}
|
|
428
375
|
}
|
|
429
376
|
/**
|
|
430
|
-
*
|
|
377
|
+
* Populate google-auth-library GoogleAuth credentials type.
|
|
431
378
|
*/
|
|
432
|
-
function
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Obtain a new OIDC token by making a remote service call.
|
|
445
|
-
*/
|
|
446
|
-
function requestIDToken(client, request) {
|
|
447
|
-
return client.send(request).then((resp) => {
|
|
448
|
-
if (!resp.text) {
|
|
449
|
-
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Unexpected response while fetching id token: response.text is undefined');
|
|
450
|
-
}
|
|
451
|
-
return resp.text;
|
|
452
|
-
}).catch((err) => {
|
|
453
|
-
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, getErrorMessage(err));
|
|
379
|
+
function populateGoogleAuth(keyFile, httpAgent) {
|
|
380
|
+
let client;
|
|
381
|
+
const auth = new google_auth_library_1.GoogleAuth({
|
|
382
|
+
scopes: SCOPES,
|
|
383
|
+
clientOptions: {
|
|
384
|
+
transporterOptions: {
|
|
385
|
+
agent: httpAgent,
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
keyFile: (typeof keyFile === 'string') ? keyFile : undefined,
|
|
454
389
|
});
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
*/
|
|
459
|
-
function getErrorMessage(err) {
|
|
460
|
-
const detail = (err instanceof api_request_1.RequestResponseError) ? getDetailFromResponse(err.response) : err.message;
|
|
461
|
-
return `Error fetching access token: ${detail}`;
|
|
462
|
-
}
|
|
463
|
-
/**
|
|
464
|
-
* Extracts details from the given HTTP error response, and returns a human-readable description. If
|
|
465
|
-
* the response is JSON-formatted, looks up the error and error_description fields sent by the
|
|
466
|
-
* Google Auth servers. Otherwise returns the entire response payload as the error detail.
|
|
467
|
-
*/
|
|
468
|
-
function getDetailFromResponse(response) {
|
|
469
|
-
if (response.isJson() && response.data.error) {
|
|
470
|
-
const json = response.data;
|
|
471
|
-
let detail = json.error;
|
|
472
|
-
if (json.error_description) {
|
|
473
|
-
detail += ' (' + json.error_description + ')';
|
|
474
|
-
}
|
|
475
|
-
return detail;
|
|
476
|
-
}
|
|
477
|
-
return response.text || 'Missing error payload';
|
|
478
|
-
}
|
|
479
|
-
function credentialFromFile(filePath, httpAgent, ignoreMissing) {
|
|
480
|
-
const credentialsFile = readCredentialFile(filePath, ignoreMissing);
|
|
481
|
-
if (typeof credentialsFile !== 'object' || credentialsFile === null) {
|
|
482
|
-
if (ignoreMissing) {
|
|
483
|
-
return null;
|
|
390
|
+
if (typeof keyFile === 'object') {
|
|
391
|
+
if (!util.isNonNullObject(keyFile)) {
|
|
392
|
+
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Service account must be an object.');
|
|
484
393
|
}
|
|
485
|
-
|
|
394
|
+
client = auth.fromJSON(keyFile);
|
|
486
395
|
}
|
|
487
|
-
|
|
488
|
-
return new ServiceAccountCredential(credentialsFile, httpAgent, true);
|
|
489
|
-
}
|
|
490
|
-
if (credentialsFile.type === 'authorized_user') {
|
|
491
|
-
return new RefreshTokenCredential(credentialsFile, httpAgent, true);
|
|
492
|
-
}
|
|
493
|
-
if (credentialsFile.type === 'impersonated_service_account') {
|
|
494
|
-
return new ImpersonatedServiceAccountCredential(credentialsFile, httpAgent, true);
|
|
495
|
-
}
|
|
496
|
-
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Invalid contents in the credentials file');
|
|
396
|
+
return { auth, client };
|
|
497
397
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL,
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
}
|
|
398
|
+
/**
|
|
399
|
+
* Populate GoogleOAuthAccessToken credentials from google-auth-library Credentials type.
|
|
400
|
+
*/
|
|
401
|
+
function populateCredential(credentials) {
|
|
402
|
+
const accessToken = credentials?.access_token;
|
|
403
|
+
const expiryDate = credentials?.expiry_date;
|
|
404
|
+
if (typeof accessToken !== 'string')
|
|
405
|
+
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse Google auth credential: access_token must be a non empty string.');
|
|
406
|
+
if (typeof expiryDate !== 'number')
|
|
407
|
+
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse Google auth credential: Invalid expiry_date.');
|
|
408
|
+
return {
|
|
409
|
+
...credentials,
|
|
410
|
+
access_token: accessToken,
|
|
411
|
+
// inverse operation of following
|
|
412
|
+
// https://github.com/googleapis/google-auth-library-nodejs/blob/5ed910513451c82e2551777a3e2212964799ef8e/src/auth/baseexternalclient.ts#L446-L446
|
|
413
|
+
expires_in: Math.floor((expiryDate - new Date().getTime()) / 1000),
|
|
414
|
+
};
|
|
515
415
|
}
|
package/lib/app/credential.d.ts
CHANGED
package/lib/app/credential.js
CHANGED
package/lib/app/firebase-app.js
CHANGED