@dereekb/firebase-server 13.11.2 → 13.11.4

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 (47) hide show
  1. package/index.cjs.js +29 -2
  2. package/index.esm.js +30 -3
  3. package/mailgun/package.json +9 -9
  4. package/model/index.cjs.js +330 -43
  5. package/model/index.esm.js +332 -46
  6. package/model/package.json +9 -9
  7. package/model/src/lib/notification/notification.action.server.d.ts +16 -1
  8. package/model/src/lib/notification/notification.module.d.ts +4 -0
  9. package/oidc/index.cjs.js +455 -38
  10. package/oidc/index.esm.js +453 -40
  11. package/oidc/package.json +10 -10
  12. package/oidc/src/lib/controller/oidc.interaction.controller.d.ts +3 -1
  13. package/oidc/src/lib/model/oidc/oidcmodel.action.server.d.ts +22 -1
  14. package/oidc/src/lib/model/oidc/oidcmodel.module.d.ts +6 -3
  15. package/oidc/src/lib/oidc.config.d.ts +82 -6
  16. package/oidc/src/lib/oidc.module.d.ts +1 -1
  17. package/oidc/src/lib/service/oidc.adapter.service.d.ts +5 -0
  18. package/oidc/src/lib/service/oidc.interaction.service.d.ts +7 -1
  19. package/oidc/src/lib/service/oidc.service.d.ts +31 -1
  20. package/oidc/src/lib/service/oidc.session-ttl.d.ts +85 -0
  21. package/package.json +10 -10
  22. package/src/lib/firestore/array.d.ts +1 -0
  23. package/src/lib/firestore/driver.accessor.batch.d.ts +1 -0
  24. package/src/lib/firestore/driver.accessor.default.d.ts +1 -0
  25. package/src/lib/firestore/driver.accessor.transaction.d.ts +1 -0
  26. package/src/lib/firestore/driver.query.d.ts +1 -0
  27. package/src/lib/firestore/increment.d.ts +1 -0
  28. package/src/lib/firestore/snapshot/snapshot.field.encrypt.d.ts +2 -0
  29. package/src/lib/nest/app.module.d.ts +1 -0
  30. package/src/lib/nest/auth/auth.module.d.ts +1 -0
  31. package/src/lib/nest/development/development.app.function.d.ts +1 -0
  32. package/src/lib/nest/development/development.function.d.ts +1 -0
  33. package/src/lib/nest/development/development.schedule.function.d.ts +1 -0
  34. package/src/lib/nest/development/development.schedule.function.error.d.ts +1 -0
  35. package/src/lib/nest/function/call.d.ts +1 -0
  36. package/src/lib/nest/function/context.d.ts +1 -0
  37. package/src/lib/nest/function/v2/blocking.d.ts +2 -0
  38. package/src/lib/nest/function/v2/call.d.ts +2 -0
  39. package/src/lib/nest/function/v2/event.d.ts +1 -0
  40. package/src/lib/nest/function/v2/schedule.d.ts +3 -0
  41. package/src/lib/nest/function/v2/taskqueue.d.ts +1 -0
  42. package/src/lib/nest/model/analytics.handler.d.ts +1 -0
  43. package/src/lib/nest/model/call.model.function.d.ts +1 -0
  44. package/src/lib/nest/model/create.model.function.d.ts +1 -0
  45. package/src/lib/nest/storage/storage.module.d.ts +1 -0
  46. package/test/package.json +11 -11
  47. package/zoho/package.json +9 -9
