@xbg.solutions/utils-token-handler 1.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.
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Firebase Auth Adapter
3
+ * Implements ITokenAdapter for Firebase Authentication
4
+ */
5
+ import * as admin from 'firebase-admin';
6
+ import { Logger } from '@xbg/utils-logger';
7
+ import { ITokenAdapter, NormalizedToken, CustomClaimsConfig, TokenVerificationError } from './token-types';
8
+ export declare class FirebaseAuthAdapter<TCustomClaims = Record<string, any>> implements ITokenAdapter<TCustomClaims> {
9
+ /**
10
+ * Verify token with Firebase Auth
11
+ */
12
+ verifyToken(rawToken: string, logger: Logger): Promise<admin.auth.DecodedIdToken>;
13
+ /**
14
+ * Generate token identifier for blacklist
15
+ * Firebase doesn't provide jti claim, so we hash the token
16
+ */
17
+ getTokenIdentifier(rawToken: string): Promise<string>;
18
+ /**
19
+ * Normalize Firebase token to platform-agnostic structure
20
+ */
21
+ normalizeToken(providerToken: admin.auth.DecodedIdToken, customClaimsConfig: CustomClaimsConfig<TCustomClaims>): NormalizedToken<TCustomClaims>;
22
+ /**
23
+ * Sync custom claims to Firebase Auth
24
+ */
25
+ syncCustomClaims(authUID: string, claims: TCustomClaims, logger: Logger): Promise<void>;
26
+ /**
27
+ * Revoke user tokens at Firebase level
28
+ * Firebase supports this via revokeRefreshTokens
29
+ */
30
+ revokeUserTokens(authUID: string, logger: Logger): Promise<boolean>;
31
+ /**
32
+ * Map Firebase errors to standard error types
33
+ */
34
+ mapProviderError(error: any): TokenVerificationError;
35
+ /**
36
+ * Extract userUID from token, with fallback logic
37
+ * This method can be customized based on how different projects
38
+ * structure their custom claims
39
+ */
40
+ private extractUserUID;
41
+ }
42
+ /**
43
+ * Factory function to create Firebase adapter with type safety
44
+ */
45
+ export declare function createFirebaseAuthAdapter<TCustomClaims = Record<string, any>>(): FirebaseAuthAdapter<TCustomClaims>;
46
+ //# sourceMappingURL=firebase-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebase-adapter.d.ts","sourceRoot":"","sources":["../src/firebase-adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAExC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EACL,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,eAAe,CAAC;AAEvB,qBAAa,mBAAmB,CAAC,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAClE,YAAW,aAAa,CAAC,aAAa,CAAC;IAEvC;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC;IAmBvF;;;OAGG;IACG,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO3D;;OAEG;IACH,cAAc,CACZ,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,cAAc,EACxC,kBAAkB,EAAE,kBAAkB,CAAC,aAAa,CAAC,GACpD,eAAe,CAAC,aAAa,CAAC;IAiCjC;;OAEG;IACG,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAoBhB;;;OAGG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBzE;;OAEG;IACH,gBAAgB,CAAC,KAAK,EAAE,GAAG,GAAG,sBAAsB;IAqCpD;;;;OAIG;IACH,OAAO,CAAC,cAAc;CAkBvB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAC3E,mBAAmB,CAAC,aAAa,CAAC,CAEnC"}
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ /**
3
+ * Firebase Auth Adapter
4
+ * Implements ITokenAdapter for Firebase Authentication
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.FirebaseAuthAdapter = void 0;
41
+ exports.createFirebaseAuthAdapter = createFirebaseAuthAdapter;
42
+ const admin = __importStar(require("firebase-admin"));
43
+ const crypto = __importStar(require("crypto"));
44
+ const token_types_1 = require("./token-types");
45
+ class FirebaseAuthAdapter {
46
+ /**
47
+ * Verify token with Firebase Auth
48
+ */
49
+ async verifyToken(rawToken, logger) {
50
+ logger.debug('FirebaseAuthAdapter: Verifying token with Firebase');
51
+ try {
52
+ const decodedToken = await admin.auth().verifyIdToken(rawToken, true);
53
+ logger.debug('FirebaseAuthAdapter: Token verified successfully', {
54
+ authUID: decodedToken.uid
55
+ });
56
+ return decodedToken;
57
+ }
58
+ catch (error) {
59
+ logger.warn('FirebaseAuthAdapter: Token verification failed', {
60
+ error: error.message
61
+ });
62
+ throw error;
63
+ }
64
+ }
65
+ /**
66
+ * Generate token identifier for blacklist
67
+ * Firebase doesn't provide jti claim, so we hash the token
68
+ */
69
+ async getTokenIdentifier(rawToken) {
70
+ return crypto
71
+ .createHash('sha256')
72
+ .update(rawToken)
73
+ .digest('hex');
74
+ }
75
+ /**
76
+ * Normalize Firebase token to platform-agnostic structure
77
+ */
78
+ normalizeToken(providerToken, customClaimsConfig) {
79
+ // Extract custom claims using provided configuration
80
+ let customClaims;
81
+ try {
82
+ customClaims = customClaimsConfig.extract(providerToken);
83
+ // Validate if validator is provided
84
+ if (customClaimsConfig.validate && !customClaimsConfig.validate(customClaims)) {
85
+ // If validation fails, use defaults
86
+ customClaims = customClaimsConfig.defaults;
87
+ }
88
+ }
89
+ catch (error) {
90
+ // If extraction fails, use defaults
91
+ customClaims = customClaimsConfig.defaults;
92
+ }
93
+ return {
94
+ authUID: providerToken.uid,
95
+ userUID: this.extractUserUID(providerToken, customClaims),
96
+ email: providerToken.email || null,
97
+ emailVerified: providerToken.email_verified || false,
98
+ phoneNumber: providerToken.phone_number || null,
99
+ issuedAt: providerToken.iat,
100
+ expiresAt: providerToken.exp,
101
+ issuer: 'firebase',
102
+ customClaims,
103
+ rawClaims: providerToken
104
+ };
105
+ }
106
+ /**
107
+ * Sync custom claims to Firebase Auth
108
+ */
109
+ async syncCustomClaims(authUID, claims, logger) {
110
+ logger.debug('FirebaseAuthAdapter: Syncing custom claims', {
111
+ authUID,
112
+ claimKeys: Object.keys(claims)
113
+ });
114
+ try {
115
+ await admin.auth().setCustomUserClaims(authUID, claims);
116
+ logger.info('FirebaseAuthAdapter: Custom claims synced successfully', {
117
+ authUID
118
+ });
119
+ }
120
+ catch (error) {
121
+ logger.error('FirebaseAuthAdapter: Failed to sync custom claims', error, {
122
+ authUID
123
+ });
124
+ throw error;
125
+ }
126
+ }
127
+ /**
128
+ * Revoke user tokens at Firebase level
129
+ * Firebase supports this via revokeRefreshTokens
130
+ */
131
+ async revokeUserTokens(authUID, logger) {
132
+ logger.info('FirebaseAuthAdapter: Revoking user tokens at Firebase', {
133
+ authUID
134
+ });
135
+ try {
136
+ await admin.auth().revokeRefreshTokens(authUID);
137
+ logger.info('FirebaseAuthAdapter: User tokens revoked successfully', {
138
+ authUID
139
+ });
140
+ return true;
141
+ }
142
+ catch (error) {
143
+ logger.error('FirebaseAuthAdapter: Failed to revoke tokens', error, {
144
+ authUID
145
+ });
146
+ return false;
147
+ }
148
+ }
149
+ /**
150
+ * Map Firebase errors to standard error types
151
+ */
152
+ mapProviderError(error) {
153
+ const errorCode = error.code || '';
154
+ const errorMessage = error.message || '';
155
+ // Firebase ID token verification errors
156
+ if (errorCode.includes('expired') || errorCode.includes('exp-') ||
157
+ errorMessage.includes('expired')) {
158
+ return token_types_1.TokenVerificationError.EXPIRED;
159
+ }
160
+ if (errorCode.includes('invalid') || errorCode.includes('signature') ||
161
+ errorMessage.includes('signature') || errorMessage.includes('invalid')) {
162
+ return token_types_1.TokenVerificationError.INVALID_SIGNATURE;
163
+ }
164
+ if (errorCode.includes('malformed') || errorMessage.includes('malformed') ||
165
+ errorMessage.includes('decode')) {
166
+ return token_types_1.TokenVerificationError.MALFORMED;
167
+ }
168
+ // Firebase-specific error codes
169
+ switch (errorCode) {
170
+ case 'auth/argument-error':
171
+ case 'auth/invalid-id-token':
172
+ return token_types_1.TokenVerificationError.MALFORMED;
173
+ case 'auth/id-token-expired':
174
+ return token_types_1.TokenVerificationError.EXPIRED;
175
+ case 'auth/id-token-revoked':
176
+ return token_types_1.TokenVerificationError.BLACKLISTED;
177
+ default:
178
+ return token_types_1.TokenVerificationError.UNKNOWN;
179
+ }
180
+ }
181
+ /**
182
+ * Extract userUID from token, with fallback logic
183
+ * This method can be customized based on how different projects
184
+ * structure their custom claims
185
+ */
186
+ extractUserUID(providerToken, customClaims) {
187
+ // Try to extract from custom claims first
188
+ if (customClaims && typeof customClaims === 'object' && 'userUID' in customClaims) {
189
+ return customClaims.userUID || null;
190
+ }
191
+ // Fallback: check if it's directly in the provider token
192
+ const anyToken = providerToken;
193
+ if (anyToken.userUID) {
194
+ return anyToken.userUID;
195
+ }
196
+ // No userUID found - this might be a first-time user
197
+ return null;
198
+ }
199
+ }
200
+ exports.FirebaseAuthAdapter = FirebaseAuthAdapter;
201
+ /**
202
+ * Factory function to create Firebase adapter with type safety
203
+ */
204
+ function createFirebaseAuthAdapter() {
205
+ return new FirebaseAuthAdapter();
206
+ }
207
+ //# sourceMappingURL=firebase-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebase-adapter.js","sourceRoot":"","sources":["../src/firebase-adapter.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+MH,8DAGC;AAhND,sDAAwC;AACxC,+CAAiC;AAEjC,+CAKuB;AAEvB,MAAa,mBAAmB;IAG9B;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,QAAgB,EAAE,MAAc;QAChD,MAAM,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;QAEnE,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAEtE,MAAM,CAAC,KAAK,CAAC,kDAAkD,EAAE;gBAC/D,OAAO,EAAE,YAAY,CAAC,GAAG;aAC1B,CAAC,CAAC;YAEH,OAAO,YAAY,CAAC;QACtB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,gDAAgD,EAAE;gBAC5D,KAAK,EAAE,KAAK,CAAC,OAAO;aACrB,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QACvC,OAAO,MAAM;aACV,UAAU,CAAC,QAAQ,CAAC;aACpB,MAAM,CAAC,QAAQ,CAAC;aAChB,MAAM,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,cAAc,CACZ,aAAwC,EACxC,kBAAqD;QAErD,qDAAqD;QACrD,IAAI,YAA2B,CAAC;QAChC,IAAI,CAAC;YACH,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAEzD,oCAAoC;YACpC,IAAI,kBAAkB,CAAC,QAAQ,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC9E,oCAAoC;gBACpC,YAAY,GAAG,kBAAkB,CAAC,QAAyB,CAAC;YAC9D,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,oCAAoC;YACpC,YAAY,GAAG,kBAAkB,CAAC,QAAyB,CAAC;QAC9D,CAAC;QAED,OAAO;YACL,OAAO,EAAE,aAAa,CAAC,GAAG;YAC1B,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,YAAY,CAAC;YAEzD,KAAK,EAAE,aAAa,CAAC,KAAK,IAAI,IAAI;YAClC,aAAa,EAAE,aAAa,CAAC,cAAc,IAAI,KAAK;YACpD,WAAW,EAAE,aAAa,CAAC,YAAY,IAAI,IAAI;YAE/C,QAAQ,EAAE,aAAa,CAAC,GAAG;YAC3B,SAAS,EAAE,aAAa,CAAC,GAAG;YAC5B,MAAM,EAAE,UAAU;YAElB,YAAY;YACZ,SAAS,EAAE,aAAa;SACzB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CACpB,OAAe,EACf,MAAqB,EACrB,MAAc;QAEd,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE;YACzD,OAAO;YACP,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,MAA6B,CAAC;SACtD,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAA6B,CAAC,CAAC;YAE/E,MAAM,CAAC,IAAI,CAAC,wDAAwD,EAAE;gBACpE,OAAO;aACR,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,mDAAmD,EAAE,KAAK,EAAE;gBACvE,OAAO;aACR,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,OAAe,EAAE,MAAc;QACpD,MAAM,CAAC,IAAI,CAAC,uDAAuD,EAAE;YACnE,OAAO;SACR,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;YAEhD,MAAM,CAAC,IAAI,CAAC,uDAAuD,EAAE;gBACnE,OAAO;aACR,CAAC,CAAC;YAEH,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,8CAA8C,EAAE,KAAK,EAAE;gBAClE,OAAO;aACR,CAAC,CAAC;YACH,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,KAAU;QACzB,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QACnC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;QAEzC,wCAAwC;QACxC,IAAI,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC3D,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACrC,OAAO,oCAAsB,CAAC,OAAO,CAAC;QACxC,CAAC;QAED,IAAI,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC;YAChE,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3E,OAAO,oCAAsB,CAAC,iBAAiB,CAAC;QAClD,CAAC;QAED,IAAI,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC;YACrE,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,OAAO,oCAAsB,CAAC,SAAS,CAAC;QAC1C,CAAC;QAED,gCAAgC;QAChC,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,qBAAqB,CAAC;YAC3B,KAAK,uBAAuB;gBAC1B,OAAO,oCAAsB,CAAC,SAAS,CAAC;YAE1C,KAAK,uBAAuB;gBAC1B,OAAO,oCAAsB,CAAC,OAAO,CAAC;YAExC,KAAK,uBAAuB;gBAC1B,OAAO,oCAAsB,CAAC,WAAW,CAAC;YAE5C;gBACE,OAAO,oCAAsB,CAAC,OAAO,CAAC;QAC1C,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,cAAc,CACpB,aAAwC,EACxC,YAA2B;QAE3B,0CAA0C;QAC1C,IAAI,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,SAAS,IAAI,YAAY,EAAE,CAAC;YAClF,OAAQ,YAAoB,CAAC,OAAO,IAAI,IAAI,CAAC;QAC/C,CAAC;QAED,yDAAyD;QACzD,MAAM,QAAQ,GAAG,aAAoB,CAAC;QACtC,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,OAAO,QAAQ,CAAC,OAAO,CAAC;QAC1B,CAAC;QAED,qDAAqD;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA9LD,kDA8LC;AAED;;GAEG;AACH,SAAgB,yBAAyB;IAEvC,OAAO,IAAI,mBAAmB,EAAiB,CAAC;AAClD,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Firestore Database Adapter
3
+ * Implements ITokenDatabase for Firestore operations
4
+ */
5
+ import * as admin from 'firebase-admin';
6
+ import { Firestore } from 'firebase-admin/firestore';
7
+ import { ITokenDatabase, TokenBlacklistEntry } from './token-types';
8
+ export declare class FirestoreTokenDatabase implements ITokenDatabase {
9
+ private db;
10
+ private collectionName;
11
+ private collection;
12
+ constructor(db: Firestore, collectionName: string);
13
+ /**
14
+ * Add entry to blacklist
15
+ */
16
+ addBlacklistEntry(entry: TokenBlacklistEntry): Promise<void>;
17
+ /**
18
+ * Check if token identifier is blacklisted
19
+ */
20
+ isTokenBlacklisted(tokenIdentifier: string): Promise<boolean>;
21
+ /**
22
+ * Get user's global token revocation timestamp
23
+ */
24
+ getUserRevocationTime(authUID: string): Promise<Date | null>;
25
+ /**
26
+ * Add global revocation entry for user
27
+ */
28
+ addUserRevocation(authUID: string, reason: string, blacklistedBy: string | null, expiresAt: Date): Promise<void>;
29
+ /**
30
+ * Remove expired blacklist entries
31
+ */
32
+ cleanupExpiredEntries(): Promise<number>;
33
+ /**
34
+ * Get collection reference for advanced operations
35
+ */
36
+ getCollection(): admin.firestore.CollectionReference;
37
+ /**
38
+ * Health check - verify database connectivity
39
+ */
40
+ healthCheck(): Promise<boolean>;
41
+ }
42
+ /**
43
+ * Factory function to create Firestore database adapter
44
+ */
45
+ export declare function createFirestoreTokenDatabase(db: Firestore, collectionName: string): FirestoreTokenDatabase;
46
+ //# sourceMappingURL=firestore-database-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firestore-database-adapter.d.ts","sourceRoot":"","sources":["../src/firestore-database-adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EACL,cAAc,EACd,mBAAmB,EACpB,MAAM,eAAe,CAAC;AAEvB,qBAAa,sBAAuB,YAAW,cAAc;IAIzD,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,cAAc;IAJxB,OAAO,CAAC,UAAU,CAAsC;gBAG9C,EAAE,EAAE,SAAS,EACb,cAAc,EAAE,MAAM;IAKhC;;OAEG;IACG,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IASlE;;OAEG;IACG,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASnE;;OAEG;IACG,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAyBlE;;OAEG;IACG,iBAAiB,CACrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,SAAS,EAAE,IAAI,GACd,OAAO,CAAC,IAAI,CAAC;IAchB;;OAEG;IACG,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC;IAoB9C;;OAEG;IACH,aAAa,IAAI,KAAK,CAAC,SAAS,CAAC,mBAAmB;IAIpD;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAStC;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,EAAE,EAAE,SAAS,EACb,cAAc,EAAE,MAAM,GACrB,sBAAsB,CAExB"}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ /**
3
+ * Firestore Database Adapter
4
+ * Implements ITokenDatabase for Firestore operations
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.FirestoreTokenDatabase = void 0;
8
+ exports.createFirestoreTokenDatabase = createFirestoreTokenDatabase;
9
+ class FirestoreTokenDatabase {
10
+ constructor(db, collectionName) {
11
+ this.db = db;
12
+ this.collectionName = collectionName;
13
+ this.collection = this.db.collection(this.collectionName);
14
+ }
15
+ /**
16
+ * Add entry to blacklist
17
+ */
18
+ async addBlacklistEntry(entry) {
19
+ await this.collection.doc(entry.blacklistEntryUID).set(Object.assign(Object.assign({}, entry), {
20
+ // Ensure dates are Firestore timestamps
21
+ blacklistedAt: entry.blacklistedAt, expiresAt: entry.expiresAt }));
22
+ }
23
+ /**
24
+ * Check if token identifier is blacklisted
25
+ */
26
+ async isTokenBlacklisted(tokenIdentifier) {
27
+ const snapshot = await this.collection
28
+ .where('tokenJTI', '==', tokenIdentifier)
29
+ .limit(1)
30
+ .get();
31
+ return !snapshot.empty;
32
+ }
33
+ /**
34
+ * Get user's global token revocation timestamp
35
+ */
36
+ async getUserRevocationTime(authUID) {
37
+ const snapshot = await this.collection
38
+ .where('tokenJTI', '==', `ALL_TOKENS_${authUID}`)
39
+ .orderBy('blacklistedAt', 'desc')
40
+ .limit(1)
41
+ .get();
42
+ if (snapshot.empty) {
43
+ return null;
44
+ }
45
+ const entry = snapshot.docs[0].data();
46
+ // Handle both Firestore Timestamp and Date objects
47
+ const blacklistedAt = entry.blacklistedAt;
48
+ if (blacklistedAt instanceof Date) {
49
+ return blacklistedAt;
50
+ }
51
+ else if (blacklistedAt && typeof blacklistedAt === 'object' && 'toDate' in blacklistedAt) {
52
+ // Firestore Timestamp
53
+ return blacklistedAt.toDate();
54
+ }
55
+ return null;
56
+ }
57
+ /**
58
+ * Add global revocation entry for user
59
+ */
60
+ async addUserRevocation(authUID, reason, blacklistedBy, expiresAt) {
61
+ const entry = {
62
+ blacklistEntryUID: `revocation_${authUID}_${Date.now()}`,
63
+ tokenJTI: `ALL_TOKENS_${authUID}`,
64
+ authUID,
65
+ blacklistedAt: new Date(),
66
+ blacklistedBy,
67
+ reason,
68
+ expiresAt
69
+ };
70
+ await this.addBlacklistEntry(entry);
71
+ }
72
+ /**
73
+ * Remove expired blacklist entries
74
+ */
75
+ async cleanupExpiredEntries() {
76
+ const now = new Date();
77
+ const snapshot = await this.collection
78
+ .where('expiresAt', '<=', now)
79
+ .get();
80
+ if (snapshot.empty) {
81
+ return 0;
82
+ }
83
+ // Batch delete for efficiency
84
+ const batch = this.db.batch();
85
+ snapshot.docs.forEach((doc) => {
86
+ batch.delete(doc.ref);
87
+ });
88
+ await batch.commit();
89
+ return snapshot.size;
90
+ }
91
+ /**
92
+ * Get collection reference for advanced operations
93
+ */
94
+ getCollection() {
95
+ return this.collection;
96
+ }
97
+ /**
98
+ * Health check - verify database connectivity
99
+ */
100
+ async healthCheck() {
101
+ try {
102
+ // Simple read operation to test connectivity
103
+ await this.collection.limit(1).get();
104
+ return true;
105
+ }
106
+ catch (error) {
107
+ return false;
108
+ }
109
+ }
110
+ }
111
+ exports.FirestoreTokenDatabase = FirestoreTokenDatabase;
112
+ /**
113
+ * Factory function to create Firestore database adapter
114
+ */
115
+ function createFirestoreTokenDatabase(db, collectionName) {
116
+ return new FirestoreTokenDatabase(db, collectionName);
117
+ }
118
+ //# sourceMappingURL=firestore-database-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firestore-database-adapter.js","sourceRoot":"","sources":["../src/firestore-database-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Generic Token Handler
3
+ * Platform-agnostic token handling with configurable auth providers
4
+ */
5
+ import { Logger } from '@xbg/utils-logger';
6
+ import { ITokenHandler, ITokenAdapter, TokenVerificationResult, TokenBlacklistEntry, TokenHandlerConfig } from './token-types';
7
+ export declare class TokenHandler<TCustomClaims = Record<string, any>> implements ITokenHandler<TCustomClaims> {
8
+ private config;
9
+ private adapter;
10
+ private blacklistManager;
11
+ constructor(config: TokenHandlerConfig<TCustomClaims>, adapter: ITokenAdapter<TCustomClaims>);
12
+ /**
13
+ * Verify and unpack raw token string
14
+ * Returns normalized token if valid, or error details if invalid
15
+ */
16
+ verifyAndUnpack(rawToken: string, logger: Logger): Promise<TokenVerificationResult<TCustomClaims>>;
17
+ /**
18
+ * Generate token identifier for blacklist lookup
19
+ */
20
+ getTokenIdentifier(rawToken: string): Promise<string>;
21
+ /**
22
+ * Sync custom claims to auth provider
23
+ */
24
+ syncCustomClaims(authUID: string, claims: TCustomClaims, logger: Logger): Promise<void>;
25
+ /**
26
+ * Revoke all tokens for a user at provider level
27
+ */
28
+ revokeUserTokens(authUID: string, logger: Logger): Promise<boolean>;
29
+ /**
30
+ * Blacklist individual token
31
+ */
32
+ blacklistToken(tokenIdentifier: string, authUID: string, reason: string, tokenExpiresAt: Date, blacklistedBy: string | null, logger: Logger): Promise<TokenBlacklistEntry>;
33
+ /**
34
+ * Blacklist all tokens for a user (global revocation)
35
+ */
36
+ blacklistAllUserTokens(authUID: string, reason: string, blacklistedBy: string | null, logger: Logger): Promise<void>;
37
+ /**
38
+ * Check if token is blacklisted
39
+ */
40
+ isTokenBlacklisted(tokenIdentifier: string, logger: Logger): Promise<boolean>;
41
+ /**
42
+ * Get user's token revocation timestamp
43
+ */
44
+ getUserTokenRevocationTime(authUID: string, logger: Logger): Promise<Date | null>;
45
+ /**
46
+ * Cleanup expired blacklist entries
47
+ */
48
+ cleanupExpiredEntries(logger: Logger): Promise<number>;
49
+ /**
50
+ * Get token handler configuration
51
+ */
52
+ getConfig(): TokenHandlerConfig<TCustomClaims>;
53
+ /**
54
+ * Extract authUID from provider token
55
+ * Different providers may structure this differently
56
+ */
57
+ private extractAuthUID;
58
+ /**
59
+ * Extract issued-at timestamp from provider token
60
+ * Different providers may structure this differently
61
+ */
62
+ private extractIssuedAt;
63
+ }
64
+ /**
65
+ * Factory function to create token handler with type safety
66
+ */
67
+ export declare function createTokenHandler<TCustomClaims = Record<string, any>>(config: TokenHandlerConfig<TCustomClaims>, adapter: ITokenAdapter<TCustomClaims>): TokenHandler<TCustomClaims>;
68
+ //# sourceMappingURL=generic-token-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generic-token-handler.d.ts","sourceRoot":"","sources":["../src/generic-token-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EACL,aAAa,EACb,aAAa,EACb,uBAAuB,EAEvB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,eAAe,CAAC;AAGvB,qBAAa,YAAY,CAAC,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAC3D,YAAW,aAAa,CAAC,aAAa,CAAC;IAKrC,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IAJjB,OAAO,CAAC,gBAAgB,CAAwB;gBAGtC,MAAM,EAAE,kBAAkB,CAAC,aAAa,CAAC,EACzC,OAAO,EAAE,aAAa,CAAC,aAAa,CAAC;IAQ/C;;;OAGG;IACG,eAAe,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,uBAAuB,CAAC,aAAa,CAAC,CAAC;IA8FlD;;OAEG;IACG,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI3D;;OAEG;IACG,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAShB;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASzE;;OAEG;IACG,cAAc,CAClB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,IAAI,EACpB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,mBAAmB,CAAC;IAW/B;;OAEG;IACG,sBAAsB,CAC1B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAShB;;OAEG;IACG,kBAAkB,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAInF;;OAEG;IACG,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAIvF;;OAEG;IACG,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI5D;;OAEG;IACH,SAAS,IAAI,kBAAkB,CAAC,aAAa,CAAC;IAI9C;;;OAGG;IACH,OAAO,CAAC,cAAc;IAKtB;;;OAGG;IACH,OAAO,CAAC,eAAe;CAGxB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACpE,MAAM,EAAE,kBAAkB,CAAC,aAAa,CAAC,EACzC,OAAO,EAAE,aAAa,CAAC,aAAa,CAAC,GACpC,YAAY,CAAC,aAAa,CAAC,CAE7B"}