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.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +13 -0
  3. package/README.md +94 -0
  4. package/dist/CloudFireAuth.d.ts +291 -0
  5. package/dist/CloudFireAuth.js +346 -0
  6. package/dist/google-auth/get-oauth-2-token.d.ts +15 -0
  7. package/dist/google-auth/get-oauth-2-token.js +66 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.js +2 -0
  10. package/dist/rest-api/create-user.d.ts +2 -0
  11. package/dist/rest-api/create-user.js +3 -0
  12. package/dist/rest-api/delete-user.d.ts +175 -0
  13. package/dist/rest-api/delete-user.js +207 -0
  14. package/dist/rest-api/delete-users.d.ts +2 -0
  15. package/dist/rest-api/delete-users.js +3 -0
  16. package/dist/rest-api/get-user-by-email.d.ts +2 -0
  17. package/dist/rest-api/get-user-by-email.js +3 -0
  18. package/dist/rest-api/get-user-by-phone-number.d.ts +2 -0
  19. package/dist/rest-api/get-user-by-phone-number.js +3 -0
  20. package/dist/rest-api/get-user-by-provider-uid.d.ts +2 -0
  21. package/dist/rest-api/get-user-by-provider-uid.js +3 -0
  22. package/dist/rest-api/get-user.d.ts +99 -0
  23. package/dist/rest-api/get-user.js +177 -0
  24. package/dist/rest-api/get-users.d.ts +2 -0
  25. package/dist/rest-api/get-users.js +3 -0
  26. package/dist/rest-api/list-users.d.ts +2 -0
  27. package/dist/rest-api/list-users.js +3 -0
  28. package/dist/rest-api/revoke-refresh-tokens.d.ts +116 -0
  29. package/dist/rest-api/revoke-refresh-tokens.js +151 -0
  30. package/dist/rest-api/set-custom-user-claims.d.ts +173 -0
  31. package/dist/rest-api/set-custom-user-claims.js +261 -0
  32. package/dist/rest-api/standard-request.d.ts +12 -0
  33. package/dist/rest-api/standard-request.js +20 -0
  34. package/dist/rest-api/update-user.d.ts +175 -0
  35. package/dist/rest-api/update-user.js +375 -0
  36. package/dist/rest-api/verify-id-token.d.ts +127 -0
  37. package/dist/rest-api/verify-id-token.js +273 -0
  38. package/dist/rest-api/verify-session-cookie.d.ts +2 -0
  39. package/dist/rest-api/verify-session-cookie.js +3 -0
  40. package/dist/types/firebase-admin/auth-config.d.ts +851 -0
  41. package/dist/types/firebase-admin/auth-config.js +1 -0
  42. package/dist/types/firebase-admin/identifier.d.ts +57 -0
  43. package/dist/types/firebase-admin/identifier.js +1 -0
  44. package/dist/types/firebase-admin/index.d.ts +153 -0
  45. package/dist/types/firebase-admin/index.js +1 -0
  46. package/dist/types/firebase-admin/token-verifier.d.ts +219 -0
  47. package/dist/types/firebase-admin/token-verifier.js +1 -0
  48. package/dist/types/firebase-admin/user-record.d.ts +289 -0
  49. package/dist/types/firebase-admin/user-record.js +1 -0
  50. package/dist/types/google-auth.d.ts +25 -0
  51. package/dist/types/google-auth.js +1 -0
  52. package/dist/types/service-account-key.d.ts +13 -0
  53. package/dist/types/service-account-key.js +1 -0
  54. package/dist/types.d.ts +6 -0
  55. package/dist/types.js +1 -0
  56. package/package.json +56 -0
  57. package/third_party/firebase-admin-license.txt +201 -0