package/oidc/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/oidc",
3
- "version": "13.11.2",
3
+ "version": "13.11.4",
4
4
  "peerDependencies": {
5
- "@dereekb/analytics": "13.11.2",
6
- "@dereekb/date": "13.11.2",
7
- "@dereekb/firebase": "13.11.2",
8
- "@dereekb/firebase-server": "13.11.2",
9
- "@dereekb/model": "13.11.2",
10
- "@dereekb/nestjs": "13.11.2",
11
- "@dereekb/rxjs": "13.11.2",
12
- "@dereekb/util": "13.11.2",
13
- "@dereekb/zoho": "13.11.2",
5
+ "@dereekb/analytics": "13.11.4",
6
+ "@dereekb/date": "13.11.4",
7
+ "@dereekb/firebase": "13.11.4",
8
+ "@dereekb/firebase-server": "13.11.4",
9
+ "@dereekb/model": "13.11.4",
10
+ "@dereekb/nestjs": "13.11.4",
11
+ "@dereekb/rxjs": "13.11.4",
12
+ "@dereekb/util": "13.11.4",
13
+ "@dereekb/zoho": "13.11.4",
14
14
  "@nestjs/common": "^11.1.19",
15
15
  "@nestjs/config": "^4.0.4",
16
16
  "express": "^5.2.1",
@@ -3,6 +3,7 @@ import { OidcProviderConfigService } from '../service';
3
3
  import { type OAuthInteractionConsentRequest, type OAuthInteractionLoginRequest, type OidcInteractionUid } from '@dereekb/firebase';
4
4
  import { OidcAccountService } from '../service/oidc.account.service';
5
5
  import { OidcInteractionService } from '../service/oidc.interaction.service';
6
+ import { OidcService } from '../service/oidc.service';
6
7
  /**
7
8
  * Controller for OIDC interaction endpoints (login/consent).
8
9
  *
@@ -17,7 +18,8 @@ export declare class OidcInteractionController {
17
18
  private readonly oidcInteractionService;
18
19
  private readonly oidcProviderConfigService;
19
20
  private readonly accountService;
20
- constructor(oidcInteractionService: OidcInteractionService, oidcProviderConfigService: OidcProviderConfigService, accountService: OidcAccountService);
21
+ private readonly oidcService;
22
+ constructor(oidcInteractionService: OidcInteractionService, oidcProviderConfigService: OidcProviderConfigService, accountService: OidcAccountService, oidcService: OidcService);
21
23
  /**
22
24
  * GET /interaction/:uid
23
25
  *
@@ -1,6 +1,7 @@
1
- import { type AsyncFirebaseFunctionCreateAction, type AsyncOidcEntryUpdateAction, type AsyncOidcEntryDeleteAction, type CreateOidcClientParams, type CreateOidcClientResult, type UpdateOidcClientParams, type DeleteOidcClientParams, type RotateOidcClientSecretParams, type RotateOidcClientSecretResult, type OidcEntryDocument } from '@dereekb/firebase';
1
+ import { type AsyncFirebaseFunctionCreateAction, type AsyncOidcEntryUpdateAction, type AsyncOidcEntryDeleteAction, type CreateOidcClientParams, type CreateOidcClientResult, type UpdateOidcClientParams, type DeleteOidcClientParams, type DeleteOidcTokenParams, type RotateOidcClientSecretParams, type RotateOidcClientSecretResult, type OidcEntryDocument } from '@dereekb/firebase';
2
2
  import { type FirebaseServerActionsContext } from '@dereekb/firebase-server';
3
3
  import { type OidcClientService } from '../../service/oidc.client.service';
4
+ import { type OidcService } from '../../service/oidc.service';
4
5
  /**
5
6
  * Context providing the OIDC client service and server action utilities needed by OIDC model server actions.
6
7
  */
@@ -9,6 +10,10 @@ export interface OidcModelServerActionsContext extends FirebaseServerActionsCont
9
10
  * Service for managing OIDC client adapter entries.
10
11
  */
11
12
  readonly oidcClientService: OidcClientService;
13
+ /**
14
+ * Core OIDC service used for grant revocation.
15
+ */
16
+ readonly oidcService: OidcService;
12
17
  }
13
18
  /**
14
19
  * Abstract service class defining all server-side OIDC client CRUD actions.
@@ -20,6 +25,7 @@ export declare abstract class OidcModelServerActions {
20
25
  abstract updateOidcClient(params: UpdateOidcClientParams): AsyncOidcEntryUpdateAction<UpdateOidcClientParams>;
21
26
  abstract rotateOidcClientSecret(params: RotateOidcClientSecretParams): AsyncFirebaseFunctionCreateAction<RotateOidcClientSecretParams, RotateOidcClientSecretResult, OidcEntryDocument>;
22
27
  abstract deleteOidcClient(params: DeleteOidcClientParams): AsyncOidcEntryDeleteAction<DeleteOidcClientParams>;
28
+ abstract deleteOidcToken(params: DeleteOidcTokenParams): AsyncOidcEntryDeleteAction<DeleteOidcTokenParams>;
23
29
  }
24
30
  /**
25
31
  * Creates a concrete {@link OidcModelServerActions} implementation wired to the provided context.
@@ -73,3 +79,18 @@ export declare function rotateOidcClientSecretFactory(context: OidcModelServerAc
73
79
  * @returns a transform function factory for deleting OIDC clients
74
80
  */
75
81
  export declare function deleteOidcClientFactory(context: OidcModelServerActionsContext): import("@dereekb/model").TransformAndValidateFunctionResultFunction<import("@dereekb/firebase").TargetModelParams, (document: OidcEntryDocument) => Promise<void>, object, unknown>;
82
+ /**
83
+ * Factory for the `deleteOidcToken` action.
84
+ *
85
+ * Asserts the target {@link OidcEntryDocument} is of type `Grant`, then delegates to
86
+ * {@link OidcService.revokeGrant} so all grantable token entries (`AccessToken`,
87
+ * `RefreshToken`, `AuthorizationCode`, `DeviceCode`, `BackchannelAuthenticationRequest`)
88
+ * sharing the grant id are deleted along with the Grant entry itself.
89
+ *
90
+ * Per-user authorization (this user owns this Grant) is enforced upstream via the
91
+ * model permission service before this action runs.
92
+ *
93
+ * @param context - the OIDC model server actions context
94
+ * @returns a transform function factory for revoking OIDC grants
95
+ */
96
+ export declare function deleteOidcTokenFactory(context: OidcModelServerActionsContext): import("@dereekb/model").TransformAndValidateFunctionResultFunction<import("@dereekb/firebase").TargetModelParams, (document: OidcEntryDocument) => Promise<void>, object, unknown>;
@@ -1,17 +1,20 @@
1
1
  import { type ModuleMetadata } from '@nestjs/common';
2
2
  import { OidcModelServerActions } from './oidcmodel.action.server';
3
3
  import { OidcClientService } from '../../service/oidc.client.service';
