cloudfire-auth 0.1.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/LICENSE +21 -0
- package/NOTICE +13 -0
- package/README.md +94 -0
- package/dist/CloudFireAuth.d.ts +291 -0
- package/dist/CloudFireAuth.js +346 -0
- package/dist/google-auth/get-oauth-2-token.d.ts +15 -0
- package/dist/google-auth/get-oauth-2-token.js +66 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/rest-api/create-user.d.ts +2 -0
- package/dist/rest-api/create-user.js +3 -0
- package/dist/rest-api/delete-user.d.ts +175 -0
- package/dist/rest-api/delete-user.js +207 -0
- package/dist/rest-api/delete-users.d.ts +2 -0
- package/dist/rest-api/delete-users.js +3 -0
- package/dist/rest-api/get-user-by-email.d.ts +2 -0
- package/dist/rest-api/get-user-by-email.js +3 -0
- package/dist/rest-api/get-user-by-phone-number.d.ts +2 -0
- package/dist/rest-api/get-user-by-phone-number.js +3 -0
- package/dist/rest-api/get-user-by-provider-uid.d.ts +2 -0
- package/dist/rest-api/get-user-by-provider-uid.js +3 -0
- package/dist/rest-api/get-user.d.ts +99 -0
- package/dist/rest-api/get-user.js +177 -0
- package/dist/rest-api/get-users.d.ts +2 -0
- package/dist/rest-api/get-users.js +3 -0
- package/dist/rest-api/list-users.d.ts +2 -0
- package/dist/rest-api/list-users.js +3 -0
- package/dist/rest-api/revoke-refresh-tokens.d.ts +116 -0
- package/dist/rest-api/revoke-refresh-tokens.js +151 -0
- package/dist/rest-api/set-custom-user-claims.d.ts +173 -0
- package/dist/rest-api/set-custom-user-claims.js +261 -0
- package/dist/rest-api/standard-request.d.ts +12 -0
- package/dist/rest-api/standard-request.js +20 -0
- package/dist/rest-api/update-user.d.ts +175 -0
- package/dist/rest-api/update-user.js +375 -0
- package/dist/rest-api/verify-id-token.d.ts +127 -0
- package/dist/rest-api/verify-id-token.js +273 -0
- package/dist/rest-api/verify-session-cookie.d.ts +2 -0
- package/dist/rest-api/verify-session-cookie.js +3 -0
- package/dist/types/firebase-admin/auth-config.d.ts +851 -0
- package/dist/types/firebase-admin/auth-config.js +1 -0
- package/dist/types/firebase-admin/identifier.d.ts +57 -0
- package/dist/types/firebase-admin/identifier.js +1 -0
- package/dist/types/firebase-admin/index.d.ts +153 -0
- package/dist/types/firebase-admin/index.js +1 -0
- package/dist/types/firebase-admin/token-verifier.d.ts +219 -0
- package/dist/types/firebase-admin/token-verifier.js +1 -0
- package/dist/types/firebase-admin/user-record.d.ts +289 -0
- package/dist/types/firebase-admin/user-record.js +1 -0
- package/dist/types/google-auth.d.ts +25 -0
- package/dist/types/google-auth.js +1 -0
- package/dist/types/service-account-key.d.ts +13 -0
- package/dist/types/service-account-key.js +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +1 -0
- package/package.json +56 -0
- package/third_party/firebase-admin-license.txt +201 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/*! firebase-admin v13.4.0 */
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright 2021 Google Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
// Rest API
|
|
18
|
+
import { verifyIdTokenHandler } from "./rest-api/verify-id-token.js";
|
|
19
|
+
import { getUserHandler } from "./rest-api/get-user.js";
|
|
20
|
+
import { getUserByEmailHandler } from "./rest-api/get-user-by-email.js";
|
|
21
|
+
import { getUserByPhoneNumberHandler } from "./rest-api/get-user-by-phone-number.js";
|
|
22
|
+
import { getUserByProviderUidHandler } from "./rest-api/get-user-by-provider-uid.js";
|
|
23
|
+
import { getUsersHandler } from "./rest-api/get-users.js";
|
|
24
|
+
import { listUsersHandler } from "./rest-api/list-users.js";
|
|
25
|
+
import { createUserHandler } from "./rest-api/create-user.js";
|
|
26
|
+
import { deleteUserHandler } from "./rest-api/delete-user.js";
|
|
27
|
+
import { deleteUsersHandler } from "./rest-api/delete-users.js";
|
|
28
|
+
import { updateUserHandler } from "./rest-api/update-user.js";
|
|
29
|
+
import { setCustomUserClaimsHandler } from "./rest-api/set-custom-user-claims.js";
|
|
30
|
+
import { revokeRefreshTokensHandler } from "./rest-api/revoke-refresh-tokens.js";
|
|
31
|
+
import { verifySessionCookieHandler } from "./rest-api/verify-session-cookie.js";
|
|
32
|
+
// Google Auth
|
|
33
|
+
import { getOauth2AccessTokenHandler } from "./google-auth/get-oauth-2-token.js";
|
|
34
|
+
export class CloudFireAuth {
|
|
35
|
+
projectId;
|
|
36
|
+
serviceAccountKey;
|
|
37
|
+
oauth2Token;
|
|
38
|
+
kvNamespace;
|
|
39
|
+
constructor(serviceAccountKey, kvNamespace) {
|
|
40
|
+
this.projectId = serviceAccountKey.project_id;
|
|
41
|
+
this.serviceAccountKey = serviceAccountKey;
|
|
42
|
+
this.kvNamespace = kvNamespace;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Verifies a Firebase ID token (JWT). If the token is valid, the promise is
|
|
46
|
+
* fulfilled with the token's decoded claims; otherwise, the promise is
|
|
47
|
+
* rejected.
|
|
48
|
+
*
|
|
49
|
+
* If `checkRevoked` is set to true, first verifies whether the corresponding
|
|
50
|
+
* user is disabled. If yes, an `auth/user-disabled` error is thrown. If no,
|
|
51
|
+
* verifies if the session corresponding to the ID token was revoked. If the
|
|
52
|
+
* corresponding user's session was invalidated, an `auth/id-token-revoked`
|
|
53
|
+
* error is thrown. If not specified the check is not applied.
|
|
54
|
+
*
|
|
55
|
+
* See {@link https://firebase.google.com/docs/auth/admin/verify-id-tokens | Verify ID Tokens}
|
|
56
|
+
* for code samples and detailed documentation.
|
|
57
|
+
*
|
|
58
|
+
* @param idToken - The ID token to verify.
|
|
59
|
+
* @param checkRevoked - Whether to check if the ID token was revoked.
|
|
60
|
+
* This requires an extra request to the Firebase Auth backend to check
|
|
61
|
+
* the `tokensValidAfterTime` time for the corresponding user.
|
|
62
|
+
* When not specified, this additional check is not applied.
|
|
63
|
+
*
|
|
64
|
+
* @returns A promise fulfilled with the
|
|
65
|
+
* token's decoded claims if the ID token is valid; otherwise, a rejected
|
|
66
|
+
* promise.
|
|
67
|
+
*/
|
|
68
|
+
async verifyIdToken(idToken, checkRevoked) {
|
|
69
|
+
const oauth2Token = await this.getOauth2AccessToken();
|
|
70
|
+
return await verifyIdTokenHandler(idToken, this.projectId, oauth2Token, this.kvNamespace, checkRevoked);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Gets the user data for the user corresponding to a given `uid`.
|
|
74
|
+
*
|
|
75
|
+
* See {@link https://firebase.google.com/docs/auth/admin/manage-users#retrieve_user_data | Retrieve user data}
|
|
76
|
+
* for code samples and detailed documentation.
|
|
77
|
+
*
|
|
78
|
+
* @param uid - The `uid` corresponding to the user whose data to fetch.
|
|
79
|
+
*
|
|
80
|
+
* @returns A promise fulfilled with the user
|
|
81
|
+
* data corresponding to the provided `uid`.
|
|
82
|
+
*/
|
|
83
|
+
async getUser(uid) {
|
|
84
|
+
const oauth2Token = await this.getOauth2AccessToken();
|
|
85
|
+
return await getUserHandler(uid, oauth2Token);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Gets the user data for the user corresponding to a given email.
|
|
89
|
+
*
|
|
90
|
+
* See {@link https://firebase.google.com/docs/auth/admin/manage-users#retrieve_user_data | Retrieve user data}
|
|
91
|
+
* for code samples and detailed documentation.
|
|
92
|
+
*
|
|
93
|
+
* @param email - The email corresponding to the user whose data to
|
|
94
|
+
* fetch.
|
|
95
|
+
*
|
|
96
|
+
* @returns A promise fulfilled with the user
|
|
97
|
+
* data corresponding to the provided email.
|
|
98
|
+
*/
|
|
99
|
+
async getUserByEmail(email) {
|
|
100
|
+
return await getUserByEmailHandler(email);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Gets the user data for the user corresponding to a given phone number. The
|
|
104
|
+
* phone number has to conform to the E.164 specification.
|
|
105
|
+
*
|
|
106
|
+
* See {@link https://firebase.google.com/docs/auth/admin/manage-users#retrieve_user_data | Retrieve user data}
|
|
107
|
+
* for code samples and detailed documentation.
|
|
108
|
+
*
|
|
109
|
+
* @param phoneNumber - The phone number corresponding to the user whose
|
|
110
|
+
* data to fetch.
|
|
111
|
+
*
|
|
112
|
+
* @returns A promise fulfilled with the user
|
|
113
|
+
* data corresponding to the provided phone number.
|
|
114
|
+
*/
|
|
115
|
+
async getUserByPhoneNumber(phoneNumber) {
|
|
116
|
+
return await getUserByPhoneNumberHandler(phoneNumber);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Gets the user data for the user corresponding to a given provider id.
|
|
120
|
+
*
|
|
121
|
+
* See {@link https://firebase.google.com/docs/auth/admin/manage-users#retrieve_user_data | Retrieve user data}
|
|
122
|
+
* for code samples and detailed documentation.
|
|
123
|
+
*
|
|
124
|
+
* @param providerId - The provider ID, for example, "google.com" for the
|
|
125
|
+
* Google provider.
|
|
126
|
+
* @param uid - The user identifier for the given provider.
|
|
127
|
+
*
|
|
128
|
+
* @returns A promise fulfilled with the user data corresponding to the
|
|
129
|
+
* given provider id.
|
|
130
|
+
*/
|
|
131
|
+
async getUserByProviderUid(providerId, uid) {
|
|
132
|
+
return await getUserByProviderUidHandler(providerId, uid);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Gets the user data corresponding to the specified identifiers.
|
|
136
|
+
*
|
|
137
|
+
* There are no ordering guarantees; in particular, the nth entry in the result list is not
|
|
138
|
+
* guaranteed to correspond to the nth entry in the input parameters list.
|
|
139
|
+
*
|
|
140
|
+
* Only a maximum of 100 identifiers may be supplied. If more than 100 identifiers are supplied,
|
|
141
|
+
* this method throws a FirebaseAuthError.
|
|
142
|
+
*
|
|
143
|
+
* @param identifiers - The identifiers used to indicate which user records should be returned.
|
|
144
|
+
* Must not have more than 100 entries.
|
|
145
|
+
* @returns A promise that resolves to the corresponding user records.
|
|
146
|
+
* @throws FirebaseAuthError If any of the identifiers are invalid or if more than 100
|
|
147
|
+
* identifiers are specified.
|
|
148
|
+
*/
|
|
149
|
+
async getUsers(identifiers) {
|
|
150
|
+
return await getUsersHandler(identifiers);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Retrieves a list of users (single batch only) with a size of `maxResults`
|
|
154
|
+
* starting from the offset as specified by `pageToken`. This is used to
|
|
155
|
+
* retrieve all the users of a specified project in batches.
|
|
156
|
+
*
|
|
157
|
+
* See {@link https://firebase.google.com/docs/auth/admin/manage-users#list_all_users | List all users}
|
|
158
|
+
* for code samples and detailed documentation.
|
|
159
|
+
*
|
|
160
|
+
* @param maxResults - The page size, 1000 if undefined. This is also
|
|
161
|
+
* the maximum allowed limit.
|
|
162
|
+
* @param pageToken - The next page token. If not specified, returns
|
|
163
|
+
* users starting without any offset.
|
|
164
|
+
* @returns A promise that resolves with
|
|
165
|
+
* the current batch of downloaded users and the next page token.
|
|
166
|
+
*/
|
|
167
|
+
async listUsers(maxResults, pageToken) {
|
|
168
|
+
return await listUsersHandler(maxResults, pageToken);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Creates a new user.
|
|
172
|
+
*
|
|
173
|
+
* See {@link https://firebase.google.com/docs/auth/admin/manage-users#create_a_user | Create a user}
|
|
174
|
+
* for code samples and detailed documentation.
|
|
175
|
+
*
|
|
176
|
+
* @param properties - The properties to set on the
|
|
177
|
+
* new user record to be created.
|
|
178
|
+
*
|
|
179
|
+
* @returns A promise fulfilled with the user
|
|
180
|
+
* data corresponding to the newly created user.
|
|
181
|
+
*/
|
|
182
|
+
async createUser(properties) {
|
|
183
|
+
return await createUserHandler(properties);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Deletes an existing user.
|
|
187
|
+
*
|
|
188
|
+
* See {@link https://firebase.google.com/docs/auth/admin/manage-users#delete_a_user | Delete a user}
|
|
189
|
+
* for code samples and detailed documentation.
|
|
190
|
+
*
|
|
191
|
+
* @param uid - The `uid` corresponding to the user to delete.
|
|
192
|
+
*
|
|
193
|
+
* @returns An empty promise fulfilled once the user has been
|
|
194
|
+
* deleted.
|
|
195
|
+
*/
|
|
196
|
+
async deleteUser(uid) {
|
|
197
|
+
const oauth2Token = await this.getOauth2AccessToken();
|
|
198
|
+
await deleteUserHandler(uid, oauth2Token);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Deletes the users specified by the given uids.
|
|
202
|
+
*
|
|
203
|
+
* Deleting a non-existing user won't generate an error (i.e. this method
|
|
204
|
+
* is idempotent.) Non-existing users are considered to be successfully
|
|
205
|
+
* deleted, and are therefore counted in the
|
|
206
|
+
* `DeleteUsersResult.successCount` value.
|
|
207
|
+
*
|
|
208
|
+
* Only a maximum of 1000 identifiers may be supplied. If more than 1000
|
|
209
|
+
* identifiers are supplied, this method throws a FirebaseAuthError.
|
|
210
|
+
*
|
|
211
|
+
* This API is currently rate limited at the server to 1 QPS. If you exceed
|
|
212
|
+
* this, you may get a quota exceeded error. Therefore, if you want to
|
|
213
|
+
* delete more than 1000 users, you may need to add a delay to ensure you
|
|
214
|
+
* don't go over this limit.
|
|
215
|
+
*
|
|
216
|
+
* @param uids - The `uids` corresponding to the users to delete.
|
|
217
|
+
*
|
|
218
|
+
* @returns A Promise that resolves to the total number of successful/failed
|
|
219
|
+
* deletions, as well as the array of errors that corresponds to the
|
|
220
|
+
* failed deletions.
|
|
221
|
+
*/
|
|
222
|
+
async deleteUsers(uids) {
|
|
223
|
+
return await deleteUsersHandler(uids);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Updates an existing user.
|
|
227
|
+
*
|
|
228
|
+
* See {@link https://firebase.google.com/docs/auth/admin/manage-users#update_a_user | Update a user}
|
|
229
|
+
* for code samples and detailed documentation.
|
|
230
|
+
*
|
|
231
|
+
* @param uid - The `uid` corresponding to the user to update.
|
|
232
|
+
* @param properties - The properties to update on
|
|
233
|
+
* the provided user.
|
|
234
|
+
*
|
|
235
|
+
* @returns A promise fulfilled with the
|
|
236
|
+
* updated user data.
|
|
237
|
+
*/
|
|
238
|
+
async updateUser(uid, properties) {
|
|
239
|
+
const oauth2Token = await this.getOauth2AccessToken();
|
|
240
|
+
return await updateUserHandler(uid, properties, oauth2Token);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Sets additional developer claims on an existing user identified by the
|
|
244
|
+
* provided `uid`, typically used to define user roles and levels of
|
|
245
|
+
* access. These claims should propagate to all devices where the user is
|
|
246
|
+
* already signed in (after token expiration or when token refresh is forced)
|
|
247
|
+
* and the next time the user signs in. If a reserved OIDC claim name
|
|
248
|
+
* is used (sub, iat, iss, etc), an error is thrown. They are set on the
|
|
249
|
+
* authenticated user's ID token JWT.
|
|
250
|
+
*
|
|
251
|
+
* See {@link https://firebase.google.com/docs/auth/admin/custom-claims |
|
|
252
|
+
* Defining user roles and access levels}
|
|
253
|
+
* for code samples and detailed documentation.
|
|
254
|
+
*
|
|
255
|
+
* @param uid - The `uid` of the user to edit.
|
|
256
|
+
* @param customUserClaims - The developer claims to set. If null is
|
|
257
|
+
* passed, existing custom claims are deleted. Passing a custom claims payload
|
|
258
|
+
* larger than 1000 bytes will throw an error. Custom claims are added to the
|
|
259
|
+
* user's ID token which is transmitted on every authenticated request.
|
|
260
|
+
* For profile non-access related user attributes, use database or other
|
|
261
|
+
* separate storage systems.
|
|
262
|
+
* @returns A promise that resolves when the operation completes
|
|
263
|
+
* successfully.
|
|
264
|
+
*/
|
|
265
|
+
async setCustomUserClaims(uid, customUserClaims) {
|
|
266
|
+
const oauth2Token = await this.getOauth2AccessToken();
|
|
267
|
+
await setCustomUserClaimsHandler(uid, customUserClaims, oauth2Token);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Revokes all refresh tokens for an existing user.
|
|
271
|
+
*
|
|
272
|
+
* This API will update the user's {@link UserRecord.tokensValidAfterTime} to
|
|
273
|
+
* the current UTC. It is important that the server on which this is called has
|
|
274
|
+
* its clock set correctly and synchronized.
|
|
275
|
+
*
|
|
276
|
+
* While this will revoke all sessions for a specified user and disable any
|
|
277
|
+
* new ID tokens for existing sessions from getting minted, existing ID tokens
|
|
278
|
+
* may remain active until their natural expiration (one hour). To verify that
|
|
279
|
+
* ID tokens are revoked, use {@link BaseAuth.verifyIdToken}
|
|
280
|
+
* where `checkRevoked` is set to true.
|
|
281
|
+
*
|
|
282
|
+
* @param uid - The `uid` corresponding to the user whose refresh tokens
|
|
283
|
+
* are to be revoked.
|
|
284
|
+
*
|
|
285
|
+
* @returns An empty promise fulfilled once the user's refresh
|
|
286
|
+
* tokens have been revoked.
|
|
287
|
+
*/
|
|
288
|
+
async revokeRefreshTokens(uid) {
|
|
289
|
+
const oauth2Token = await this.getOauth2AccessToken();
|
|
290
|
+
return await revokeRefreshTokensHandler(uid, oauth2Token);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Verifies a Firebase session cookie. Returns a Promise with the cookie claims.
|
|
294
|
+
* Rejects the promise if the cookie could not be verified.
|
|
295
|
+
*
|
|
296
|
+
* If `checkRevoked` is set to true, first verifies whether the corresponding
|
|
297
|
+
* user is disabled: If yes, an `auth/user-disabled` error is thrown. If no,
|
|
298
|
+
* verifies if the session corresponding to the session cookie was revoked.
|
|
299
|
+
* If the corresponding user's session was invalidated, an
|
|
300
|
+
* `auth/session-cookie-revoked` error is thrown. If not specified the check
|
|
301
|
+
* is not performed.
|
|
302
|
+
*
|
|
303
|
+
* See {@link https://firebase.google.com/docs/auth/admin/manage-cookies#verify_session_cookie_and_check_permissions |
|
|
304
|
+
* Verify Session Cookies}
|
|
305
|
+
* for code samples and detailed documentation
|
|
306
|
+
*
|
|
307
|
+
* @param sessionCookie - The session cookie to verify.
|
|
308
|
+
* @param checkForRevocation - Whether to check if the session cookie was
|
|
309
|
+
* revoked. This requires an extra request to the Firebase Auth backend to
|
|
310
|
+
* check the `tokensValidAfterTime` time for the corresponding user.
|
|
311
|
+
* When not specified, this additional check is not performed.
|
|
312
|
+
*
|
|
313
|
+
* @returns A promise fulfilled with the
|
|
314
|
+
* session cookie's decoded claims if the session cookie is valid; otherwise,
|
|
315
|
+
* a rejected promise.
|
|
316
|
+
*/
|
|
317
|
+
async verifySessionCookie(sessionCookie, checkRevoked) {
|
|
318
|
+
return await verifySessionCookieHandler(sessionCookie, checkRevoked);
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Gets an OAuth2 access token from Google's OAuth2 server. This token is
|
|
322
|
+
* required for accessing the Firebase Auth REST API via fetch requests.
|
|
323
|
+
*
|
|
324
|
+
* Checks if a token already exists in the KV namespace. If not, it gets a new
|
|
325
|
+
* token from Google's OAuth2 server, and sets it on the KV namespace.¨
|
|
326
|
+
*
|
|
327
|
+
* This code is under the MIT Licence.
|
|
328
|
+
*
|
|
329
|
+
* @returns The OAuth2 access token
|
|
330
|
+
*/
|
|
331
|
+
async getOauth2AccessToken() {
|
|
332
|
+
if (this.oauth2Token) {
|
|
333
|
+
return this.oauth2Token;
|
|
334
|
+
}
|
|
335
|
+
let token = null;
|
|
336
|
+
if (this.kvNamespace) {
|
|
337
|
+
token = await this.kvNamespace?.get("oauth2Token");
|
|
338
|
+
}
|
|
339
|
+
if (!token) {
|
|
340
|
+
// Sets the token on the KV namespace
|
|
341
|
+
token = await getOauth2AccessTokenHandler(this.serviceAccountKey, 3000, this.kvNamespace);
|
|
342
|
+
}
|
|
343
|
+
this.oauth2Token = token;
|
|
344
|
+
return token;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ServiceAccountKey } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Gets an OAuth2 access token from Google's OAuth2 server. This token is
|
|
4
|
+
* required for accessing the Firebase Auth REST API via fetch requests.
|
|
5
|
+
*
|
|
6
|
+
* The token is stored in the KV namespace for the amount of time which is
|
|
7
|
+
* shorter:
|
|
8
|
+
*
|
|
9
|
+
* - The provided expiration time
|
|
10
|
+
* - The expiration time returned from Google's OAuth2 server
|
|
11
|
+
*
|
|
12
|
+
* @returns The OAuth2 access token
|
|
13
|
+
*/
|
|
14
|
+
export declare function getOauth2AccessTokenHandler(serviceAccountKey: ServiceAccountKey, expiration?: number, // 50 minutes
|
|
15
|
+
kvNamespace?: KVNamespace): Promise<string>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { importPKCS8, SignJWT } from "jose";
|
|
2
|
+
/**
|
|
3
|
+
* Gets an OAuth2 access token from Google's OAuth2 server. This token is
|
|
4
|
+
* required for accessing the Firebase Auth REST API via fetch requests.
|
|
5
|
+
*
|
|
6
|
+
* The token is stored in the KV namespace for the amount of time which is
|
|
7
|
+
* shorter:
|
|
8
|
+
*
|
|
9
|
+
* - The provided expiration time
|
|
10
|
+
* - The expiration time returned from Google's OAuth2 server
|
|
11
|
+
*
|
|
12
|
+
* @returns The OAuth2 access token
|
|
13
|
+
*/
|
|
14
|
+
export async function getOauth2AccessTokenHandler(serviceAccountKey, expiration = 3000, // 50 minutes
|
|
15
|
+
kvNamespace) {
|
|
16
|
+
const signedJwt = await createSignedJwt(serviceAccountKey, expiration);
|
|
17
|
+
const response = await fetch("https://oauth2.googleapis.com/token", {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: {
|
|
20
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
21
|
+
},
|
|
22
|
+
body: new URLSearchParams({
|
|
23
|
+
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
24
|
+
assertion: signedJwt,
|
|
25
|
+
}),
|
|
26
|
+
});
|
|
27
|
+
const oauth2TokenResponse = (await response.json());
|
|
28
|
+
const shortestExpiration = Math.min(expiration, oauth2TokenResponse.expires_in);
|
|
29
|
+
if (kvNamespace) {
|
|
30
|
+
await kvNamespace.put("oauth2Token", oauth2TokenResponse.access_token, {
|
|
31
|
+
expirationTtl: shortestExpiration,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return oauth2TokenResponse.access_token;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Creates a signed JWT using information from a service account key. The JWT
|
|
38
|
+
* is sent to Google's OAuth2 server to produce an OAuth2 access token.
|
|
39
|
+
*
|
|
40
|
+
* The scope we're using is:
|
|
41
|
+
* - https://www.googleapis.com/auth/identitytoolkit
|
|
42
|
+
*
|
|
43
|
+
* This scope is required for the Firebase Auth REST API.
|
|
44
|
+
*
|
|
45
|
+
* The JWT is valid for 50 minutes.
|
|
46
|
+
*
|
|
47
|
+
* @returns The signed JWT
|
|
48
|
+
*/
|
|
49
|
+
async function createSignedJwt(serviceAccountKey, expiration) {
|
|
50
|
+
const header = {
|
|
51
|
+
alg: "RS256",
|
|
52
|
+
typ: "JWT",
|
|
53
|
+
kid: serviceAccountKey.private_key_id,
|
|
54
|
+
};
|
|
55
|
+
const now = Math.floor(Date.now() / 1000);
|
|
56
|
+
const claims = {
|
|
57
|
+
iss: serviceAccountKey.client_email,
|
|
58
|
+
scope: "https://www.googleapis.com/auth/identitytoolkit", // The scope we need for the Firebase Auth REST API
|
|
59
|
+
aud: "https://oauth2.googleapis.com/token",
|
|
60
|
+
exp: now + expiration,
|
|
61
|
+
iat: now,
|
|
62
|
+
};
|
|
63
|
+
const signingKey = await importPKCS8(serviceAccountKey.private_key, "RS256");
|
|
64
|
+
const jwt = new SignJWT(claims).setProtectedHeader(header).sign(signingKey);
|
|
65
|
+
return jwt;
|
|
66
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deletes an existing Firebase Auth user permanently from the system.
|
|
3
|
+
*
|
|
4
|
+
* This function completely removes a user account and all associated data from Firebase Auth.
|
|
5
|
+
* Once deleted, the user cannot be recovered and will need to create a new account if they
|
|
6
|
+
* wish to access the system again. This operation is permanent and irreversible.
|
|
7
|
+
*
|
|
8
|
+
* **Important Implementation Details:**
|
|
9
|
+
* - Permanently deletes the user account from Firebase Auth
|
|
10
|
+
* - All user data including profile information, custom claims, and metadata is removed
|
|
11
|
+
* - Linked provider accounts are unlinked and removed
|
|
12
|
+
* - Multi-factor authentication settings are deleted
|
|
13
|
+
* - The operation is idempotent - deleting a non-existent user succeeds silently
|
|
14
|
+
* - Uses Firebase Admin API's `accounts:delete` endpoint
|
|
15
|
+
*
|
|
16
|
+
* **Security Considerations:**
|
|
17
|
+
* - This operation cannot be undone - user data is permanently lost
|
|
18
|
+
* - Should be used with extreme caution in production environments
|
|
19
|
+
* - Consider disabling users instead of deleting for audit and recovery purposes
|
|
20
|
+
* - Requires proper authorization and access control in production systems
|
|
21
|
+
* - May affect user sessions and active tokens immediately
|
|
22
|
+
*
|
|
23
|
+
* **Use Cases:**
|
|
24
|
+
* - User account closure requests (GDPR compliance)
|
|
25
|
+
* - Administrative account management
|
|
26
|
+
* - Cleanup of test or demo accounts
|
|
27
|
+
* - System maintenance and data purging
|
|
28
|
+
* - User request for account deletion
|
|
29
|
+
*
|
|
30
|
+
* **Behavioral Notes:**
|
|
31
|
+
* - **Idempotent Operation**: Deleting a non-existent user does not throw an error
|
|
32
|
+
* - **Immediate Effect**: User cannot authenticate immediately after deletion
|
|
33
|
+
* - **Related Data**: Only Firebase Auth data is deleted - external data must be handled separately
|
|
34
|
+
* - **Audit Trail**: Consider logging deletion events for compliance and debugging
|
|
35
|
+
* - **Batch Operations**: For bulk deletions, consider using deleteUsersHandler instead
|
|
36
|
+
*
|
|
37
|
+
* @param uid - The Firebase Auth user ID (localId) of the user to delete.
|
|
38
|
+
* Must be a valid Firebase user identifier string.
|
|
39
|
+
* @param oauth2AccessToken - Valid OAuth2 access token with Firebase Admin API privileges.
|
|
40
|
+
* Obtained via service account authentication.
|
|
41
|
+
*
|
|
42
|
+
* @returns Promise that resolves when the deletion is complete.
|
|
43
|
+
* No return value - success is indicated by promise resolution.
|
|
44
|
+
* The promise resolves successfully even if the user doesn't exist.
|
|
45
|
+
*
|
|
46
|
+
* @throws {Error} When deletion fails due to system errors:
|
|
47
|
+
* - **Validation Errors**:
|
|
48
|
+
* - "uid must be a non-empty string" - Invalid or missing uid parameter
|
|
49
|
+
* - "oauth2AccessToken must be a non-empty string" - Invalid or missing token parameter
|
|
50
|
+
* - **Firebase API Errors**:
|
|
51
|
+
* - "Failed to delete user: {status} {statusText} - {details}" - API errors with detailed information
|
|
52
|
+
* - "INVALID_ID_TOKEN" - OAuth2 token is invalid or expired
|
|
53
|
+
* - "PERMISSION_DENIED" - Insufficient permissions to delete users
|
|
54
|
+
* - **Network Errors**: Various network-related failures during API communication
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* // Delete a user account (basic usage)
|
|
59
|
+
* try {
|
|
60
|
+
* await deleteUserHandler('user123', oauth2Token);
|
|
61
|
+
* console.log('User account deleted successfully');
|
|
62
|
+
* } catch (error) {
|
|
63
|
+
* console.error('Failed to delete user:', error.message);
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* // User-initiated account deletion with confirmation
|
|
70
|
+
* async function handleAccountDeletion(userId: string) {
|
|
71
|
+
* try {
|
|
72
|
+
* // 1. Verify user identity and intent
|
|
73
|
+
* const user = await getUserHandler(userId, oauth2Token);
|
|
74
|
+
* console.log(`Deleting account for: ${user.email}`);
|
|
75
|
+
*
|
|
76
|
+
* // 2. Perform additional cleanup (external data, files, etc.)
|
|
77
|
+
* await cleanupUserData(userId);
|
|
78
|
+
*
|
|
79
|
+
* // 3. Delete the Firebase Auth account
|
|
80
|
+
* await deleteUserHandler(userId, oauth2Token);
|
|
81
|
+
*
|
|
82
|
+
* console.log('Account deletion completed');
|
|
83
|
+
* } catch (error) {
|
|
84
|
+
* console.error('Account deletion failed:', error.message);
|
|
85
|
+
* throw error;
|
|
86
|
+
* }
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* // Administrative cleanup with error handling
|
|
93
|
+
* async function adminDeleteInactiveUsers(userIds: string[]) {
|
|
94
|
+
* const results = [];
|
|
95
|
+
*
|
|
96
|
+
* for (const userId of userIds) {
|
|
97
|
+
* try {
|
|
98
|
+
* await deleteUserHandler(userId, oauth2Token);
|
|
99
|
+
* results.push({ userId, status: 'deleted', error: null });
|
|
100
|
+
* } catch (error) {
|
|
101
|
+
* results.push({ userId, status: 'failed', error: error.message });
|
|
102
|
+
* }
|
|
103
|
+
* }
|
|
104
|
+
*
|
|
105
|
+
* return results;
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* // GDPR compliance workflow
|
|
112
|
+
* async function processGDPRDeletionRequest(userEmail: string) {
|
|
113
|
+
* try {
|
|
114
|
+
* // 1. Find the user by email
|
|
115
|
+
* const user = await getUserByEmailHandler(userEmail, oauth2Token);
|
|
116
|
+
*
|
|
117
|
+
* // 2. Export user data for compliance (if required)
|
|
118
|
+
* const userData = await exportUserData(user.uid);
|
|
119
|
+
* await saveDataExport(userData, `${userEmail}-export.json`);
|
|
120
|
+
*
|
|
121
|
+
* // 3. Delete associated external data
|
|
122
|
+
* await deleteUserFromDatabase(user.uid);
|
|
123
|
+
* await deleteUserFiles(user.uid);
|
|
124
|
+
*
|
|
125
|
+
* // 4. Delete the Firebase Auth account
|
|
126
|
+
* await deleteUserHandler(user.uid, oauth2Token);
|
|
127
|
+
*
|
|
128
|
+
* // 5. Log the deletion for audit purposes
|
|
129
|
+
* await logGDPRDeletion({
|
|
130
|
+
* userEmail,
|
|
131
|
+
* userId: user.uid,
|
|
132
|
+
* deletedAt: new Date(),
|
|
133
|
+
* reason: 'GDPR_REQUEST'
|
|
134
|
+
* });
|
|
135
|
+
*
|
|
136
|
+
* console.log(`GDPR deletion completed for ${userEmail}`);
|
|
137
|
+
* } catch (error) {
|
|
138
|
+
* console.error(`GDPR deletion failed for ${userEmail}:`, error);
|
|
139
|
+
* throw error;
|
|
140
|
+
* }
|
|
141
|
+
* }
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* **Technical Implementation:**
|
|
145
|
+
* - Makes POST request to `https://identitytoolkit.googleapis.com/v1/accounts:delete`
|
|
146
|
+
* - Sends `localId` parameter to identify the target user
|
|
147
|
+
* - Handles Firebase API error responses with detailed error information
|
|
148
|
+
* - Validates input parameters before making API calls
|
|
149
|
+
* - Operates idempotently - no error for non-existent users
|
|
150
|
+
*
|
|
151
|
+
* **Testing Considerations:**
|
|
152
|
+
* - Create test users specifically for deletion tests
|
|
153
|
+
* - Verify user is actually deleted by attempting to retrieve them
|
|
154
|
+
* - Test idempotent behavior by deleting non-existent users
|
|
155
|
+
* - Unit tests should mock the fetch call and verify request format
|
|
156
|
+
* - Integration tests should verify actual deletion from Firebase
|
|
157
|
+
*
|
|
158
|
+
* **Production Considerations:**
|
|
159
|
+
* - **Logging**: Log all deletion operations for audit trails
|
|
160
|
+
* - **Confirmation**: Implement confirmation flows for critical deletions
|
|
161
|
+
* - **Backup**: Consider backing up user data before deletion
|
|
162
|
+
* - **Related Data**: Ensure external data is properly cleaned up
|
|
163
|
+
* - **Rate Limits**: Be aware of Firebase API rate limits for bulk operations
|
|
164
|
+
* - **Alternative**: Consider using `disabled: true` instead of deletion for recoverable scenarios
|
|
165
|
+
*
|
|
166
|
+
* @see {@link getUserHandler} For retrieving user data before deletion
|
|
167
|
+
* @see {@link updateUserHandler} For disabling users instead of deletion
|
|
168
|
+
* @see {@link deleteUsersHandler} For bulk deletion operations
|
|
169
|
+
* @see {@link https://firebase.google.com/docs/auth/admin/manage-users#delete_a_user Firebase User Deletion}
|
|
170
|
+
* @see {@link https://firebase.google.com/docs/reference/rest/auth#section-delete-account Firebase REST API}
|
|
171
|
+
*
|
|
172
|
+
* @package
|
|
173
|
+
* @since 1.0.0
|
|
174
|
+
*/
|
|
175
|
+
export declare function deleteUserHandler(uid: string, oauth2AccessToken: string): Promise<void>;
|