@@ -0,0 +1,207 @@
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 async function deleteUserHandler(uid, oauth2AccessToken) {
176
+ // Validate input parameters
177
+ if (typeof uid !== "string" || uid.length === 0) {
178
+ throw new Error("uid must be a non-empty string");
179
+ }
180
+ if (typeof oauth2AccessToken !== "string" || oauth2AccessToken.length === 0) {
181
+ throw new Error("oauth2AccessToken must be a non-empty string");
182
+ }
183
+ // Make the API call to delete the user
184
+ const response = await fetch("https://identitytoolkit.googleapis.com/v1/accounts:delete", {
185
+ method: "POST",
186
+ headers: {
187
+ "Content-Type": "application/json",
188
+ Authorization: `Bearer ${oauth2AccessToken}`,
189
+ },
190
+ body: JSON.stringify({
191
+ localId: uid,
192
+ }),
193
+ });
194
+ if (!response.ok) {
195
+ const errorText = await response.text();
196
+ let errorMessage;
197
+ try {
198
+ const errorData = JSON.parse(errorText);
199
+ const formattedErrorText = JSON.stringify(errorData, null, 2);
200
+ errorMessage = `Failed to delete user: ${response.status} ${response.statusText}\n${formattedErrorText}`;
201
+ }
202
+ catch {
203
+ errorMessage = `Failed to delete user: ${response.status} ${response.statusText} - ${errorText}`;
204
+ }
205
+ throw new Error(errorMessage);
206
+ }
207
+ }
@@ -0,0 +1,2 @@
1
+ import type { DeleteUsersResult } from "../types.js";
2
+ export declare function deleteUsersHandler(uids: string[]): Promise<DeleteUsersResult>;
@@ -0,0 +1,3 @@
1
+ export async function deleteUsersHandler(uids) {
2
+ throw new Error("Not implemented");
3
+ }
@@ -0,0 +1,2 @@
1
+ import type { UserRecord } from "../types.js";
2
+ export declare function getUserByEmailHandler(email: string): Promise<UserRecord>;
@@ -0,0 +1,3 @@
1
+ export async function getUserByEmailHandler(email) {
2
+ throw new Error("Not implemented");
3
+ }
@@ -0,0 +1,2 @@
1
+ import type { UserRecord } from "../types.js";
2
+ export declare function getUserByPhoneNumberHandler(phoneNumber: string): Promise<UserRecord>;
@@ -0,0 +1,3 @@
1
+ export async function getUserByPhoneNumberHandler(phoneNumber) {
2
+ throw new Error("Not implemented");
3
+ }
@@ -0,0 +1,2 @@
1
+ import type { UserRecord } from "../types.js";
2
+ export declare function getUserByProviderUidHandler(providerId: string, uid: string): Promise<UserRecord>;
@@ -0,0 +1,3 @@
1
+ export async function getUserByProviderUidHandler(providerId, uid) {
2
+ throw new Error("Not implemented");
3
+ }
@@ -0,0 +1,99 @@
1
+ import type { UserRecord } from "../types.js";
2
+ /**
3
+ * Retrieves a Firebase Auth user by their unique identifier (UID).
4
+ *
5
+ * This function provides comprehensive user data retrieval by making a direct call
6
+ * to the Firebase Admin API's accounts:lookup endpoint. It transforms the Firebase
7
+ * response into a standardized UserRecord format that matches the Firebase Admin SDK.
8
+ *
9
+ * **Retrieved User Information:**
10
+ * - **Basic Profile**: uid, email, emailVerified, displayName, photoURL, phoneNumber
11
+ * - **Account Status**: disabled status, creation and last sign-in timestamps
12
+ * - **Provider Data**: All linked authentication providers with their details
13
+ * - **Custom Claims**: Parsed from customAttributes if present
14
+ * - **Metadata**: Creation time, last sign-in time, last refresh time
15
+ *
16
+ * **Firebase API Integration:**
17
+ * - Uses Firebase Admin API's `accounts:lookup` endpoint
18
+ * - Requires valid OAuth2 access token with admin privileges
19
+ * - Handles Firebase response format `{ users: [GetAccountInfoUserResponse] }`
20
+ * - Safely processes optional fields with proper null handling
21
+ * - Transforms provider information to match Admin SDK format
22
+ *
23
+ * @param uid - The Firebase Auth user ID (localId) to retrieve.
24
+ * Must be a valid, existing Firebase user identifier.
25
+ * @param oauth2AccessToken - Valid OAuth2 access token with Firebase Admin API privileges.
26
+ * Obtained via service account authentication.
27
+ *
28
+ * @returns Promise that resolves to the UserRecord containing complete user information.
29
+ *
30
+ * @throws {Error} When user lookup fails or user doesn't exist:
31
+ * - "Failed to get user: {status} {statusText}, {details}" - Firebase API errors with HTTP details
32
+ * - "User not found: {uid}" - No user exists with the specified UID
33
+ * - Network errors during Firebase API communication
34
+ * - JSON parsing errors from malformed Firebase responses
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * // Basic user retrieval
39
+ * const user = await getUserHandler('user123', oauth2Token);
40
+ * console.log(`User: ${user.displayName} (${user.email})`);
41
+ * console.log(`Created: ${user.metadata.creationTime}`);
42
+ * console.log(`Verified: ${user.emailVerified}`);
43
+ * ```
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * // Check user status and providers
48
+ * const user = await getUserHandler('user456', oauth2Token);
49
+ *
50
+ * if (user.disabled) {
51
+ * console.log('Account is disabled');
52
+ * }
53
+ *
54
+ * // List all authentication providers
55
+ * user.providerData.forEach(provider => {
56
+ * console.log(`Provider: ${provider.providerId} - ${provider.email}`);
57
+ * });
58
+ *
59
+ * // Access custom claims if available
60
+ * const customClaims = user.customClaims;
61
+ * if (customClaims?.role) {
62
+ * console.log(`User role: ${customClaims.role}`);
63
+ * }
64
+ * ```
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * // Error handling with detailed information
69
+ * try {
70
+ * const user = await getUserHandler(userId, oauth2Token);
71
+ * console.log('User retrieved successfully:', user.uid);
72
+ * } catch (error) {
73
+ * if (error.message.includes('User not found')) {
74
+ * console.error('User does not exist:', userId);
75
+ * } else if (error.message.includes('Failed to get user')) {
76
+ * console.error('Firebase API error:', error.message);
77
+ * } else {
78
+ * console.error('Unexpected error:', error);
79
+ * }
80
+ * }
81
+ * ```
82
+ *
83
+ * **Important Notes:**
84
+ * - Returns complete user profile including sensitive information (use appropriate access controls)
85
+ * - Custom claims are automatically parsed from Firebase's customAttributes field
86
+ * - Provider data includes all linked authentication methods (Google, Facebook, etc.)
87
+ * - Metadata timestamps are in ISO 8601 format or empty strings if not available
88
+ * - Phone numbers are returned in the format stored in Firebase (may not be E.164)
89
+ * - Disabled users can still be retrieved but cannot authenticate
90
+ * - This function requires Firebase Admin privileges - ensure proper token scoping
91
+ *
92
+ * @see {@link https://firebase.google.com/docs/auth/admin/manage-users Firebase User Management}
93
+ * @see {@link https://firebase.google.com/docs/reference/rest/auth#section-get-account-info Firebase REST API}
94
+ * @see {@link UserRecord} For complete UserRecord interface documentation
95
+ *
96
+ * @package
97
+ * @since 1.0.0
98
+ */
99
+ export declare function getUserHandler(uid: string, oauth2AccessToken: string): Promise<UserRecord>;
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Retrieves a Firebase Auth user by their unique identifier (UID).
3
+ *
4
+ * This function provides comprehensive user data retrieval by making a direct call
5
+ * to the Firebase Admin API's accounts:lookup endpoint. It transforms the Firebase
6
+ * response into a standardized UserRecord format that matches the Firebase Admin SDK.
7
+ *
8
+ * **Retrieved User Information:**
9
+ * - **Basic Profile**: uid, email, emailVerified, displayName, photoURL, phoneNumber
10
+ * - **Account Status**: disabled status, creation and last sign-in timestamps
11
+ * - **Provider Data**: All linked authentication providers with their details
12
+ * - **Custom Claims**: Parsed from customAttributes if present
13
+ * - **Metadata**: Creation time, last sign-in time, last refresh time
14
+ *
15
+ * **Firebase API Integration:**
16
+ * - Uses Firebase Admin API's `accounts:lookup` endpoint
17
+ * - Requires valid OAuth2 access token with admin privileges
18
+ * - Handles Firebase response format `{ users: [GetAccountInfoUserResponse] }`
19
+ * - Safely processes optional fields with proper null handling
20
+ * - Transforms provider information to match Admin SDK format
21
+ *
22
+ * @param uid - The Firebase Auth user ID (localId) to retrieve.
23
+ * Must be a valid, existing Firebase user identifier.
24
+ * @param oauth2AccessToken - Valid OAuth2 access token with Firebase Admin API privileges.
25
+ * Obtained via service account authentication.
26
+ *
27
+ * @returns Promise that resolves to the UserRecord containing complete user information.
28
+ *
29
+ * @throws {Error} When user lookup fails or user doesn't exist:
30
+ * - "Failed to get user: {status} {statusText}, {details}" - Firebase API errors with HTTP details
31
+ * - "User not found: {uid}" - No user exists with the specified UID
32
+ * - Network errors during Firebase API communication
33
+ * - JSON parsing errors from malformed Firebase responses
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * // Basic user retrieval
38
+ * const user = await getUserHandler('user123', oauth2Token);
39
+ * console.log(`User: ${user.displayName} (${user.email})`);
40
+ * console.log(`Created: ${user.metadata.creationTime}`);
41
+ * console.log(`Verified: ${user.emailVerified}`);
42
+ * ```
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * // Check user status and providers
47
+ * const user = await getUserHandler('user456', oauth2Token);
48
+ *
49
+ * if (user.disabled) {
50
+ * console.log('Account is disabled');
51
+ * }
52
+ *
53
+ * // List all authentication providers
54
+ * user.providerData.forEach(provider => {
55
+ * console.log(`Provider: ${provider.providerId} - ${provider.email}`);
56
+ * });
57
+ *
58
+ * // Access custom claims if available
59
+ * const customClaims = user.customClaims;
60
+ * if (customClaims?.role) {
61
+ * console.log(`User role: ${customClaims.role}`);
62
+ * }
63
+ * ```
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * // Error handling with detailed information
68
+ * try {
69
+ * const user = await getUserHandler(userId, oauth2Token);
70
+ * console.log('User retrieved successfully:', user.uid);
71
+ * } catch (error) {
72
+ * if (error.message.includes('User not found')) {
73
+ * console.error('User does not exist:', userId);
74
+ * } else if (error.message.includes('Failed to get user')) {
75
+ * console.error('Firebase API error:', error.message);
76
+ * } else {
77
+ * console.error('Unexpected error:', error);
78
+ * }
79
+ * }
80
+ * ```
81
+ *
82
+ * **Important Notes:**
83
+ * - Returns complete user profile including sensitive information (use appropriate access controls)
84
+ * - Custom claims are automatically parsed from Firebase's customAttributes field
85
+ * - Provider data includes all linked authentication methods (Google, Facebook, etc.)
86
+ * - Metadata timestamps are in ISO 8601 format or empty strings if not available
87
+ * - Phone numbers are returned in the format stored in Firebase (may not be E.164)
88
+ * - Disabled users can still be retrieved but cannot authenticate
89
+ * - This function requires Firebase Admin privileges - ensure proper token scoping
90
+ *
91
+ * @see {@link https://firebase.google.com/docs/auth/admin/manage-users Firebase User Management}
92
+ * @see {@link https://firebase.google.com/docs/reference/rest/auth#section-get-account-info Firebase REST API}
93
+ * @see {@link UserRecord} For complete UserRecord interface documentation
94
+ *
95
+ * @package
96
+ * @since 1.0.0
97
+ */
98
+ export async function getUserHandler(uid, oauth2AccessToken) {
99
+ const response = await fetch("https://identitytoolkit.googleapis.com/v1/accounts:lookup", {
100
+ method: "POST",
101
+ headers: {
102
+ "Content-Type": "application/json",
103
+ Authorization: `Bearer ${oauth2AccessToken}`,
104
+ },
105
+ body: JSON.stringify({
106
+ localId: [uid],
107
+ }),
108
+ });
109
+ if (!response.ok) {
110
+ throw new Error(`Failed to get user: ${response.status} ${response.statusText}, ${await response.text()}`);
111
+ }
112
+ const data = (await response.json());
113
+ let userData;
114
+ try {
115
+ userData = data.users[0];
116
+ }
117
+ catch (error) {
118
+ console.error("Error parsing user data:", error);
119
+ throw new Error(`User not found: ${uid}`);
120
+ }
121
+ if (!userData) {
122
+ throw new Error(`User not found: ${uid}`);
123
+ }
124
+ const userRecord = convertToUserRecord(userData);
125
+ return userRecord;
126
+ }
127
+ /**
128
+ * Converts Firebase's GetAccountInfoUserResponse to a UserRecord to match
129
+ * the Firebase Admin SDK format.
130
+ *
131
+ * This function safely handles optional fields and transforms the Firebase API
132
+ * response structure into a standardized UserRecord. It includes proper null
133
+ * handling, custom claims parsing, and provider data transformation.
134
+ *
135
+ * @param userData - The raw user data from Firebase Admin API.
136
+ * @returns The converted UserRecord with all available user information.
137
+ * @internal
138
+ */
139
+ function convertToUserRecord(userData) {
140
+ // Safely map provider user info, handling optional fields properly
141
+ const userInfo = userData.providerUserInfo?.map((providerUserInfo) => ({
142
+ uid: providerUserInfo.rawId || providerUserInfo.federatedId || "",
143
+ displayName: providerUserInfo.displayName || null,
144
+ email: providerUserInfo.email || null,
145
+ photoURL: providerUserInfo.photoUrl || null,
146
+ providerId: providerUserInfo.providerId,
147
+ phoneNumber: providerUserInfo.phoneNumber || null,
148
+ })) || [];
149
+ // Parse custom claims from customAttributes JSON string
150
+ let customClaims = null;
151
+ if (userData.customAttributes) {
152
+ try {
153
+ customClaims = JSON.parse(userData.customAttributes);
154
+ }
155
+ catch (error) {
156
+ // Invalid JSON in customAttributes, leave as null
157
+ console.warn("Failed to parse custom attributes as JSON:", error);
158
+ }
159
+ }
160
+ const userRecord = {
161
+ uid: userData.localId,
162
+ email: userData.email || null,
163
+ emailVerified: userData.emailVerified || false,
164
+ displayName: userData.displayName || null,
165
+ photoURL: userData.photoUrl || null,
166
+ phoneNumber: userData.phoneNumber || null,
167
+ disabled: userData.disabled || false,
168
+ providerData: userInfo,
169
+ customClaims: customClaims,
170
+ metadata: {
171
+ creationTime: userData.createdAt || "",
172
+ lastSignInTime: userData.lastLoginAt || "",
173
+ lastRefreshTime: userData.lastRefreshAt || null,
174
+ },
175
+ };
176
+ return userRecord;
177
+ }
@@ -0,0 +1,2 @@
1
+ import type { UserIdentifier, GetUsersResult } from "../types.js";
2
+ export declare function getUsersHandler(identifiers: UserIdentifier[]): Promise<GetUsersResult>;
@@ -0,0 +1,3 @@
1
+ export async function getUsersHandler(identifiers) {
2
+ throw new Error("Not implemented");
3
+ }
@@ -0,0 +1,2 @@
1
+ import type { ListUsersResult } from "../types.js";
2
+ export declare function listUsersHandler(maxResults?: number, pageToken?: string): Promise<ListUsersResult>;
@@ -0,0 +1,3 @@
1
+ export async function listUsersHandler(maxResults, pageToken) {
2
+ throw new Error("Not implemented");
3
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Revokes all refresh tokens for an existing Firebase Auth user.
3
+ *
4
+ * This function updates the user's `tokensValidAfterTime` to the current UTC timestamp,
5
+ * effectively invalidating all existing refresh tokens and sessions for the specified user.
6
+ * After calling this function, the user will need to re-authenticate to obtain new tokens.
7
+ *
8
+ * **Important Implementation Details:**
9
+ * - Updates the user's `tokensValidAfterTime` to the current UTC timestamp (in seconds)
10
+ * - All existing refresh tokens become invalid immediately
11
+ * - Existing ID tokens remain valid until their natural expiration (1 hour) unless verified with `checkRevoked=true`
12
+ * - Requires accurate server time synchronization for proper functionality
13
+ * - Uses Firebase Admin API's `accounts:update` endpoint with `validSince` parameter
14
+ *
15
+ * **Security Considerations:**
16
+ * - Forces user re-authentication on all devices and sessions
17
+ * - Useful for compromised accounts or mandatory sign-out scenarios
18
+ * - Should be combined with ID token verification using `checkRevoked=true` for immediate effect
19
+ * - Does not affect the user's account data or profile information
20
+ *
21
+ * **Use Cases:**
22
+ * - Security incident response (compromised accounts)
23
+ * - Forced logout from all devices
24
+ * - Administrative account suspension workflows
25
+ * - Password change security measures
26
+ * - Device management and session control
27
+ *
28
+ * @param uid - The Firebase Auth user ID (localId) whose refresh tokens should be revoked.
29
+ * Must be a valid, existing Firebase user identifier.
30
+ * @param oauth2AccessToken - Valid OAuth2 access token with Firebase Admin API privileges.
31
+ * Obtained via service account authentication.
32
+ *
33
+ * @returns Promise that resolves when the revocation is complete.
34
+ * No return value - success is indicated by promise resolution.
35
+ *
36
+ * @throws {Error} When revocation fails:
37
+ * - **Validation Errors**:
38
+ * - "uid must be a non-empty string" - Invalid or missing uid parameter
39
+ * - **Firebase API Errors**:
40
+ * - "Failed to revoke refresh tokens: {status} {statusText} - {details}" - API errors with detailed information
41
+ * - "USER_NOT_FOUND" - Specified user does not exist
42
+ * - "INVALID_ID_TOKEN" - OAuth2 token is invalid or expired
43
+ * - **Network Errors**: Various network-related failures during API communication
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * // Revoke all refresh tokens for a user (security incident)
48
+ * try {
49
+ * await revokeRefreshTokensHandler('user123', oauth2Token);
50
+ * console.log('All refresh tokens revoked successfully');
51
+ *
52
+ * // Verify that existing ID tokens are now invalid
53
+ * await verifyIdTokenHandler(existingIdToken, projectId, oauth2Token, kvNamespace, true);
54
+ * } catch (error) {
55
+ * if (error.message.includes('id-token-revoked')) {
56
+ * console.log('Tokens successfully revoked - existing ID token is invalid');
57
+ * } else {
58
+ * console.error('Failed to revoke tokens:', error);
59
+ * }
60
+ * }
61
+ * ```
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * // Force logout from all devices after password change
66
+ * try {
67
+ * // First update the password
68
+ * await updateUserHandler('user456', { password: 'newSecurePassword' }, oauth2Token);
69
+ *
70
+ * // Then revoke all existing sessions for security
71
+ * await revokeRefreshTokensHandler('user456', oauth2Token);
72
+ *
73
+ * console.log('Password updated and all sessions revoked');
74
+ * } catch (error) {
75
+ * console.error('Security update failed:', error);
76
+ * }
77
+ * ```
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * // Administrative account suspension workflow
82
+ * try {
83
+ * // Disable the account
84
+ * await updateUserHandler('suspendedUser', { disabled: true }, oauth2Token);
85
+ *
86
+ * // Revoke all active sessions
87
+ * await revokeRefreshTokensHandler('suspendedUser', oauth2Token);
88
+ *
89
+ * console.log('Account suspended and all sessions terminated');
90
+ * } catch (error) {
91
+ * console.error('Account suspension failed:', error);
92
+ * }
93
+ * ```
94
+ *
95
+ * **Technical Implementation:**
96
+ * - Makes POST request to `https://identitytoolkit.googleapis.com/v1/accounts:update`
97
+ * - Sets `validSince` to current timestamp: `Math.floor(Date.now() / 1000)`
98
+ * - Uses `localId` parameter to identify the target user
99
+ * - Handles Firebase API error responses with detailed error information
100
+ * - Validates input parameters before making API calls
101
+ *
102
+ * **Testing Considerations:**
103
+ * - Can be verified by attempting to verify existing ID tokens with `checkRevoked=true`
104
+ * - Integration tests should create tokens, revoke them, then verify revocation
105
+ * - Unit tests should mock the fetch call and verify request format
106
+ * - Error scenarios should test various Firebase API error responses
107
+ *
108
+ * @see {@link verifyIdTokenHandler} For verifying ID tokens with revocation checking
109
+ * @see {@link updateUserHandler} For other user management operations
110
+ * @see {@link https://firebase.google.com/docs/auth/admin/manage-sessions#revoke_refresh_tokens Firebase Session Management}
111
+ * @see {@link https://firebase.google.com/docs/reference/rest/auth#section-update-account Firebase REST API}
112
+ *
113
+ * @package
114
+ * @since 1.0.0
115
+ */
116
+ export declare function revokeRefreshTokensHandler(uid: string, oauth2AccessToken: string): Promise<void>;