4
+ import { OidcService } from '../../service/oidc.service';
4
5
  /**
5
- * Factory that creates an {@link OidcModelServerActions} instance from the injected {@link OidcClientService}.
6
+ * Factory that creates an {@link OidcModelServerActions} instance from the injected services.
6
7
  *
7
- * @param oidcClientService - the OIDC client service to wire into the server actions
8
+ * @param oidcClientService - the OIDC client service for client CRUD actions
9
+ * @param oidcService - the core OIDC service for grant revocation
8
10
  * @returns the configured OidcModelServerActions instance
9
11
  */
10
- export declare function oidcModelServerActionsFactory(oidcClientService: OidcClientService): OidcModelServerActions;
12
+ export declare function oidcModelServerActionsFactory(oidcClientService: OidcClientService, oidcService: OidcService): OidcModelServerActions;
11
13
  export interface ProvideAppOidcModelMetadataConfig {
12
14
  /**
13
15
  * The OidcModule that exports the required OIDC dependencies:
14
16
  * - {@link OidcClientService}
17
+ * - {@link OidcService}
15
18
  */
16
19
  readonly oidcModule: Required<ModuleMetadata>['imports']['0'];
17
20
  }
@@ -1,5 +1,5 @@
1
1
  import type { Configuration } from 'oidc-provider';
2
- import { type WebsitePath, type SlashPath } from '@dereekb/util';
2
+ import { type WebsitePath, type SlashPath, type Seconds } from '@dereekb/util';
3
3
  import { type OidcScope, type OidcTokenEndpointAuthMethod } from '@dereekb/firebase';
4
4
  import { type JwksServiceConfig } from './service/oidc.jwks.service';
5
5
  import { type JwksKeyConverterConfig } from './model';
@@ -49,27 +49,51 @@ export interface OidcProviderConfig<S extends OidcScope = OidcScope> {
49
49
  }
50
50
  /**
51
51
  * Configures the lifetime (in seconds) for each token type issued by the OIDC provider.
52
+ *
53
+ * `session` and `grant` set the *default* TTLs; the effective values may be reduced when a
54
+ * client passes the `dbx_session_ttl` request param (see {@link OidcModuleConfig.maxRequestedLoginDuration}).
52
55
  */
53
56
  export interface OidcTokenLifetimes {
54
57
  /**
55
58
  * Access token lifetime in seconds. Defaults to 900 (15 min).
56
59
  */
57
- readonly accessToken: number;
60
+ readonly accessToken: Seconds;
58
61
  /**
59
62
  * ID token lifetime in seconds. Defaults to 3600 (1 hour).
60
63
  */
61
- readonly idToken: number;
64
+ readonly idToken: Seconds;
62
65
  /**
63
66
  * Refresh token lifetime in seconds (absolute). Defaults to 2592000 (30 days).
64
67
  */
65
- readonly refreshToken: number;
68
+ readonly refreshToken: Seconds;
66
69
  /**
67
70
  * Authorization code lifetime in seconds. Defaults to 60.
68
71
  */
69
- readonly authorizationCode: number;
72
+ readonly authorizationCode: Seconds;
73
+ /**
74
+ * Session lifetime in seconds. Defaults to 2592000 (30 days).
75
+ *
76
+ * Caps how long a user's authenticated session at the IdP lasts before re-authentication is required.
77
+ */
78
+ readonly session: Seconds;
79
+ /**
80
+ * Grant lifetime in seconds. Defaults to 2592000 (30 days).
81
+ *
82
+ * Caps how long a granted authorization (consent) lasts. Once the grant expires, refresh tokens
83
+ * issued under it stop working and the user must re-consent.
84
+ */
85
+ readonly grant: Seconds;
70
86
  }
71
87
  /**
72
- * Default token lifetimes: 15 min access tokens, 30-day refresh tokens, 60 s auth codes.
88
+ * Default global ceiling for a client-requested login duration, in seconds. 90 days.
89
+ */
90
+ export declare const DEFAULT_MAX_REQUESTED_LOGIN_DURATION_SECONDS: number;
91
+ /**
92
+ * Default global floor for a client-requested login duration, in seconds. 1 hour.
93
+ */
94
+ export declare const DEFAULT_MIN_REQUESTED_LOGIN_DURATION_SECONDS: number;
95
+ /**
96
+ * Default token lifetimes: 15 min access tokens, 30-day refresh tokens, 30-day sessions/grants, 60 s auth codes.
73
97
  */
74
98
  export declare const DEFAULT_OIDC_TOKEN_LIFETIMES: OidcTokenLifetimes;
75
99
  /**
@@ -108,6 +132,29 @@ export declare abstract class OidcModuleConfig {
108
132
  * Token lifetime configuration.
109
133
  */
110
134
  readonly tokenLifetimes: OidcTokenLifetimes;
