firebase-admin-edge 1.0.22 → 1.0.24
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 +58 -20
- package/dist/auth/cache-types.d.ts +7 -0
- package/dist/auth/cache-types.d.ts.map +1 -0
- package/dist/auth/cache-types.js +2 -0
- package/dist/auth/cache-types.js.map +1 -0
- package/dist/auth/cookie-types.d.ts +4 -0
- package/dist/auth/cookie-types.d.ts.map +1 -1
- package/dist/auth/firebase-admin-auth.d.ts +82 -11
- package/dist/auth/firebase-admin-auth.d.ts.map +1 -1
- package/dist/auth/firebase-admin-auth.js +134 -35
- package/dist/auth/firebase-admin-auth.js.map +1 -1
- package/dist/auth/firebase-admin-auth.test.js +39 -51
- package/dist/auth/firebase-admin-auth.test.js.map +1 -1
- package/dist/auth/firebase-auth-endpoints.d.ts +10 -4
- package/dist/auth/firebase-auth-endpoints.d.ts.map +1 -1
- package/dist/auth/firebase-auth-endpoints.js +10 -5
- package/dist/auth/firebase-auth-endpoints.js.map +1 -1
- package/dist/auth/firebase-auth-endpoints.test.js +8 -8
- package/dist/auth/firebase-auth-endpoints.test.js.map +1 -1
- package/dist/auth/firebase-auth.d.ts +33 -0
- package/dist/auth/firebase-auth.d.ts.map +1 -1
- package/dist/auth/firebase-auth.js +33 -0
- package/dist/auth/firebase-auth.js.map +1 -1
- package/dist/auth/firebase-jwt.d.ts.map +1 -1
- package/dist/auth/firebase-jwt.js +1 -0
- package/dist/auth/firebase-jwt.js.map +1 -1
- package/dist/auth/firebase-types.d.ts +5 -29
- package/dist/auth/firebase-types.d.ts.map +1 -1
- package/dist/auth/google-oauth.d.ts +5 -10
- package/dist/auth/google-oauth.d.ts.map +1 -1
- package/dist/auth/google-oauth.js +12 -1
- package/dist/auth/google-oauth.js.map +1 -1
- package/dist/firebase-edge-errors.d.ts +8 -0
- package/dist/firebase-edge-errors.d.ts.map +1 -1
- package/dist/firebase-edge-errors.js +8 -0
- package/dist/firebase-edge-errors.js.map +1 -1
- package/dist/firebase-edge-server.d.ts +18 -12
- package/dist/firebase-edge-server.d.ts.map +1 -1
- package/dist/firebase-edge-server.js +115 -43
- package/dist/firebase-edge-server.js.map +1 -1
- package/dist/firebase-edge-server.test.js +5 -5
- package/dist/firebase-edge-server.test.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/token-cache.d.ts +9 -0
- package/dist/utils/token-cache.d.ts.map +1 -0
- package/dist/utils/token-cache.js +27 -0
- package/dist/utils/token-cache.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -23,9 +23,12 @@ npm i firebase-admin-edge
|
|
|
23
23
|
### Basic setup
|
|
24
24
|
|
|
25
25
|
```typescript
|
|
26
|
-
import { createFirebaseEdgeServer } from 'firebase-admin-edge';
|
|
26
|
+
import { createFirebaseEdgeServer, TokenCache } from 'firebase-admin-edge';
|
|
27
27
|
import { getCookie, setCookie } from 'your-framework-library';
|
|
28
28
|
|
|
29
|
+
// Optional: Create a cache for service account tokens (recommended for performance)
|
|
30
|
+
const cache = new TokenCache();
|
|
31
|
+
|
|
29
32
|
// Create the edge server once during initialization. Keep secrets out of
|
|
30
33
|
// source control — load the `serviceAccount` and client secrets from
|
|
31
34
|
// environment variables or a secret manager.
|
|
@@ -44,6 +47,10 @@ export const firebaseServer = createFirebaseEdgeServer({
|
|
|
44
47
|
google: {
|
|
45
48
|
client_id: 'your-google-oauth-client-id',
|
|
46
49
|
client_secret: 'your-google-oauth-client-secret'
|
|
50
|
+
},
|
|
51
|
+
github: {
|
|
52
|
+
client_id: 'your-github-oauth-client-id',
|
|
53
|
+
client_secret: 'your-github-oauth-client-secret'
|
|
47
54
|
}
|
|
48
55
|
},
|
|
49
56
|
cookies: {
|
|
@@ -51,8 +58,27 @@ export const firebaseServer = createFirebaseEdgeServer({
|
|
|
51
58
|
getSession: (name) => getCookie(name),
|
|
52
59
|
saveSession: (name, value, options) => setCookie(name, value, options)
|
|
53
60
|
},
|
|
61
|
+
// Optional: Token caching for improved performance (tokens cached for 1 hour)
|
|
62
|
+
cache: {
|
|
63
|
+
getCache: (name) => cache.get(name),
|
|
64
|
+
setCache: (name, value, ttl) => cache.set(name, value, ttl)
|
|
65
|
+
},
|
|
66
|
+
// Optional: Custom session cookie name (defaults to '__session')
|
|
67
|
+
cookieName: '__session',
|
|
68
|
+
// Optional: Custom cookie options
|
|
69
|
+
cookieOptions: {
|
|
70
|
+
httpOnly: true,
|
|
71
|
+
secure: true,
|
|
72
|
+
sameSite: 'lax',
|
|
73
|
+
path: '/',
|
|
74
|
+
maxAge: 60 * 60 * 24 * 5 // 5 days
|
|
75
|
+
},
|
|
54
76
|
// OAuth callback URL (registered with your provider)
|
|
55
|
-
redirectUri: 'https://example.com/auth/callback'
|
|
77
|
+
redirectUri: 'https://example.com/auth/callback',
|
|
78
|
+
// Optional: Tenant ID for multi-tenancy
|
|
79
|
+
tenantId: 'your-tenant-id',
|
|
80
|
+
// Optional: Automatically link accounts with same email
|
|
81
|
+
autoLinkProviders: false
|
|
56
82
|
});
|
|
57
83
|
```
|
|
58
84
|
|
|
@@ -99,29 +125,41 @@ redirect(302, '/');
|
|
|
99
125
|
- ✅ **Zero Dependencies** - Uses only fetch API and jose
|
|
100
126
|
- ✅ **TypeScript Support** - Full type safety and IntelliSense
|
|
101
127
|
- ✅ **Session Management** - Secure HTTP-only cookies
|
|
102
|
-
- ✅ **
|
|
128
|
+
- ✅ **OAuth Support** - Google and GitHub OAuth 2.0 flows
|
|
103
129
|
- ✅ **Token Management** - Generate client tokens from server sessions
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
- ☐ Magic Link (auto save email
|
|
111
|
-
- ☐
|
|
112
|
-
- ☐
|
|
113
|
-
- ☐
|
|
130
|
+
- ✅ **Token Caching** - Optional caching for service account tokens (1-hour TTL)
|
|
131
|
+
- ✅ **Multi-Tenancy** - Support for Firebase Auth tenant IDs
|
|
132
|
+
- ✅ **Flexible Configuration** - Customizable cookie options and cache implementations
|
|
133
|
+
|
|
134
|
+
## Firebase Auth Todo
|
|
135
|
+
|
|
136
|
+
- ☐ Magic Link Login (auto save email option)
|
|
137
|
+
- ☐ Link and Unlink Providers
|
|
138
|
+
- ☐ Email / Password / Annonymous Login
|
|
139
|
+
- ☐ Reset Password
|
|
140
|
+
- ☐ Change Email
|
|
141
|
+
- ☐ Get User By ID
|
|
142
|
+
- ☐ Get All Users with Order By and Pagination
|
|
143
|
+
- ☐ Create User
|
|
144
|
+
- ☐ Delete
|
|
114
145
|
- ☐ Update User
|
|
115
|
-
- ☐ Delete User
|
|
116
146
|
- ☐ Add / Remove Custom Claims
|
|
117
|
-
- ☐
|
|
118
|
-
- ☐ All Providers
|
|
147
|
+
- ☐ Disable User (Ban User)
|
|
148
|
+
- ☐ Add All Providers
|
|
149
|
+
- ☐ Add App Check
|
|
119
150
|
- ☐ Ban Users
|
|
120
151
|
- ☐ RBAC
|
|
121
152
|
|
|
122
|
-
|
|
153
|
+
## Firestore Todo
|
|
154
|
+
|
|
155
|
+
- ☐ Get Document By ID
|
|
156
|
+
- ☐ Create Document
|
|
157
|
+
- ☐ Update Document (merge option)
|
|
158
|
+
- ☐ Delete Document
|
|
159
|
+
- ☐ Query Documents
|
|
123
160
|
|
|
124
|
-
|
|
125
|
-
- (enableTokenRefreshOnExpiredKidHeader ? cookieSignatureKeys ?)
|
|
161
|
+
## Firebase Storage
|
|
126
162
|
|
|
127
|
-
|
|
163
|
+
- ☐ Create File
|
|
164
|
+
- ☐ Delete File
|
|
165
|
+
- ☐ Get File
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type SetCache = <T>(name: string, value: T, ttlMs?: number) => Promise<void> | void;
|
|
2
|
+
export type GetCache = <T>(name: string) => Promise<T | undefined> | T | undefined;
|
|
3
|
+
export type CacheConfig = {
|
|
4
|
+
getCache: GetCache;
|
|
5
|
+
setCache: SetCache;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=cache-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-types.d.ts","sourceRoot":"","sources":["../../src/auth/cache-types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,EACrB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,EACR,KAAK,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1B,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,EACrB,IAAI,EAAE,MAAM,KACX,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;AAE5C,MAAM,MAAM,WAAW,GAAG;IACtB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;CACtB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-types.js","sourceRoot":"","sources":["../../src/auth/cache-types.ts"],"names":[],"mappings":""}
|
|
@@ -16,4 +16,8 @@ export type CookieOptions = Partial<{
|
|
|
16
16
|
};
|
|
17
17
|
export type GetSession = (name: string) => Promise<string | null | undefined> | string | null | undefined;
|
|
18
18
|
export type SetSession = (name: string, value: string, options: CookieOptions) => Promise<void> | void;
|
|
19
|
+
export type CookieConfig = {
|
|
20
|
+
getSession: GetSession;
|
|
21
|
+
saveSession: SetSession;
|
|
22
|
+
};
|
|
19
23
|
//# sourceMappingURL=cookie-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookie-types.d.ts","sourceRoot":"","sources":["../../src/auth/cookie-types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC7B,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC;IAChC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,QAAQ,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACjD,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtB,MAAM,MAAM,UAAU,GAAG,CACrB,IAAI,EAAE,MAAM,KACX,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAEpE,MAAM,MAAM,UAAU,GAAG,CACrB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,KACrB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC"}
|
|
1
|
+
{"version":3,"file":"cookie-types.d.ts","sourceRoot":"","sources":["../../src/auth/cookie-types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC7B,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC;IAChC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,QAAQ,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACjD,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtB,MAAM,MAAM,UAAU,GAAG,CACrB,IAAI,EAAE,MAAM,KACX,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAEpE,MAAM,MAAM,UAAU,GAAG,CACrB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,KACrB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1B,MAAM,MAAM,YAAY,GAAG;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,UAAU,CAAC;CAC3B,CAAC"}
|
|
@@ -1,40 +1,111 @@
|
|
|
1
1
|
import type { ServiceAccount } from './firebase-types.js';
|
|
2
2
|
import { FirebaseEdgeError } from './errors.js';
|
|
3
|
+
import type { CacheConfig } from './cache-types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Firebase Admin Authentication handler for edge environments.
|
|
6
|
+
* Provides server-side authentication operations using service account credentials.
|
|
7
|
+
*/
|
|
3
8
|
export declare class FirebaseAdminAuth {
|
|
4
9
|
private serviceAccountKey;
|
|
5
10
|
private tenantId?;
|
|
6
11
|
private fetch?;
|
|
7
|
-
|
|
12
|
+
private cache?;
|
|
13
|
+
private cacheName?;
|
|
14
|
+
private _cacheName;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new Firebase Admin Auth instance.
|
|
17
|
+
*
|
|
18
|
+
* @param serviceAccountKey Firebase service account credentials
|
|
19
|
+
* @param tenantId Optional tenant ID for multi-tenancy
|
|
20
|
+
* @param fetch Optional custom fetch implementation
|
|
21
|
+
* @param cache Optional cache implementation for token caching
|
|
22
|
+
* @param cacheName Optional cache key name (defaults to '__cache')
|
|
23
|
+
*/
|
|
24
|
+
constructor(serviceAccountKey: ServiceAccount, tenantId?: string | undefined, fetch?: typeof globalThis.fetch | undefined, cache?: CacheConfig | undefined, cacheName?: string | undefined);
|
|
25
|
+
/**
|
|
26
|
+
* Retrieves a cached service account token or fetches a new one.
|
|
27
|
+
* Tokens are cached for 1 hour.
|
|
28
|
+
*
|
|
29
|
+
* @returns Promise with token data and error
|
|
30
|
+
*/
|
|
31
|
+
private getCachedToken;
|
|
32
|
+
/**
|
|
33
|
+
* Retrieves user account information by UID.
|
|
34
|
+
*
|
|
35
|
+
* @param uid User ID to look up
|
|
36
|
+
* @returns Promise with object containing user data or null, and error if any
|
|
37
|
+
*/
|
|
8
38
|
getUser(uid: string): Promise<{
|
|
9
39
|
data: null;
|
|
10
40
|
error: FirebaseEdgeError;
|
|
11
41
|
} | {
|
|
12
|
-
data: import("./firebase-types.js").
|
|
42
|
+
data: import("./firebase-types.js").UserInfo | null | undefined;
|
|
13
43
|
error: null;
|
|
14
44
|
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Retrieves user account information by email address.
|
|
47
|
+
*
|
|
48
|
+
* @param email Email address to look up
|
|
49
|
+
* @returns Promise with object containing user data or null, and error if any
|
|
50
|
+
*/
|
|
51
|
+
getUserByEmail(email: string): Promise<{
|
|
52
|
+
data: null;
|
|
53
|
+
error: FirebaseEdgeError;
|
|
54
|
+
} | {
|
|
55
|
+
data: import("./firebase-types.js").UserInfo | null | undefined;
|
|
56
|
+
error: null;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Verifies a Firebase ID token and returns the decoded payload.
|
|
60
|
+
* Optionally checks if the token has been revoked.
|
|
61
|
+
*
|
|
62
|
+
* @param idToken Firebase ID token to verify
|
|
63
|
+
* @param checkRevoked Whether to check if token has been revoked (defaults to false)
|
|
64
|
+
* @returns Promise with object containing decoded token payload or null, and error if any
|
|
65
|
+
*/
|
|
15
66
|
verifyIdToken(idToken: string, checkRevoked?: boolean): Promise<{
|
|
67
|
+
data: null;
|
|
68
|
+
error: FirebaseEdgeError;
|
|
69
|
+
} | {
|
|
16
70
|
data: import("./firebase-types.js").FirebaseIdTokenPayload;
|
|
17
71
|
error: null;
|
|
18
|
-
} | {
|
|
19
|
-
data: null;
|
|
20
|
-
error: Error;
|
|
21
72
|
}>;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Creates a session cookie from a Firebase ID token.
|
|
75
|
+
*
|
|
76
|
+
* @param idToken Firebase ID token to convert to session cookie
|
|
77
|
+
* @param expiresIn_ms Session cookie expiration time in milliseconds
|
|
78
|
+
* @returns Promise with object containing session cookie string or null, and error if any
|
|
79
|
+
*/
|
|
80
|
+
createSessionCookie(idToken: string, expiresIn_ms: number): Promise<{
|
|
25
81
|
data: null;
|
|
26
82
|
error: FirebaseEdgeError;
|
|
27
83
|
} | {
|
|
28
84
|
data: string | null;
|
|
29
85
|
error: null;
|
|
30
86
|
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Verifies a Firebase session cookie and returns the decoded payload.
|
|
89
|
+
* Optionally checks if the token has been revoked.
|
|
90
|
+
*
|
|
91
|
+
* @param sessionCookie Session cookie to verify
|
|
92
|
+
* @param checkRevoked Whether to check if token has been revoked (defaults to false)
|
|
93
|
+
* @returns Promise with object containing decoded session payload or null, and error if any
|
|
94
|
+
*/
|
|
31
95
|
verifySessionCookie(sessionCookie: string, checkRevoked?: boolean): Promise<{
|
|
96
|
+
data: null;
|
|
97
|
+
error: FirebaseEdgeError;
|
|
98
|
+
} | {
|
|
32
99
|
data: import("./firebase-types.js").FirebaseIdTokenPayload;
|
|
33
100
|
error: null;
|
|
34
|
-
} | {
|
|
35
|
-
data: null;
|
|
36
|
-
error: Error;
|
|
37
101
|
}>;
|
|
102
|
+
/**
|
|
103
|
+
* Creates a custom Firebase authentication token for a given user.
|
|
104
|
+
*
|
|
105
|
+
* @param uid User ID to create token for
|
|
106
|
+
* @param developerClaims Optional custom claims to include in the token
|
|
107
|
+
* @returns Promise with object containing custom token string or null, and error if any
|
|
108
|
+
*/
|
|
38
109
|
createCustomToken(uid: string, developerClaims?: object): Promise<{
|
|
39
110
|
data: null;
|
|
40
111
|
error: FirebaseEdgeError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"firebase-admin-auth.d.ts","sourceRoot":"","sources":["../../src/auth/firebase-admin-auth.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"firebase-admin-auth.d.ts","sourceRoot":"","sources":["../../src/auth/firebase-admin-auth.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAuB,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE/E,OAAO,EACH,iBAAiB,EAGpB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;GAGG;AACH,qBAAa,iBAAiB;IAatB,OAAO,CAAC,iBAAiB;IACzB,OAAO,CAAC,QAAQ,CAAC;IACjB,OAAO,CAAC,KAAK,CAAC;IACd,OAAO,CAAC,KAAK,CAAC;IACd,OAAO,CAAC,SAAS,CAAC;IAhBtB,OAAO,CAAC,UAAU,CAAa;IAE/B;;;;;;;;OAQG;gBAES,iBAAiB,EAAE,cAAc,EACjC,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,YAAA,EAC/B,KAAK,CAAC,EAAE,WAAW,YAAA,EACnB,SAAS,CAAC,EAAE,MAAM,YAAA;IAK9B;;;;;OAKG;YACW,cAAc;IAoC5B;;;;;OAKG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM;;;;;;;IA+BzB;;;;;OAKG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM;;;;;;;IA+BlC;;;;;;;OAOG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,GAAE,OAAe;;;;;;;IAwGlE;;;;;;OAMG;IACG,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;;;;;;;IAuC/D;;;;;;;OAOG;IACG,mBAAmB,CACrB,aAAa,EAAE,MAAM,EACrB,YAAY,GAAE,OAAe;;;;;;;IAgFjC;;;;;;OAMG;IACG,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,GAAE,MAAW;;;;;;;CAmCpE"}
|
|
@@ -1,32 +1,106 @@
|
|
|
1
|
-
import { createSessionCookie,
|
|
1
|
+
import { createSessionCookie, getAccountInfo } from './firebase-auth-endpoints.js';
|
|
2
2
|
import { signJWTCustomToken, verifyJWT, verifySessionJWT } from './firebase-jwt.js';
|
|
3
3
|
import { getToken } from './google-oauth.js';
|
|
4
4
|
import { FirebaseEdgeError, FirebaseAdminAuthErrorInfo, ensureError } from './errors.js';
|
|
5
|
+
/**
|
|
6
|
+
* Firebase Admin Authentication handler for edge environments.
|
|
7
|
+
* Provides server-side authentication operations using service account credentials.
|
|
8
|
+
*/
|
|
5
9
|
export class FirebaseAdminAuth {
|
|
6
10
|
serviceAccountKey;
|
|
7
11
|
tenantId;
|
|
8
12
|
fetch;
|
|
9
|
-
|
|
13
|
+
cache;
|
|
14
|
+
cacheName;
|
|
15
|
+
_cacheName = '__cache';
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new Firebase Admin Auth instance.
|
|
18
|
+
*
|
|
19
|
+
* @param serviceAccountKey Firebase service account credentials
|
|
20
|
+
* @param tenantId Optional tenant ID for multi-tenancy
|
|
21
|
+
* @param fetch Optional custom fetch implementation
|
|
22
|
+
* @param cache Optional cache implementation for token caching
|
|
23
|
+
* @param cacheName Optional cache key name (defaults to '__cache')
|
|
24
|
+
*/
|
|
25
|
+
constructor(serviceAccountKey, tenantId, fetch, cache, cacheName) {
|
|
10
26
|
this.serviceAccountKey = serviceAccountKey;
|
|
11
27
|
this.tenantId = tenantId;
|
|
12
28
|
this.fetch = fetch;
|
|
29
|
+
this.cache = cache;
|
|
30
|
+
this.cacheName = cacheName;
|
|
31
|
+
this._cacheName = this.cacheName || this._cacheName;
|
|
13
32
|
}
|
|
14
|
-
|
|
15
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Retrieves a cached service account token or fetches a new one.
|
|
35
|
+
* Tokens are cached for 1 hour.
|
|
36
|
+
*
|
|
37
|
+
* @returns Promise with token data and error
|
|
38
|
+
*/
|
|
39
|
+
async getCachedToken() {
|
|
40
|
+
const cachedToken = await this.cache?.getCache(this._cacheName);
|
|
41
|
+
if (cachedToken) {
|
|
42
|
+
return {
|
|
43
|
+
data: cachedToken,
|
|
44
|
+
error: null
|
|
45
|
+
};
|
|
46
|
+
}
|
|
16
47
|
const { data: token, error: getTokenError } = await getToken(this.serviceAccountKey, this.fetch);
|
|
48
|
+
if (token && this.cache) {
|
|
49
|
+
// Google tokens are valid for 1 hour
|
|
50
|
+
this.cache?.setCache('token', token, 3600);
|
|
51
|
+
}
|
|
17
52
|
if (getTokenError) {
|
|
18
53
|
return {
|
|
19
54
|
data: null,
|
|
20
|
-
error:
|
|
55
|
+
error: getTokenError
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
data: token,
|
|
60
|
+
error: null
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Retrieves user account information by UID.
|
|
65
|
+
*
|
|
66
|
+
* @param uid User ID to look up
|
|
67
|
+
* @returns Promise with object containing user data or null, and error if any
|
|
68
|
+
*/
|
|
69
|
+
async getUser(uid) {
|
|
70
|
+
const { data: token, error: tokenError } = await this.getCachedToken();
|
|
71
|
+
if (tokenError) {
|
|
72
|
+
return {
|
|
73
|
+
data: null,
|
|
74
|
+
error: tokenError
|
|
21
75
|
};
|
|
22
76
|
}
|
|
23
|
-
|
|
77
|
+
const { data, error } = await getAccountInfo({ uid }, token.access_token, this.serviceAccountKey.project_id, this.tenantId, this.fetch);
|
|
78
|
+
if (error) {
|
|
79
|
+
return {
|
|
80
|
+
data: null,
|
|
81
|
+
error
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
data,
|
|
86
|
+
error: null
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Retrieves user account information by email address.
|
|
91
|
+
*
|
|
92
|
+
* @param email Email address to look up
|
|
93
|
+
* @returns Promise with object containing user data or null, and error if any
|
|
94
|
+
*/
|
|
95
|
+
async getUserByEmail(email) {
|
|
96
|
+
const { data: token, error: tokenError } = await this.getCachedToken();
|
|
97
|
+
if (tokenError) {
|
|
24
98
|
return {
|
|
25
99
|
data: null,
|
|
26
|
-
error:
|
|
100
|
+
error: tokenError
|
|
27
101
|
};
|
|
28
102
|
}
|
|
29
|
-
const { data, error } = await
|
|
103
|
+
const { data, error } = await getAccountInfo({ email }, token.access_token, this.serviceAccountKey.project_id, this.tenantId, this.fetch);
|
|
30
104
|
if (error) {
|
|
31
105
|
return {
|
|
32
106
|
data: null,
|
|
@@ -38,6 +112,14 @@ export class FirebaseAdminAuth {
|
|
|
38
112
|
error: null
|
|
39
113
|
};
|
|
40
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Verifies a Firebase ID token and returns the decoded payload.
|
|
117
|
+
* Optionally checks if the token has been revoked.
|
|
118
|
+
*
|
|
119
|
+
* @param idToken Firebase ID token to verify
|
|
120
|
+
* @param checkRevoked Whether to check if token has been revoked (defaults to false)
|
|
121
|
+
* @returns Promise with object containing decoded token payload or null, and error if any
|
|
122
|
+
*/
|
|
41
123
|
async verifyIdToken(idToken, checkRevoked = false) {
|
|
42
124
|
const { data: decodedIdToken, error: verifyError } = await verifyJWT(idToken, this.serviceAccountKey.project_id, this.fetch);
|
|
43
125
|
if (verifyError) {
|
|
@@ -58,8 +140,11 @@ export class FirebaseAdminAuth {
|
|
|
58
140
|
if (tokenTenantId !== this.tenantId) {
|
|
59
141
|
return {
|
|
60
142
|
data: null,
|
|
61
|
-
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.
|
|
62
|
-
|
|
143
|
+
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_TENANT_ID_INVALID, {
|
|
144
|
+
context: {
|
|
145
|
+
tokenTenantId,
|
|
146
|
+
expectedTenantId: this.tenantId
|
|
147
|
+
}
|
|
63
148
|
})
|
|
64
149
|
};
|
|
65
150
|
}
|
|
@@ -74,13 +159,13 @@ export class FirebaseAdminAuth {
|
|
|
74
159
|
if (userError) {
|
|
75
160
|
return {
|
|
76
161
|
data: null,
|
|
77
|
-
error: new
|
|
162
|
+
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_USER_LOOKUP_FAILED, { cause: ensureError(userError) })
|
|
78
163
|
};
|
|
79
164
|
}
|
|
80
165
|
if (!user) {
|
|
81
166
|
return {
|
|
82
167
|
data: null,
|
|
83
|
-
error: new
|
|
168
|
+
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_USER_RECORD_NOT_FOUND)
|
|
84
169
|
};
|
|
85
170
|
}
|
|
86
171
|
if (user.disabled) {
|
|
@@ -89,13 +174,10 @@ export class FirebaseAdminAuth {
|
|
|
89
174
|
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_USER_DISABLED)
|
|
90
175
|
};
|
|
91
176
|
}
|
|
92
|
-
if (user.
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
const validSinceUtc = new Date(user.tokensValidAfterTime).getTime();
|
|
97
|
-
// Check if authentication time is older than valid since time.
|
|
98
|
-
if (authTimeUtc < validSinceUtc) {
|
|
177
|
+
if (user.validSince) {
|
|
178
|
+
const validSinceSeconds = Number(user.validSince);
|
|
179
|
+
const authTimeSeconds = decodedIdToken.auth_time;
|
|
180
|
+
if (authTimeSeconds < validSinceSeconds) {
|
|
99
181
|
return {
|
|
100
182
|
data: null,
|
|
101
183
|
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_ID_TOKEN_REVOKED)
|
|
@@ -107,21 +189,22 @@ export class FirebaseAdminAuth {
|
|
|
107
189
|
error: null
|
|
108
190
|
};
|
|
109
191
|
}
|
|
110
|
-
|
|
111
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Creates a session cookie from a Firebase ID token.
|
|
194
|
+
*
|
|
195
|
+
* @param idToken Firebase ID token to convert to session cookie
|
|
196
|
+
* @param expiresIn_ms Session cookie expiration time in milliseconds
|
|
197
|
+
* @returns Promise with object containing session cookie string or null, and error if any
|
|
198
|
+
*/
|
|
199
|
+
async createSessionCookie(idToken, expiresIn_ms) {
|
|
200
|
+
const { data: token, error: getTokenError } = await this.getCachedToken();
|
|
112
201
|
if (getTokenError) {
|
|
113
202
|
return {
|
|
114
203
|
data: null,
|
|
115
204
|
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_SERVICE_ACCOUNT_TOKEN_FAILED, { cause: getTokenError })
|
|
116
205
|
};
|
|
117
206
|
}
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
data: null,
|
|
121
|
-
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_NO_TOKEN_RETURNED)
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
const { data, error } = await createSessionCookie(idToken, token.access_token, this.serviceAccountKey.project_id, expiresIn, this.tenantId, this.fetch);
|
|
207
|
+
const { data, error } = await createSessionCookie(idToken, token.access_token, this.serviceAccountKey.project_id, expiresIn_ms, this.tenantId, this.fetch);
|
|
125
208
|
if (error) {
|
|
126
209
|
return {
|
|
127
210
|
data: null,
|
|
@@ -133,6 +216,14 @@ export class FirebaseAdminAuth {
|
|
|
133
216
|
error: null
|
|
134
217
|
};
|
|
135
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Verifies a Firebase session cookie and returns the decoded payload.
|
|
221
|
+
* Optionally checks if the token has been revoked.
|
|
222
|
+
*
|
|
223
|
+
* @param sessionCookie Session cookie to verify
|
|
224
|
+
* @param checkRevoked Whether to check if token has been revoked (defaults to false)
|
|
225
|
+
* @returns Promise with object containing decoded session payload or null, and error if any
|
|
226
|
+
*/
|
|
136
227
|
async verifySessionCookie(sessionCookie, checkRevoked = false) {
|
|
137
228
|
const { data, error } = await verifySessionJWT(sessionCookie, this.serviceAccountKey.project_id, this.fetch);
|
|
138
229
|
if (error) {
|
|
@@ -144,9 +235,7 @@ export class FirebaseAdminAuth {
|
|
|
144
235
|
if (!data) {
|
|
145
236
|
return {
|
|
146
237
|
data: null,
|
|
147
|
-
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_SESSION_COOKIE_VERIFY_FAILED
|
|
148
|
-
cause: new Error('No data returned from session cookie verification')
|
|
149
|
-
})
|
|
238
|
+
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_SESSION_COOKIE_VERIFY_FAILED)
|
|
150
239
|
};
|
|
151
240
|
}
|
|
152
241
|
// Validate tenant ID if specified
|
|
@@ -155,8 +244,11 @@ export class FirebaseAdminAuth {
|
|
|
155
244
|
if (tokenTenantId !== this.tenantId) {
|
|
156
245
|
return {
|
|
157
246
|
data: null,
|
|
158
|
-
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.
|
|
159
|
-
|
|
247
|
+
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_TENANT_ID_INVALID, {
|
|
248
|
+
context: {
|
|
249
|
+
tokenTenantId,
|
|
250
|
+
expectedTenantId: this.tenantId
|
|
251
|
+
}
|
|
160
252
|
})
|
|
161
253
|
};
|
|
162
254
|
}
|
|
@@ -171,13 +263,13 @@ export class FirebaseAdminAuth {
|
|
|
171
263
|
if (userError) {
|
|
172
264
|
return {
|
|
173
265
|
data: null,
|
|
174
|
-
error: new
|
|
266
|
+
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_USER_LOOKUP_FAILED, { cause: ensureError(userError) })
|
|
175
267
|
};
|
|
176
268
|
}
|
|
177
269
|
if (!user) {
|
|
178
270
|
return {
|
|
179
271
|
data: null,
|
|
180
|
-
error: new
|
|
272
|
+
error: new FirebaseEdgeError(FirebaseAdminAuthErrorInfo.ADMIN_USER_RECORD_NOT_FOUND)
|
|
181
273
|
};
|
|
182
274
|
}
|
|
183
275
|
return {
|
|
@@ -185,6 +277,13 @@ export class FirebaseAdminAuth {
|
|
|
185
277
|
error: null
|
|
186
278
|
};
|
|
187
279
|
}
|
|
280
|
+
/**
|
|
281
|
+
* Creates a custom Firebase authentication token for a given user.
|
|
282
|
+
*
|
|
283
|
+
* @param uid User ID to create token for
|
|
284
|
+
* @param developerClaims Optional custom claims to include in the token
|
|
285
|
+
* @returns Promise with object containing custom token string or null, and error if any
|
|
286
|
+
*/
|
|
188
287
|
async createCustomToken(uid, developerClaims = {}) {
|
|
189
288
|
const claims = this.tenantId
|
|
190
289
|
? { ...developerClaims, tenant_id: this.tenantId }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"firebase-admin-auth.js","sourceRoot":"","sources":["../../src/auth/firebase-admin-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACnB,
|
|
1
|
+
{"version":3,"file":"firebase-admin-auth.js","sourceRoot":"","sources":["../../src/auth/firebase-admin-auth.ts"],"names":[],"mappings":"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"}
|