135
+ /**
136
+ * Maximum login duration (seconds) a client may request via the `dbx_session_ttl` auth-URL param.
137
+ *
138
+ * Acts as the global server cap for any per-request duration. A registered client can declare its own
139
+ * lower ceiling via the `dbx_max_session_ttl` client metadata field; the effective ceiling is
140
+ * `min(client.dbx_max_session_ttl, this)`.
141
+ *
142
+ * Defaults to {@link DEFAULT_MAX_REQUESTED_LOGIN_DURATION_SECONDS} (90 days).
143
+ */
144
+ readonly maxRequestedLoginDuration?: number;
145
+ /**
146
+ * Minimum login duration (seconds) a client may request via the `dbx_session_ttl` auth-URL param.
147
+ *
148
+ * Requested values below this floor are clamped up. Prevents pathological 30-second sessions.
149
+ *
150
+ * Defaults to {@link DEFAULT_MIN_REQUESTED_LOGIN_DURATION_SECONDS} (1 hour).
151
+ */
152
+ readonly minRequestedLoginDuration?: number;
153
+ /**
154
+ * Default login duration (seconds) used when a client does NOT pass the `dbx_session_ttl`
155
+ * auth-URL param. When undefined, falls back to {@link OidcTokenLifetimes.refreshToken}.
156
+ */
157
+ readonly defaultRequestedLoginDuration?: number;
111
158
  /**
112
159
  * JWKS service configuration (encryption secret, rotated key max age).
113
160
  */
@@ -164,6 +211,35 @@ export declare abstract class OidcModuleConfig {
164
211
  * Defaults to `false`.
165
212
  */
166
213
  readonly registrationEnabled?: boolean;
214
+ /**
215
+ * Whether the oidc-provider should trust upstream proxy headers
216
+ * (`X-Forwarded-Host`, `X-Forwarded-Proto`) when computing the request URL
217
+ * used to build resume/return URLs and discovery metadata absolute paths.
218
+ *
219
+ * Required when running behind a reverse proxy such as Firebase Hosting →
220
+ * Cloud Run / Cloud Functions, where the request `Host` header is the
221
+ * underlying Cloud Run host (e.g. `api-xxxxx-uc.a.run.app`) and not the
222
+ * canonical issuer host. Without this, the interaction `returnTo` URL is
223
+ * built off the Cloud Run host and the browser is redirected away from the
224
+ * issuer's domain after login — causing the interaction cookies (scoped to
225
+ * the canonical host) to be missing on the resume request and producing
226
+ * "authorization request has expired".
227
+ *
228
+ * Maps to `provider.proxy = <value>` on the underlying oidc-provider
229
+ * (which is the Koa `app.proxy` setting).
230
+ *
231
+ * Defaults to `'prod_only'` if the environment is `production`, otherwise `false`.
232
+ */
233
+ readonly trustProxy?: boolean;
234
+ /**
235
+ * Whether to trust proxy headers in a non-production environment, such as the local environment.
236
+ *
237
+ * The dev environment typically does not require proxy headers, and setting
238
+ * `true` will result in errors.
239
+ *
240
+ * Defaults to `false`.
241
+ */
242
+ readonly trustProxyInNonProduction?: boolean;
167
243
  /**
168
244
  * Validates that all required fields are present on the config.
169
245
  *
@@ -89,7 +89,7 @@ export interface ProvideAppOidcModuleMetadataConfig extends Pick<ModuleMetadata,
89
89
  /**
90
90
  * Optional overrides to merge into the {@link OidcModuleConfig} produced by the factory.
91
91
  */
92
- readonly config?: Partial<Pick<OidcModuleConfig, 'suppressBodyParserWarning' | 'renderError' | 'protectedPaths' | 'appOAuthInteractionPath' | 'appOAuthLoginUrlPart' | 'appOAuthConsentUrlPart' | 'tokenEndpointAuthMethods' | 'registrationEnabled'>>;
92
+ readonly config?: Partial<Pick<OidcModuleConfig, 'suppressBodyParserWarning' | 'renderError' | 'protectedPaths' | 'appOAuthInteractionPath' | 'appOAuthLoginUrlPart' | 'appOAuthConsentUrlPart' | 'tokenEndpointAuthMethods' | 'registrationEnabled' | 'trustProxy' | 'trustProxyInNonProduction' | 'tokenLifetimes' | 'maxRequestedLoginDuration' | 'minRequestedLoginDuration' | 'defaultRequestedLoginDuration'>>;
93
93
  }
94
94
  /**
95
95
  * Convenience function used to generate ModuleMetadata for an app's OidcModule.
@@ -1,6 +1,11 @@
1
1
  import type { AdapterConstructor } from 'oidc-provider';
2
2
  import { type OidcServerFirestoreCollections } from '../model';
3
3
  import { type OidcEncryptionService } from './oidc.encryption.service';
4
+ /**
5
+ * Model types that support grantId-based revocation.
6
+ */
7
+ export declare const GRANTABLE_MODEL_NAMES: readonly ["AccessToken", "AuthorizationCode", "RefreshToken", "DeviceCode", "BackchannelAuthenticationRequest"];
8
+ export type GrantableModelName = (typeof GRANTABLE_MODEL_NAMES)[number];
4
9
  /**
5
10
  * Creates an oidc-provider adapter constructor backed by Firestore via {@link OidcServerFirestoreCollections}.
6
11
  *
@@ -50,10 +50,16 @@ export declare class OidcInteractionService {
50
50
  /**
51
51
  * Finds an existing grant by ID, or creates a new one.
52
52
  *
53
+ * For new grants, optionally pre-set `expiresIn` so {@link Grant#save} writes the requested TTL
54
+ * instead of falling through to the configured Grant TTL function (which cannot read the original
55
+ * `dbx_session_ttl` request param when save is driven from a NestJS controller — see
56
+ * {@link OidcService#resolveLoginDurationForGrant}).
57
+ *
53
58
  * @param grantId - the existing grant ID to look up, or undefined to create a new grant
54
59
  * @param accountId - the account ID for creating a new grant
55
60
  * @param clientId - the client ID for creating a new grant
61
+ * @param expiresInSeconds - optional TTL (seconds) to assign to a newly-created grant
56
62
  * @returns the found or newly created grant
57
63
  */
58
- findOrCreateGrant(grantId: string | undefined, accountId: string, clientId: string): Promise<Grant>;
64
+ findOrCreateGrant(grantId: string | undefined, accountId: string, clientId: string, expiresInSeconds?: number): Promise<Grant>;
59
65
  }
@@ -1,4 +1,4 @@
1
- import type { default as Provider, Configuration } from 'oidc-provider';
1
+ import { type default as Provider, type Configuration } from 'oidc-provider';
2
2
  import { OidcModuleConfig } from '../oidc.config';
3
3
  import { JwksService } from './oidc.jwks.service';
4
4
  import { OidcAccountService } from './oidc.account.service';
@@ -27,6 +27,22 @@ export declare class OidcService {
27
27
  * @returns the lazily-initialized oidc-provider instance
28
28
  */
29
29
  getProvider(): Promise<Provider>;
30
+ /**
31
+ * Resolves the login-duration TTL (seconds) for a Grant being created from a fresh consent submission.
32
+ *
33
+ * The Grant TTL configured on the oidc-provider only fires when oidc-provider's koa middleware drives
34
+ * `grant.save()` (so `AsyncLocalStorage` carries the request context). Our consent flow saves grants
35
+ * from a NestJS controller, so we resolve the TTL up-front and pre-set `grant.expiresIn` before saving.
36
+ *
37
+ * Mirrors the resolution used by the `Grant`/`Session` TTL functions in {@link buildProviderConfiguration}.
38
+ *
39
+ * @param requestedRawTtl - The raw `dbx_session_ttl` value from `interaction.params`, if any.
40
+ * @param clientPayload - The persisted client metadata, used to read the per-client `dbx_max_session_ttl` cap.
41
+ * @returns The resolved Grant TTL in seconds.
42
+ */
43
+ resolveLoginDurationForGrant(requestedRawTtl: unknown, clientPayload: {
44
+ dbx_max_session_ttl?: number;
45
+ } | undefined): number;
30
46
  /**
31
47
  * Verifies an opaque access token and returns the {@link OidcAuthData}.
32
48
  *
@@ -37,6 +53,20 @@ export declare class OidcService {
37
53
  * @returns The auth context, or `undefined` if the token is invalid or expired.
38
54
  */
39
55
  verifyAccessToken(rawToken: string): Promise<OidcAuthData | undefined>;
56
+ /**
57
+ * Revokes a Grant entry and every grantable token entry that references it.
58
+ *
59
+ * Iterates through every grantable model (`AccessToken`, `AuthorizationCode`,
60
+ * `RefreshToken`, `DeviceCode`, `BackchannelAuthenticationRequest`) and calls
61
+ * the adapter's `revokeByGrantId` to delete all matching entries, then
62
+ * deletes the Grant adapter entry itself. After this resolves, any token
63
+ * referencing the grant is gone — `verifyAccessToken` returns `undefined`
64
+ * and a `grant_type=refresh_token` exchange fails with `invalid_grant`.
65
+ *
66
+ * @param grantId - the grant id (and Grant adapter entry id) to revoke
67
+ * @throws when the Grant entry does not exist
68
+ */
69
+ revokeGrant(grantId: string): Promise<void>;
40
70
  /**
41
71
  * Finds a client payload by ID directly from the adapter store.
42
72
  *
@@ -0,0 +1,85 @@
1
+ import type { KoaContextWithOIDC } from 'oidc-provider';
2
+ /**
3
+ * Custom OIDC auth-URL parameter clients use to request a non-default login duration.
4
+ *
5
+ * Value is integer seconds. Subject to per-client and global server caps via {@link resolveLoginDurationSeconds}.
6
+ */
7
+ export declare const DBX_FIREBASE_SERVER_OIDC_SESSION_TTL_PARAM = "dbx_session_ttl";
8
+ /**
9
+ * Custom oidc-provider client metadata field for a client's maximum requestable login duration (seconds).
10
+ */
11
+ export declare const DBX_FIREBASE_SERVER_OIDC_MAX_SESSION_TTL_CLIENT_METADATA = "dbx_max_session_ttl";
12
+ /**
13
+ * Inputs to {@link resolveLoginDurationSeconds}.
14
+ */
15
+ export interface ResolveLoginDurationInput {
16
+ /**
17
+ * Seconds requested by the client via {@link DBX_FIREBASE_SERVER_OIDC_SESSION_TTL_PARAM}, or undefined when not provided.
18
+ */
19
+ readonly requestedSeconds: number | undefined;
20
+ /**
21
+ * Per-client ceiling from the client's {@link DBX_FIREBASE_SERVER_OIDC_MAX_SESSION_TTL_CLIENT_METADATA} metadata, or undefined.
22
+ */
23
+ readonly clientMaxSeconds: number | undefined;
24
+ /**
25
+ * Global server ceiling (seconds).
26
+ */
27
+ readonly serverMaxSeconds: number;
28
+ /**
29
+ * Global server floor (seconds).
30
+ */
31
+ readonly serverMinSeconds: number;
32
+ /**
33
+ * Default duration (seconds) used when `requestedSeconds` is undefined.
34
+ */
35
+ readonly defaultSeconds: number;
36
+ }
37
+ /**
38
+ * Clamps a requested login duration into the allowed range.
39
+ *
40
+ * Resolution order:
41
+ * 1. Pick the requested value, falling back to the configured default when omitted.
42
+ * 2. Compute the effective ceiling as `min(serverMax, clientMax-or-Infinity)`.
43
+ * 3. Clamp the value to `[serverMin, ceiling]`.
44
+ *
45
+ * @param input - The clamp inputs (requested value, client cap, server bounds, default).
46
+ * @returns The clamped duration in seconds.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * resolveLoginDurationSeconds({
51
+ * requestedSeconds: 60 * 24 * 60 * 60, // 60 days
52
+ * clientMaxSeconds: 30 * 24 * 60 * 60, // 30 days client cap
53
+ * serverMaxSeconds: 90 * 24 * 60 * 60, // 90 days global cap
54
+ * serverMinSeconds: 60 * 60, // 1 hour floor
55
+ * defaultSeconds: 30 * 24 * 60 * 60
56
+ * }); // → 30 * 24 * 60 * 60 (clamped to client max)
57
+ * ```
58
+ */
59
+ export declare function resolveLoginDurationSeconds(input: ResolveLoginDurationInput): number;
60
+ /**
61
+ * Parses a raw `dbx_session_ttl` value (string or number, from URL query / form / persisted interaction params)
62
+ * into a positive integer number of seconds. Returns `undefined` when missing or invalid so the caller falls
63
+ * back to a default.
64
+ *
65
+ * @param raw - The raw value to parse.
66
+ * @returns The parsed positive integer seconds, or `undefined` when absent/invalid.
67
+ */
68
+ export declare function parseRequestedSessionTtlSeconds(raw: unknown): number | undefined;
69
+ /**
70
+ * Reads {@link DBX_FIREBASE_SERVER_OIDC_SESSION_TTL_PARAM} from a KoaContextWithOIDC and parses it to a positive integer
71
+ * number of seconds. Returns `undefined` when missing or invalid (so the caller falls back to a default).
72
+ *
73
+ * @param ctx - The OIDC Koa context, or undefined.
74
+ * @returns The parsed positive integer seconds, or `undefined` when absent/invalid.
75
+ */
76
+ export declare function readRequestedSessionTtlSeconds(ctx: KoaContextWithOIDC | undefined): number | undefined;
77
+ /**
78
+ * Inspects oidc-provider entities on the context to find the resolved Grant expiry.
79
+ *
80
+ * Returns the remaining seconds until the Grant expires, or `undefined` when no Grant is bound to the context.
81
+ *
82
+ * @param ctx - The OIDC Koa context, or undefined.
83
+ * @returns The remaining seconds until grant expiry, or `undefined` when no grant is bound or it has expired.
84
+ */
85
+ export declare function readRemainingGrantSeconds(ctx: KoaContextWithOIDC | undefined): number | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server",
3
- "version": "13.11.2",
3
+ "version": "13.11.4",
4
4
  "sideEffects": false,
5
5
  "exports": {
6
6
  "./test": {
@@ -44,15 +44,15 @@
44
44
  "main": "./index.cjs.js",
45
45
  "types": "./src/index.d.ts",
46
46
  "peerDependencies": {
47
- "@dereekb/analytics": "13.11.2",
48
- "@dereekb/date": "13.11.2",
49
- "@dereekb/dbx-core": "13.11.2",
50
- "@dereekb/firebase": "13.11.2",
51
- "@dereekb/model": "13.11.2",
52
- "@dereekb/nestjs": "13.11.2",
53
- "@dereekb/rxjs": "13.11.2",
54
- "@dereekb/util": "13.11.2",
55
- "@dereekb/zoho": "13.11.2",
47
+ "@dereekb/analytics": "13.11.4",
48
+ "@dereekb/date": "13.11.4",
49
+ "@dereekb/dbx-core": "13.11.4",
50
+ "@dereekb/firebase": "13.11.4",
51
+ "@dereekb/model": "13.11.4",
52
+ "@dereekb/nestjs": "13.11.4",
53
+ "@dereekb/rxjs": "13.11.4",
54
+ "@dereekb/util": "13.11.4",
55
+ "@dereekb/zoho": "13.11.4",
56
56
  "@google-cloud/firestore": "^7.11.6",
57
57
  "@google-cloud/storage": "^7.19.0",
58
58
  "@nestjs/common": "^11.1.19",
@@ -13,5 +13,6 @@ import { type UpdateData, type FirestoreAccessorArrayUpdate } from '@dereekb/fir
13
13
  * remove: { tags: ['old-tag'] }
14
14
  * });
15
15
  * ```
16
+ * @__NO_SIDE_EFFECTS__
16
17
  */
17
18
  export declare function firestoreServerArrayUpdateToUpdateData<T extends object>(input: FirestoreAccessorArrayUpdate<T>): UpdateData<T>;
@@ -41,6 +41,7 @@ export declare class WriteBatchFirestoreDocumentDataAccessor<T> implements Fires
41
41
  * await accessor.set({ name: 'Alice' });
42
42
  * await batch.commit();
43
43
  * ```
44
+ * @__NO_SIDE_EFFECTS__
44
45
  */
45
46
  export declare function writeBatchAccessorFactory<T>(writeBatch: GoogleCloudWriteBatch): FirestoreDocumentDataAccessorFactory<T>;
46
47
  /**
@@ -32,6 +32,7 @@ export declare class DefaultFirestoreDocumentDataAccessor<T> implements Firestor
32
32
  * const factory = defaultFirestoreAccessorFactory<User>();
33
33
  * const accessor = factory.accessorFor(userDocRef);
34
34
  * ```
35
+ * @__NO_SIDE_EFFECTS__
35
36
  */
36
37
  export declare function defaultFirestoreAccessorFactory<T>(): FirestoreDocumentDataAccessorFactory<T>;
37
38
  /**
@@ -43,6 +43,7 @@ export declare class TransactionFirestoreDocumentDataAccessor<T> implements Fire
43
43
  * await accessor.update({ name: 'Updated' });
44
44
  * });
45
45
  * ```
46
+ * @__NO_SIDE_EFFECTS__
46
47
  */
47
48
  export declare function transactionAccessorFactory<T>(transaction: GoogleCloudTransaction): FirestoreDocumentDataAccessorFactory<T>;
48
49
  /**
@@ -16,6 +16,7 @@ export declare const FIRESTORE_CLIENT_QUERY_CONSTRAINT_HANDLER_MAPPING: FullFire
16
16
  * Translates abstract query constraints into Google Cloud Firestore query builder calls.
17
17
  *
18
18
  * @returns A {@link FirestoreQueryConstraintFunctionsDriver} for the server SDK.
19
+ * @__NO_SIDE_EFFECTS__
19
20
  */
20
21
  export declare function firestoreClientQueryConstraintFunctionsDriver(): FirestoreQueryConstraintFunctionsDriver;
21
22
  /**
@@ -15,5 +15,6 @@ import { type UpdateData, type FirestoreAccessorIncrementUpdate } from '@dereekb
15
15
  * likeCount: -1
16
16
  * });
17
17
  * ```
18
+ * @__NO_SIDE_EFFECTS__
18
19
  */
19
20
  export declare function firestoreServerIncrementUpdateToUpdateData<T extends object>(input: FirestoreAccessorIncrementUpdate<T>): UpdateData<T>;
@@ -44,6 +44,7 @@ export interface OptionalFirestoreEncryptedFieldConfig<T> {
44
44
  * @template T - The JSON-serializable value type.
45
45
  * @param config - Encryption field configuration.
46
46
  * @returns A field mapping configuration for encrypted values.
47
+ * @__NO_SIDE_EFFECTS__
47
48
  */
48
49
  export declare function firestoreEncryptedField<T>(config: FirestoreEncryptedFieldConfig<T>): FirestoreModelFieldMapFunctionsConfig<T, string>;
49
50
  /**
@@ -62,5 +63,6 @@ export declare function firestoreEncryptedField<T>(config: FirestoreEncryptedFie
62
63
  * @template T - The JSON-serializable value type.
63
64
  * @param config - Encryption field configuration.
64
65
  * @returns A field mapping configuration for optional encrypted values.
66
+ * @__NO_SIDE_EFFECTS__
65
67
  */
66
68
  export declare function optionalFirestoreEncryptedField<T>(config: OptionalFirestoreEncryptedFieldConfig<T>): FirestoreModelFieldMapFunctionsConfig<Maybe<T>, Maybe<string>>;
@@ -121,5 +121,6 @@ export interface NestServerRootModuleResult {
121
121
  *
122
122
  * @param config - Shared configuration
123
123
  * @returns The root module and resolved prefix config
124
+ * @__NO_SIDE_EFFECTS__
124
125
  */
125
126
  export declare function buildNestServerRootModule(config: NestServerRootModuleConfig): NestServerRootModuleResult;
@@ -38,6 +38,7 @@ export type ProvideFirebaseServerAuthService<T extends FirebaseServerAuthService
38
38
  * useFactory: (auth) => new MyAuthService(auth)
39
39
  * });
40
40
  * ```
41
+ * @__NO_SIDE_EFFECTS__
41
42
  */
42
43
  export declare function provideFirebaseServerAuthService<T extends FirebaseServerAuthService>(provider: ProvideFirebaseServerAuthService<T>): [ProvideFirebaseServerAuthService<T>, Provider<T>];
43
44
  export interface FirebaseServerAuthModuleMetadataConfig<T extends FirebaseServerAuthService> extends AdditionalModuleMetadata {
@@ -78,5 +78,6 @@ export interface FirebaseServerDevFunctions {
78
78
  *
79
79
  * export const { dev } = devFunctions;
80
80
  * ```
81
+ * @__NO_SIDE_EFFECTS__
81
82
  */
82
83
  export declare function firebaseServerDevFunctions<N extends AbstractFirebaseNestContext<any, any>, S extends NestApplicationScheduleConfiguredFunctionMap>(config: FirebaseServerDevFunctionsConfig<N, S>): FirebaseServerDevFunctions;
@@ -53,6 +53,7 @@ export interface OnCallDevelopmentConfig<N> {
53
53
  * resetData: resetDataFunction
54
54
  * });
55
55
  * ```
56
+ * @__NO_SIDE_EFFECTS__
56
57
  */
57
58
  export declare function onCallDevelopmentFunction<N>(map: OnCallDevelopmentFunctionMap<N>, config?: OnCallDevelopmentConfig<N>): OnCallWithNestContext<N, OnCallDevelopmentParams>;
58
59
  /**
@@ -34,5 +34,6 @@ export interface MakeScheduledFunctionDevelopmentFunctionConfig {
34
34
  * [SCHEDULED_FUNCTION_DEV_FUNCTION_SPECIFIER]: scheduleDev
35
35
  * };
36
36
  * ```
37
+ * @__NO_SIDE_EFFECTS__
37
38
  */
38
39
  export declare function makeScheduledFunctionDevelopmentFunction(config: MakeScheduledFunctionDevelopmentFunctionConfig): OnCallDevelopmentFunction<unknown, ScheduledFunctionDevelopmentFirebaseFunctionParams, ScheduledFunctionDevelopmentFirebaseFunctionResult>;
@@ -7,6 +7,7 @@ export declare const NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FU
7
7
  * without specifying which scheduled function to execute.
8
8
  *
9
9
  * @returns A bad-request error indicating the missing run name.
10
+ * @__NO_SIDE_EFFECTS__
10
11
  */
11
12
  export declare function noRunNameSpecifiedForScheduledFunctionDevelopmentFunction(): import("firebase-functions/https").HttpsError;
12
13
  /**
@@ -98,6 +98,7 @@ export interface OnCallWithAuthAwareNestRequireAuthRef {
98
98
  *
99
99
  * @param fn
100
100
  * @param request
101
+ * @__NO_SIDE_EFFECTS__
101
102
  */
102
103
  export declare function assertRequestRequiresAuthForFunction(fn: OnCallWithAuthAwareNestRequireAuthRef, request: OnCallWithNestContextRequest<any, any>): void;
103
104
  /**
@@ -124,5 +124,6 @@ export interface FirebaseServerActionsTransformFactoryOptions {
124
124
  *
125
125
  * @param options - Optional configuration for error logging behavior.
126
126
  * @returns A factory that creates type-safe transform functions from ArkType schemas.
127
+ * @__NO_SIDE_EFFECTS__
127
128
  */
128
129
  export declare function firebaseServerActionsTransformFactory(options?: FirebaseServerActionsTransformFactoryOptions): TransformAndValidateObjectFactory;
@@ -74,6 +74,7 @@ export interface BlockingFunctionBuilder<E extends object, O> {
74
74
  * @param handler - The handler logic to execute on each event.
75
75
  * @param opts - Optional {@link BlockingOptions} passed to the builder.
76
76
  * @returns A {@link BlockingFunctionWithHandler} with the handler accessible via `__handler`.
77
+ * @__NO_SIDE_EFFECTS__
77
78
  */
78
79
  export declare function makeBlockingFunctionWithHandler<E extends object, O>(blockingFunctionBuilder: BlockingFunctionBuilder<E, O>, handler: BlockingFunctionHandler<E, O>, opts?: Maybe<BlockingOptions>): BlockingFunctionWithHandler<E, O>;
79
80
  /**
@@ -128,5 +129,6 @@ export type BlockingFunctionHandlerWithNestContextFactory<N> = <E extends object
128
129
  *
129
130
  * @param makeNestContext - Factory that creates the typed context from the NestJS application context.
130
131
  * @returns A factory for creating nest-context-aware blocking function handlers.
132
+ * @__NO_SIDE_EFFECTS__
131
133
  */
132
134
  export declare function blockingFunctionHandlerWithNestContextFactory<N>(makeNestContext: MakeNestContext<N>): BlockingFunctionHandlerWithNestContextFactory<N>;
@@ -31,6 +31,7 @@ export type OnCallHandlerWithNestApplicationFactory = <I = unknown, O = unknown>
31
31
  *
32
32
  * @param defaultOpts - Default {@link https.CallableOptions} applied to all functions created by this factory.
33
33
  * @returns A factory that creates nest-application-aware callable functions.
34
+ * @__NO_SIDE_EFFECTS__
34
35
  */
35
36
  export declare function onCallHandlerWithNestApplicationFactory(defaultOpts?: https.CallableOptions): OnCallHandlerWithNestApplicationFactory;
36
37
  /**
@@ -57,5 +58,6 @@ export type OnCallHandlerWithNestContextFactory<C> = <I = unknown, O = unknown>(
57
58
  * @param appFactory - The base application-level callable factory.
58
59
  * @param makeNestContext - Factory that creates the typed context from the application context.
59
60
  * @returns A factory that creates typed-context-aware callable functions.
61
+ * @__NO_SIDE_EFFECTS__
60
62
  */
61
63
  export declare function onCallHandlerWithNestContextFactory<C>(appFactory: OnCallHandlerWithNestApplicationFactory, makeNestContext: MakeNestContext<C>): OnCallHandlerWithNestContextFactory<C>;
@@ -89,5 +89,6 @@ export type CloudEventHandlerWithNestContextFactory<N> = <E extends CloudEvent<a
89
89
  *
90
90
  * @param makeNestContext - Factory that creates the typed context from the NestJS application context.
91
91
  * @returns A factory for creating nest-context-aware event function handlers.
92
+ * @__NO_SIDE_EFFECTS__
92
93
  */
93
94
  export declare function cloudEventHandlerWithNestContextFactory<N>(makeNestContext: MakeNestContext<N>): CloudEventHandlerWithNestContextFactory<N>;