@enterprisestandard/react 0.0.5-beta.20260115.4 → 0.0.6

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/dist/index.d.ts CHANGED
@@ -1,2589 +1,43 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { PropsWithChildren, ReactNode } from 'react';
3
-
4
- /** The Standard Schema interface. @see https://standardschema.dev/ */
5
- interface StandardSchemaV1<Input = unknown, Output = Input> {
6
- /** The Standard Schema properties. */
7
- readonly '~standard': StandardSchemaV1.Props<Input, Output>;
8
- }
9
- declare namespace StandardSchemaV1 {
10
- /** The Standard Schema properties interface. */
11
- interface Props<Input = unknown, Output = Input> {
12
- /** The version number of the standard. */
13
- readonly version: 1;
14
- /** The vendor name of the schema library. */
15
- readonly vendor: string;
16
- /** Validates unknown input values. */
17
- readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
18
- /** Inferred types associated with the schema. */
19
- readonly types?: Types<Input, Output> | undefined;
20
- }
21
- /** The result interface of the validate function. */
22
- type Result<Output> = SuccessResult<Output> | FailureResult;
23
- /** The result interface if validation succeeds. */
24
- interface SuccessResult<Output> {
25
- /** The typed output value. */
26
- readonly value: Output;
27
- /** The non-existent issues. */
28
- readonly issues?: undefined;
29
- }
30
- /** The result interface if validation fails. */
31
- interface FailureResult {
32
- /** The issues of failed validation. */
33
- readonly issues: ReadonlyArray<Issue>;
34
- }
35
- /** The issue interface of the failure output. */
36
- interface Issue {
37
- /** The error message of the issue. */
38
- readonly message: string;
39
- /** The path of the issue, if any. */
40
- readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
41
- }
42
- /** The path segment interface of the issue. */
43
- interface PathSegment {
44
- /** The key representing a path segment. */
45
- readonly key: PropertyKey;
46
- }
47
- /** The Standard Schema types interface. */
48
- interface Types<Input = unknown, Output = Input> {
49
- /** The input type of the schema. */
50
- readonly input: Input;
51
- /** The output type of the schema. */
52
- readonly output: Output;
53
- }
54
- /** Infers the input type of a Standard Schema. */
55
- type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
56
- /** Infers the output type of a Standard Schema. */
57
- type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
58
- }
59
-
60
- /**
61
- * SCIM 2.0 User Resource
62
- * @see https://datatracker.ietf.org/doc/html/rfc7643#section-4.1
63
- */
64
- /**
65
- * SCIM Name sub-attribute
66
- */
67
- interface Name {
68
- /**
69
- * The full name, including all middle names, titles, and suffixes as appropriate
70
- */
71
- formatted?: string;
72
- /**
73
- * The family name of the User, or last name
74
- */
75
- familyName?: string;
76
- /**
77
- * The given name of the User, or first name
78
- */
79
- givenName?: string;
80
- /**
81
- * The middle name(s) of the User
82
- */
83
- middleName?: string;
84
- /**
85
- * The honorific prefix(es) of the User, or title
86
- */
87
- honorificPrefix?: string;
88
- /**
89
- * The honorific suffix(es) of the User, or suffix
90
- */
91
- honorificSuffix?: string;
92
- }
93
- /**
94
- * SCIM Email sub-attribute
95
- */
96
- interface Email {
97
- /**
98
- * The email address value
99
- */
100
- value: string;
101
- /**
102
- * A human-readable name, primarily used for display purposes
103
- */
104
- display?: string;
105
- /**
106
- * A label indicating the attribute's function (e.g., "work" or "home")
107
- */
108
- type?: string;
109
- /**
110
- * A Boolean value indicating the 'primary' or preferred attribute value
111
- */
112
- primary?: boolean;
113
- }
114
- /**
115
- * SCIM Phone Number sub-attribute
116
- */
117
- interface PhoneNumber {
118
- /**
119
- * The phone number value
120
- */
121
- value: string;
122
- /**
123
- * A human-readable name, primarily used for display purposes
124
- */
125
- display?: string;
126
- /**
127
- * A label indicating the attribute's function (e.g., "work", "home", "mobile")
128
- */
129
- type?: string;
130
- /**
131
- * A Boolean value indicating the 'primary' or preferred attribute value
132
- */
133
- primary?: boolean;
134
- }
135
- /**
136
- * SCIM Address sub-attribute
137
- */
138
- interface Address {
139
- /**
140
- * The full mailing address, formatted for display
141
- */
142
- formatted?: string;
143
- /**
144
- * The full street address component
145
- */
146
- streetAddress?: string;
147
- /**
148
- * The city or locality component
149
- */
150
- locality?: string;
151
- /**
152
- * The state or region component
153
- */
154
- region?: string;
155
- /**
156
- * The zip code or postal code component
157
- */
158
- postalCode?: string;
159
- /**
160
- * The country name component
161
- */
162
- country?: string;
163
- /**
164
- * A label indicating the attribute's function (e.g., "work" or "home")
165
- */
166
- type?: string;
167
- /**
168
- * A Boolean value indicating the 'primary' or preferred attribute value
169
- */
170
- primary?: boolean;
171
- }
172
- /**
173
- * SCIM Group reference (used within User resources)
174
- */
175
- interface Group {
176
- /**
177
- * The identifier of the User's group
178
- */
179
- value: string;
180
- /**
181
- * The URI of the corresponding 'Group' resource
182
- */
183
- $ref?: string;
184
- /**
185
- * A human-readable name, primarily used for display purposes
186
- */
187
- display?: string;
188
- /**
189
- * A label indicating the attribute's function (e.g., "direct" or "indirect")
190
- */
191
- type?: string;
192
- }
193
- /**
194
- * SCIM Group Member reference
195
- */
196
- interface GroupMember {
197
- /**
198
- * The identifier of the member (User or Group)
199
- */
200
- value: string;
201
- /**
202
- * The URI of the corresponding member resource
203
- */
204
- $ref?: string;
205
- /**
206
- * A human-readable name of the member
207
- */
208
- display?: string;
209
- /**
210
- * The type of the member (e.g., "User" or "Group")
211
- */
212
- type?: 'User' | 'Group';
213
- }
214
- /**
215
- * SCIM 2.0 Group Resource
216
- * @see https://datatracker.ietf.org/doc/html/rfc7643#section-4.2
217
- */
218
- interface GroupResource {
219
- /**
220
- * REQUIRED. The schemas attribute
221
- */
222
- schemas?: string[];
223
- /**
224
- * Unique identifier for the Group, assigned by the service provider
225
- */
226
- id?: string;
227
- /**
228
- * External identifier from the provisioning client
229
- */
230
- externalId?: string;
231
- /**
232
- * Resource metadata
233
- */
234
- meta?: {
235
- resourceType?: string;
236
- created?: string;
237
- lastModified?: string;
238
- location?: string;
239
- version?: string;
240
- };
241
- /**
242
- * REQUIRED. A human-readable name for the Group
243
- */
244
- displayName: string;
245
- /**
246
- * A list of members of the Group
247
- */
248
- members?: GroupMember[];
249
- }
250
- /**
251
- * SCIM Role
252
- */
253
- interface Role {
254
- /**
255
- * The value of the role
256
- */
257
- value: string;
258
- /**
259
- * A human-readable name, primarily used for display purposes
260
- */
261
- display?: string;
262
- /**
263
- * A label indicating the attribute's function
264
- */
265
- type?: string;
266
- /**
267
- * A Boolean value indicating the 'primary' or preferred attribute value
268
- */
269
- primary?: boolean;
270
- }
271
- /**
272
- * SCIM X509 Certificate
273
- */
274
- interface X509Certificate {
275
- /**
276
- * The value of the X.509 certificate
277
- */
278
- value: string;
279
- /**
280
- * A human-readable name, primarily used for display purposes
281
- */
282
- display?: string;
283
- /**
284
- * A label indicating the attribute's function
285
- */
286
- type?: string;
287
- /**
288
- * A Boolean value indicating the 'primary' or preferred attribute value
289
- */
290
- primary?: boolean;
291
- }
292
- /**
293
- * SCIM Enterprise User Extension
294
- * @see https://datatracker.ietf.org/doc/html/rfc7643#section-4.3
295
- */
296
- interface EnterpriseExtension {
297
- /**
298
- * Numeric or alphanumeric identifier assigned to a person
299
- */
300
- employeeNumber?: string;
301
- /**
302
- * Identifies the name of a cost center
303
- */
304
- costCenter?: string;
305
- /**
306
- * Identifies the name of an organization
307
- */
308
- organization?: string;
309
- /**
310
- * Identifies the name of a division
311
- */
312
- division?: string;
313
- /**
314
- * Identifies the name of a department
315
- */
316
- department?: string;
317
- /**
318
- * The user's manager
319
- */
320
- manager?: {
321
- /**
322
- * The "id" of the SCIM resource representing the User's manager
323
- */
324
- value?: string;
325
- /**
326
- * The URI of the SCIM resource representing the User's manager
327
- */
328
- $ref?: string;
329
- /**
330
- * The displayName of the User's manager
331
- */
332
- displayName?: string;
333
- };
334
- }
335
- /**
336
- * SCIM User Resource
337
- */
338
- interface User$1 {
339
- /**
340
- * REQUIRED. Unique identifier for the User, typically from the provider
341
- */
342
- id?: string;
343
- /**
344
- * REQUIRED. A unique identifier for a SCIM resource as defined by the service provider
345
- */
346
- externalId?: string;
347
- /**
348
- * Resource metadata
349
- */
350
- meta?: {
351
- resourceType?: string;
352
- created?: string;
353
- lastModified?: string;
354
- location?: string;
355
- version?: string;
356
- };
357
- /**
358
- * REQUIRED. Unique identifier for the User, typically used for login
359
- */
360
- userName: string;
361
- /**
362
- * The components of the user's name
363
- */
364
- name?: Name;
365
- /**
366
- * The name of the User, suitable for display to end-users
367
- */
368
- displayName?: string;
369
- /**
370
- * The casual way to address the user
371
- */
372
- nickName?: string;
373
- /**
374
- * A fully qualified URL pointing to a page representing the User's online profile
375
- */
376
- profileUrl?: string;
377
- /**
378
- * The user's title, such as "Vice President"
379
- */
380
- title?: string;
381
- /**
382
- * Used to identify the relationship between the organization and the user
383
- */
384
- userType?: string;
385
- /**
386
- * Indicates the User's preferred written or spoken language
387
- */
388
- preferredLanguage?: string;
389
- /**
390
- * Used to indicate the User's default location for purposes of localizing items such as currency
391
- */
392
- locale?: string;
393
- /**
394
- * The User's time zone in the "Olson" time zone database format
395
- */
396
- timezone?: string;
397
- /**
398
- * A Boolean value indicating the User's administrative status
399
- */
400
- active?: boolean;
401
- /**
402
- * The User's cleartext password
403
- */
404
- password?: string;
405
- /**
406
- * Email addresses for the user
407
- */
408
- emails?: Email[];
409
- /**
410
- * Phone numbers for the User
411
- */
412
- phoneNumbers?: PhoneNumber[];
413
- /**
414
- * Instant messaging addresses for the User
415
- */
416
- ims?: Array<{
417
- value: string;
418
- display?: string;
419
- type?: string;
420
- primary?: boolean;
421
- }>;
422
- /**
423
- * URLs of photos of the User
424
- */
425
- photos?: Array<{
426
- value: string;
427
- display?: string;
428
- type?: string;
429
- primary?: boolean;
430
- }>;
431
- /**
432
- * Physical mailing addresses for this User
433
- */
434
- addresses?: Address[];
435
- /**
436
- * A list of groups to which the user belongs
437
- */
438
- groups?: Group[];
439
- /**
440
- * A list of entitlements for the User
441
- */
442
- entitlements?: Array<{
443
- value: string;
444
- display?: string;
445
- type?: string;
446
- primary?: boolean;
447
- }>;
448
- /**
449
- * A list of roles for the User
450
- */
451
- roles?: Role[];
452
- /**
453
- * A list of certificates issued to the User
454
- */
455
- x509Certificates?: X509Certificate[];
456
- /**
457
- * Enterprise User Extension
458
- */
459
- 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'?: EnterpriseExtension;
460
- /**
461
- * REQUIRED. The schemas attribute is an array of Strings which allows introspection of the supported schema version
462
- */
463
- schemas?: string[];
464
- }
465
- /**
466
- * Creates a StandardSchemaV1 for validating SCIM User resources.
467
- * @param vendor - The name of the vendor creating this schema
468
- * @returns A StandardSchemaV1 instance for SCIM User resources
469
- */
470
- declare function userSchema(vendor: string): StandardSchemaV1<Record<string, unknown>, User$1>;
471
- /**
472
- * Creates a StandardSchemaV1 for validating SCIM Group resources.
473
- * @param vendor - The name of the vendor creating this schema
474
- * @returns A StandardSchemaV1 instance for SCIM Group resources
475
- */
476
- declare function groupResourceSchema(vendor: string): StandardSchemaV1<Record<string, unknown>, GroupResource>;
477
-
478
- /**
479
- * Group storage for persisting group data.
480
- *
481
- * Group stores are an optional extension for the IAM Groups functionality.
482
- * They enable:
483
- * - Caching group data locally for fast lookups
484
- * - Receiving group provisioning from external IAM providers (SCIM server)
485
- * - Storing groups close to your application (in-memory, Redis, database)
486
- *
487
- * ## Example Usage
488
- *
489
- * ```typescript
490
- * import { InMemoryGroupStore } from '@enterprisestandard/react';
491
- *
492
- * const groupStore = new InMemoryGroupStore();
493
- *
494
- * // Store a group
495
- * await groupStore.upsert({
496
- * id: 'group-123',
497
- * displayName: 'Administrators',
498
- * createdAt: new Date(),
499
- * updatedAt: new Date(),
500
- * });
501
- *
502
- * // Look up groups
503
- * const group = await groupStore.get('group-123');
504
- * const allGroups = await groupStore.list();
505
- * ```
506
- */
507
-
508
- /**
509
- * Stored group data with required id and tracking metadata.
510
- *
511
- * @template TExtended - Type-safe custom data that consumers can add to groups
512
- */
513
- type StoredGroup<TExtended = {}> = {
514
- /**
515
- * Required unique identifier for the group.
516
- * This is the primary key for group storage.
517
- */
518
- id: string;
519
- /**
520
- * Required human-readable name for the group.
521
- */
522
- displayName: string;
523
- /**
524
- * Optional external identifier from provisioning client.
525
- */
526
- externalId?: string;
527
- /**
528
- * List of members in the group.
529
- */
530
- members?: GroupMember[];
531
- /**
532
- * Timestamp when the group was first stored.
533
- */
534
- createdAt: Date;
535
- /**
536
- * Timestamp when the group was last updated.
537
- */
538
- updatedAt: Date;
539
- } & TExtended;
540
- /**
541
- * Abstract interface for group storage backends.
542
- *
543
- * Consumers can implement this interface to use different storage backends:
544
- * - In-memory (for development/testing)
545
- * - Redis (for production with fast lookups)
546
- * - Database (PostgreSQL, MySQL, etc.)
547
- *
548
- * @template TExtended - Type-safe custom data that consumers can add to groups
549
- */
550
- interface GroupStore<TExtended = {}> {
551
- /**
552
- * Retrieve a group by its unique identifier.
553
- *
554
- * @param id - The group's unique identifier
555
- * @returns The group if found, null otherwise
556
- */
557
- get(id: string): Promise<StoredGroup<TExtended> | null>;
558
- /**
559
- * Retrieve a group by its external identifier.
560
- *
561
- * @param externalId - The external identifier from the provisioning client
562
- * @returns The group if found, null otherwise
563
- */
564
- getByExternalId(externalId: string): Promise<StoredGroup<TExtended> | null>;
565
- /**
566
- * Retrieve a group by its display name.
567
- *
568
- * @param displayName - The group's display name
569
- * @returns The group if found, null otherwise
570
- */
571
- getByDisplayName(displayName: string): Promise<StoredGroup<TExtended> | null>;
572
- /**
573
- * List all groups in the store.
574
- *
575
- * @returns Array of all stored groups
576
- */
577
- list(): Promise<StoredGroup<TExtended>[]>;
578
- /**
579
- * Create or update a group in the store.
580
- *
581
- * If a group with the same `id` exists, it will be updated.
582
- * Otherwise, a new group will be created.
583
- *
584
- * @param group - The group data to store
585
- */
586
- upsert(group: StoredGroup<TExtended>): Promise<void>;
587
- /**
588
- * Delete a group by its unique identifier.
589
- *
590
- * @param id - The group's unique identifier to delete
591
- */
592
- delete(id: string): Promise<void>;
593
- /**
594
- * Add a member to a group.
595
- *
596
- * @param groupId - The group's unique identifier
597
- * @param member - The member to add
598
- */
599
- addMember(groupId: string, member: GroupMember): Promise<void>;
600
- /**
601
- * Remove a member from a group.
602
- *
603
- * @param groupId - The group's unique identifier
604
- * @param memberId - The member's value/id to remove
605
- */
606
- removeMember(groupId: string, memberId: string): Promise<void>;
607
- }
608
- /**
609
- * In-memory group store implementation using Maps.
610
- *
611
- * Suitable for:
612
- * - Development and testing
613
- * - Single-server deployments
614
- * - Applications without high availability requirements
615
- *
616
- * NOT suitable for:
617
- * - Multi-server deployments (groups not shared)
618
- * - High availability scenarios (groups lost on restart)
619
- * - Production applications with distributed architecture
620
- *
621
- * For production, implement GroupStore with Redis or a database.
622
- *
623
- * @template TExtended - Type-safe custom data that consumers can add to groups
624
- */
625
- declare class InMemoryGroupStore<TExtended = {}> implements GroupStore<TExtended> {
626
- /** Primary storage: id -> group */
627
- private groups;
628
- /** Secondary index: externalId -> id */
629
- private externalIdIndex;
630
- /** Secondary index: displayName (lowercase) -> id */
631
- private displayNameIndex;
632
- get(id: string): Promise<StoredGroup<TExtended> | null>;
633
- getByExternalId(externalId: string): Promise<StoredGroup<TExtended> | null>;
634
- getByDisplayName(displayName: string): Promise<StoredGroup<TExtended> | null>;
635
- list(): Promise<StoredGroup<TExtended>[]>;
636
- upsert(group: StoredGroup<TExtended>): Promise<void>;
637
- delete(id: string): Promise<void>;
638
- addMember(groupId: string, member: GroupMember): Promise<void>;
639
- removeMember(groupId: string, memberId: string): Promise<void>;
640
- }
641
-
642
- /**
643
- * Base user with simple, developer-friendly attributes.
644
- * Extended by User (SSO) and EnterpriseUser (SCIM).
645
- */
646
- interface BaseUser {
647
- /**
648
- * Unique identifier for the user
649
- */
650
- id?: string;
651
- /**
652
- * REQUIRED. Unique identifier for login
653
- */
654
- userName: string;
655
- /**
656
- * REQUIRED. Simple display name
657
- */
658
- name: string;
659
- /**
660
- * REQUIRED. Primary email address
661
- */
662
- email: string;
663
- /**
664
- * URL to user's avatar/profile picture
665
- */
666
- avatarUrl?: string;
667
- }
668
-
669
- /**
670
- * OIDC Code Flow Callback URL Parameters
671
- * @see https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth
672
- */
673
- interface OidcCallbackParams {
674
- /**
675
- * REQUIRED. The authorization code returned from the authorization server.
676
- */
677
- code: string;
678
- /**
679
- * REQUIRED if the "state" parameter was present in the client authorization request.
680
- * The exact value received from the client.
681
- */
682
- state?: string;
683
- /**
684
- * RECOMMENDED. The session state value. Clients should use this to verify the session state.
685
- */
686
- session_state?: string;
687
- /**
688
- * OAuth 2.0 error code if the authorization request failed.
689
- */
690
- error?: string;
691
- /**
692
- * Human-readable ASCII text providing additional information for the error.
693
- */
694
- error_description?: string;
695
- /**
696
- * A URI identifying a human-readable web page with information about the error.
697
- */
698
- error_uri?: string;
699
- /**
700
- * The "iss" (issuer) parameter identifies the principal that issued the response.
701
- * This is typically used in the implicit flow.
702
- */
703
- iss?: string;
704
- }
705
- /**
706
- * Creates a StandardSchemaV1 for validating OIDC callback URL parameters.
707
- * @param vendor - The name of the vendor creating this schema
708
- * @returns A StandardSchemaV1 instance for OIDC callback parameters
709
- */
710
- declare function oidcCallbackSchema(vendor: string): StandardSchemaV1<Record<string, unknown>, OidcCallbackParams>;
711
- /**
712
- * Token Response from IdP
713
- */
714
- interface TokenResponse {
715
- access_token: string;
716
- id_token: string;
717
- refresh_token?: string;
718
- token_type: string;
719
- expires_in?: number;
720
- scope?: string;
721
- refresh_expires_in?: number;
722
- session_state?: string;
723
- expires?: string;
724
- }
725
- /**
726
- * Creates a StandardSchemaV1 for validating OIDC Token Responses.
727
- * @param vendor - The name of the vendor creating this schema
728
- * @returns A StandardSchemaV1 instance for Token Response validation
729
- */
730
- declare function tokenResponseSchema(vendor: string): StandardSchemaV1<Record<string, unknown>, TokenResponse>;
731
- /**
732
- * ID Token Claims
733
- */
734
- interface IdTokenClaims {
735
- iss?: string;
736
- aud?: string;
737
- exp?: number;
738
- iat?: number;
739
- sub?: string;
740
- sid?: string;
741
- name?: string;
742
- email?: string;
743
- preferred_username?: string;
744
- picture?: string;
745
- [key: string]: unknown;
746
- }
747
- /**
748
- * Creates a StandardSchemaV1 for validating ID Token Claims.
749
- * @param vendor - The name of the vendor creating this schema
750
- * @returns A StandardSchemaV1 instance for ID Token Claims validation
751
- */
752
- declare function idTokenClaimsSchema(vendor: string): StandardSchemaV1<Record<string, unknown>, IdTokenClaims>;
753
-
754
- /**
755
- * Primary user type for SSO/OIDC applications.
756
- * Extends BaseUser with SSO-specific data.
757
- */
758
- interface User extends BaseUser {
759
- /**
760
- * SSO/OIDC authentication data
761
- */
762
- sso: {
763
- /**
764
- * ID Token claims from the identity provider
765
- */
766
- profile: IdTokenClaims;
767
- /**
768
- * Tenant/organization information
769
- */
770
- tenant: {
771
- id: string;
772
- name: string;
773
- };
774
- /**
775
- * OAuth scopes granted
776
- */
777
- scope?: string;
778
- /**
779
- * Token type (typically "Bearer")
780
- */
781
- tokenType: string;
782
- /**
783
- * Session state from the identity provider
784
- */
785
- sessionState?: string;
786
- /**
787
- * Token expiration time
788
- */
789
- expires: Date;
790
- };
791
- }
792
-
793
- /**
794
- * User storage for persisting user profiles from SSO authentication.
795
- *
796
- * User stores are optional - the package works with JWT cookies alone.
797
- * User stores are useful when you want to:
798
- * - Cache user profiles for fast lookup
799
- * - Store users close to your application (in-memory, Redis, etc.)
800
- * - Avoid custom IAM/SCIM integration for simple use cases
801
- *
802
- * ## When to Use UserStore vs IAM
803
- *
804
- * **Use UserStore when:**
805
- * - You just need fast user lookups without external systems
806
- * - Users are managed by an external IdP and you just cache them locally
807
- * - You want simple in-memory or Redis storage
808
- *
809
- * **Use IAM (SCIM) when:**
810
- * - You need to provision users to an external identity provider
811
- * - You need custom user attributes beyond what SSO provides
812
- * - You need to sync users with enterprise directories
813
- *
814
- * ## Example Usage
815
- *
816
- * ```typescript
817
- * import { sso, InMemoryUserStore } from '@enterprisestandard/react/server';
818
- *
819
- * const userStore = new InMemoryUserStore();
820
- *
821
- * const auth = sso({
822
- * // ... other config
823
- * user_store: userStore,
824
- * });
825
- *
826
- * // Later, look up users
827
- * const user = await userStore.get('user-sub-id');
828
- * const userByEmail = await userStore.getByEmail('user@example.com');
829
- * ```
830
- */
831
-
832
- /**
833
- * Stored user data with required id and tracking metadata.
834
- *
835
- * Extends the SSO User type with:
836
- * - Required `id` (the `sub` claim from the IdP)
837
- * - Timestamps for tracking when users were first seen and last updated
838
- * - Optional custom extended data
839
- *
840
- * @template TExtended - Type-safe custom data that consumers can add to users
841
- */
842
- type StoredUser<TExtended = {}> = User & {
843
- /**
844
- * Required unique identifier (the `sub` claim from the IdP).
845
- * This is the primary key for user storage.
846
- */
847
- id: string;
848
- /**
849
- * Timestamp when the user was first stored.
850
- */
851
- createdAt: Date;
852
- /**
853
- * Timestamp when the user was last updated (e.g., on re-login).
854
- */
855
- updatedAt: Date;
856
- } & TExtended;
857
- /**
858
- * Abstract interface for user storage backends.
859
- *
860
- * Consumers can implement this interface to use different storage backends:
861
- * - In-memory (for development/testing)
862
- * - Redis (for production with fast lookups)
863
- * - Database (PostgreSQL, MySQL, etc.)
864
- *
865
- * @template TExtended - Type-safe custom data that consumers can add to users
866
- *
867
- * @example
868
- * ```typescript
869
- * // Custom user data
870
- * type MyUserData = {
871
- * department: string;
872
- * roles: string[];
873
- * };
874
- *
875
- * // Implement custom store
876
- * class RedisUserStore implements UserStore<MyUserData> {
877
- * async get(sub: string): Promise<StoredUser<MyUserData> | null> {
878
- * const data = await redis.get(`user:${sub}`);
879
- * return data ? JSON.parse(data) : null;
880
- * }
881
- * // ... other methods
882
- * }
883
- * ```
884
- */
885
- interface UserStore<TExtended = {}> {
886
- /**
887
- * Retrieve a user by their subject identifier (sub).
888
- *
889
- * @param sub - The user's unique identifier from the IdP
890
- * @returns The user if found, null otherwise
891
- */
892
- get(sub: string): Promise<StoredUser<TExtended> | null>;
893
- /**
894
- * Retrieve a user by their email address.
895
- *
896
- * @param email - The user's email address
897
- * @returns The user if found, null otherwise
898
- */
899
- getByEmail(email: string): Promise<StoredUser<TExtended> | null>;
900
- /**
901
- * Retrieve a user by their username.
902
- *
903
- * @param userName - The user's username
904
- * @returns The user if found, null otherwise
905
- */
906
- getByUserName(userName: string): Promise<StoredUser<TExtended> | null>;
907
- /**
908
- * Create or update a user in the store.
909
- *
910
- * If a user with the same `id` (sub) exists, it will be updated.
911
- * Otherwise, a new user will be created.
912
- *
913
- * @param user - The user data to store
914
- */
915
- upsert(user: StoredUser<TExtended>): Promise<void>;
916
- /**
917
- * Delete a user by their subject identifier (sub).
918
- *
919
- * @param sub - The user's unique identifier to delete
920
- */
921
- delete(sub: string): Promise<void>;
922
- }
923
- /**
924
- * In-memory user store implementation using Maps.
925
- *
926
- * Suitable for:
927
- * - Development and testing
928
- * - Single-server deployments
929
- * - Applications without high availability requirements
930
- *
931
- * NOT suitable for:
932
- * - Multi-server deployments (users not shared)
933
- * - High availability scenarios (users lost on restart)
934
- * - Production applications with distributed architecture
935
- *
936
- * For production, implement UserStore with Redis or a database.
937
- *
938
- * @template TExtended - Type-safe custom data that consumers can add to users
939
- */
940
- declare class InMemoryUserStore<TExtended = {}> implements UserStore<TExtended> {
941
- /** Primary storage: sub -> user */
942
- private users;
943
- /** Secondary index: email -> sub */
944
- private emailIndex;
945
- /** Secondary index: userName -> sub */
946
- private userNameIndex;
947
- get(sub: string): Promise<StoredUser<TExtended> | null>;
948
- getByEmail(email: string): Promise<StoredUser<TExtended> | null>;
949
- getByUserName(userName: string): Promise<StoredUser<TExtended> | null>;
950
- upsert(user: StoredUser<TExtended>): Promise<void>;
951
- delete(sub: string): Promise<void>;
952
- }
953
-
954
- /**
955
- * JWT Assertion Claims for OAuth2 JWT Bearer Grant (RFC 7523) and OAuth2 Access Tokens
956
- * @see https://datatracker.ietf.org/doc/html/rfc7523
957
- * @see https://datatracker.ietf.org/doc/html/rfc9068
958
- */
959
- interface JWTAssertionClaims {
960
- /**
961
- * REQUIRED. Issuer - the workload identity (e.g., SPIFFE ID) or authorization server
962
- */
963
- iss: string;
964
- /**
965
- * REQUIRED. Subject - the workload identity or service account
966
- */
967
- sub: string;
968
- /**
969
- * OPTIONAL. Audience - may be a string or array of strings
970
- * Note: Required for JWT assertions, but may be absent in OAuth2 access tokens
971
- */
972
- aud?: string | string[];
973
- /**
974
- * REQUIRED. Expiration time (Unix timestamp)
975
- */
976
- exp: number;
977
- /**
978
- * REQUIRED. Issued at time (Unix timestamp)
979
- */
980
- iat: number;
981
- /**
982
- * OPTIONAL. JWT ID - unique identifier for this token
983
- * Note: Required for JWT assertions, optional for access tokens
984
- */
985
- jti?: string;
986
- /**
987
- * OPTIONAL. Requested OAuth scopes (space-delimited)
988
- */
989
- scope?: string;
990
- /**
991
- * Allow additional claims for extensibility
992
- */
993
- [key: string]: unknown;
994
- }
995
- /**
996
- * Creates a StandardSchemaV1 for validating JWT Assertion Claims.
997
- * @param vendor - The name of the vendor creating this schema
998
- * @returns A StandardSchemaV1 instance for JWT Assertion Claims validation
999
- */
1000
- declare function jwtAssertionClaimsSchema(vendor: string): StandardSchemaV1<Record<string, unknown>, JWTAssertionClaims>;
1001
- /**
1002
- * Workload Token Response from OAuth2 token endpoint
1003
- * @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.1
1004
- */
1005
- interface WorkloadTokenResponse {
1006
- /**
1007
- * REQUIRED. The access token issued by the authorization server.
1008
- */
1009
- access_token: string;
1010
- /**
1011
- * REQUIRED. The type of the token (typically "Bearer").
1012
- */
1013
- token_type: string;
1014
- /**
1015
- * RECOMMENDED. The lifetime in seconds of the access token.
1016
- */
1017
- expires_in?: number;
1018
- /**
1019
- * OPTIONAL. The scope of the access token.
1020
- */
1021
- scope?: string;
1022
- /**
1023
- * OPTIONAL. The refresh token (rarely used for workload identities).
1024
- */
1025
- refresh_token?: string;
1026
- /**
1027
- * OPTIONAL. The expiration time as an ISO 8601 string.
1028
- */
1029
- expires?: string;
1030
- }
1031
- /**
1032
- * Creates a StandardSchemaV1 for validating Workload Token Responses.
1033
- * @param vendor - The name of the vendor creating this schema
1034
- * @returns A StandardSchemaV1 instance for Workload Token Response validation
1035
- */
1036
- declare function workloadTokenResponseSchema(vendor: string): StandardSchemaV1<Record<string, unknown>, WorkloadTokenResponse>;
1037
- /**
1038
- * Token Validation Result
1039
- */
1040
- interface TokenValidationResult {
1041
- /**
1042
- * Whether the token is valid
1043
- */
1044
- valid: boolean;
1045
- /**
1046
- * The decoded and validated claims (if valid)
1047
- */
1048
- claims?: JWTAssertionClaims;
1049
- /**
1050
- * Error message (if invalid)
1051
- */
1052
- error?: string;
1053
- /**
1054
- * Token expiration time (if valid)
1055
- */
1056
- expiresAt?: Date;
1057
- }
1058
-
1059
- /**
1060
- * Token caching for workload identity authentication.
1061
- *
1062
- * Token stores are optional but recommended for performance - they enable:
1063
- * - Token caching to avoid repeated token acquisition
1064
- * - Automatic token refresh before expiration
1065
- * - Reduced load on authorization servers
1066
- *
1067
- * ## Token Caching Strategy
1068
- *
1069
- * Unlike session stores for user authentication, workload token stores cache
1070
- * short-lived access tokens (typically 5 minutes) for service-to-service calls.
1071
- *
1072
- * **Default Behavior:**
1073
- * - Tokens cached with 5-minute TTL
1074
- * - Auto-refresh 60 seconds before expiration
1075
- * - Expired tokens automatically removed
1076
- *
1077
- * ## Performance Characteristics
1078
- *
1079
- * | Backend | Lookup Time | Use Case |
1080
- * |--------------|-------------|----------------------------|
1081
- * | InMemory | <0.00005ms | Single-server deployments |
1082
- * | Redis | 1-2ms | Multi-server deployments |
1083
- * | Database | 5-20ms | Persistent token storage |
1084
- *
1085
- * ## Example Usage
1086
- *
1087
- * ```typescript
1088
- * import { workload, InMemoryWorkloadTokenStore } from '@enterprisestandard/react/server';
1089
- *
1090
- * // With token caching
1091
- * const workloadAuth = workload({
1092
- * // ... other config
1093
- * token_store: new InMemoryWorkloadTokenStore(),
1094
- * auto_refresh: true, // Refresh before expiry
1095
- * });
1096
- *
1097
- * // Without token caching (fetch new token each time)
1098
- * const workloadAuth = workload({
1099
- * // ... config without token_store
1100
- * });
1101
- * ```
1102
- */
1103
- /**
1104
- * Cached workload token data.
1105
- *
1106
- * @template TExtended - Type-safe custom data that consumers can add to cached tokens
1107
- */
1108
- type CachedWorkloadToken<TExtended = object> = {
1109
- /**
1110
- * Workload identifier (typically SPIFFE ID).
1111
- * Used as the primary key for token lookup.
1112
- */
1113
- workload_id: string;
1114
- /**
1115
- * OAuth2 access token (Bearer token)
1116
- */
1117
- access_token: string;
1118
- /**
1119
- * Token type (always "Bearer" for OAuth2)
1120
- */
1121
- token_type: string;
1122
- /**
1123
- * OAuth2 scopes granted for this token
1124
- */
1125
- scope?: string;
1126
- /**
1127
- * Timestamp when the token expires.
1128
- * Used for automatic cleanup and refresh logic.
1129
- */
1130
- expires_at: Date;
1131
- /**
1132
- * Timestamp when the token was created/cached.
1133
- */
1134
- created_at: Date;
1135
- /**
1136
- * Optional refresh token (rarely used for workload identities)
1137
- */
1138
- refresh_token?: string;
1139
- } & TExtended;
1140
- /**
1141
- * Abstract interface for workload token storage backends.
1142
- *
1143
- * Consumers can implement this interface to use different storage backends:
1144
- * - Redis (recommended for multi-server deployments)
1145
- * - Database (PostgreSQL, MySQL, etc. for persistence)
1146
- * - Distributed cache (Memcached, etc.)
1147
- * - Custom solutions
1148
- *
1149
- * @template TExtended - Type-safe custom data that consumers can add to cached tokens
1150
- *
1151
- * @example
1152
- * ```typescript
1153
- * // Custom token cache data
1154
- * type MyTokenData = {
1155
- * environment: string;
1156
- * region: string;
1157
- * };
1158
- *
1159
- * // Implement custom store with Redis
1160
- * class RedisWorkloadTokenStore implements WorkloadTokenStore<MyTokenData> {
1161
- * async set(token: CachedWorkloadToken<MyTokenData>): Promise<void> {
1162
- * const ttl = Math.floor((token.expires_at.getTime() - Date.now()) / 1000);
1163
- * await redis.setex(
1164
- * `workload:token:${token.workload_id}`,
1165
- * ttl,
1166
- * JSON.stringify(token)
1167
- * );
1168
- * }
1169
- *
1170
- * async get(workload_id: string): Promise<CachedWorkloadToken<MyTokenData> | null> {
1171
- * const data = await redis.get(`workload:token:${workload_id}`);
1172
- * if (!data) return null;
1173
- * const token = JSON.parse(data);
1174
- * // Convert date strings back to Date objects
1175
- * token.expires_at = new Date(token.expires_at);
1176
- * token.created_at = new Date(token.created_at);
1177
- * return token;
1178
- * }
1179
- *
1180
- * // ... other methods
1181
- * }
1182
- * ```
1183
- */
1184
- interface WorkloadTokenStore<TExtended = object> {
1185
- /**
1186
- * Store or update a workload token in the cache.
1187
- *
1188
- * @param token - The token data to cache
1189
- */
1190
- set(token: CachedWorkloadToken<TExtended>): Promise<void>;
1191
- /**
1192
- * Retrieve a cached token by workload ID.
1193
- *
1194
- * @param workload_id - The workload identifier (e.g., SPIFFE ID)
1195
- * @returns The cached token if found and not expired, null otherwise
1196
- */
1197
- get(workload_id: string): Promise<CachedWorkloadToken<TExtended> | null>;
1198
- /**
1199
- * Delete a cached token by workload ID.
1200
- *
1201
- * Used when explicitly revoking tokens or clearing cache.
1202
- *
1203
- * @param workload_id - The workload identifier to remove
1204
- */
1205
- delete(workload_id: string): Promise<void>;
1206
- /**
1207
- * Check if a valid (non-expired) token exists for a workload.
1208
- *
1209
- * @param workload_id - The workload identifier to check
1210
- * @returns true if a valid token exists, false otherwise
1211
- */
1212
- isValid(workload_id: string): Promise<boolean>;
1213
- /**
1214
- * Remove all expired tokens from the cache.
1215
- *
1216
- * Should be called periodically to prevent memory leaks.
1217
- */
1218
- cleanup(): Promise<void>;
1219
- }
1220
- /**
1221
- * In-memory workload token store implementation using Maps.
1222
- *
1223
- * Suitable for:
1224
- * - Development and testing
1225
- * - Single-server deployments
1226
- * - Applications without high availability requirements
1227
- *
1228
- * NOT suitable for:
1229
- * - Multi-server deployments (tokens not shared across instances)
1230
- * - High availability scenarios (tokens lost on restart)
1231
- * - Production applications with distributed architecture
1232
- *
1233
- * For production multi-server deployments, implement WorkloadTokenStore with Redis.
1234
- *
1235
- * @template TExtended - Type-safe custom data that consumers can add to cached tokens
1236
- */
1237
- declare class InMemoryWorkloadTokenStore<TExtended = object> implements WorkloadTokenStore<TExtended> {
1238
- private tokens;
1239
- set(token: CachedWorkloadToken<TExtended>): Promise<void>;
1240
- get(workload_id: string): Promise<CachedWorkloadToken<TExtended> | null>;
1241
- delete(workload_id: string): Promise<void>;
1242
- isValid(workload_id: string): Promise<boolean>;
1243
- cleanup(): Promise<void>;
1244
- }
1245
-
1246
- /**
1247
- * Common fields shared across all workload authentication modes
1248
- */
1249
- type WorkloadConfigBase = {
1250
- /**
1251
- * OAuth2 token endpoint URL
1252
- * REQUIRED for client role (token acquisition)
1253
- */
1254
- token_url?: string;
1255
- /**
1256
- * JWKS endpoint URL for public key retrieval
1257
- * REQUIRED for server role (token validation)
1258
- */
1259
- jwks_uri?: string;
1260
- /**
1261
- * Expected token issuer URL for validation
1262
- * RECOMMENDED for server role (token validation)
1263
- */
1264
- issuer?: string;
1265
- /**
1266
- * Target audience for tokens
1267
- */
1268
- audience?: string;
1269
- /**
1270
- * Default OAuth2 scopes (space-delimited)
1271
- */
1272
- scope?: string;
1273
- /**
1274
- * JWT assertion/token lifetime in seconds
1275
- * @default 300 (5 minutes)
1276
- */
1277
- token_lifetime?: number;
1278
- /**
1279
- * Refresh threshold in seconds (refresh token this many seconds before expiry)
1280
- * @default 60
1281
- */
1282
- refresh_threshold?: number;
1283
- /**
1284
- * Optional token store for caching access tokens
1285
- */
1286
- token_store?: WorkloadTokenStore;
1287
- /**
1288
- * Automatically refresh tokens before expiration
1289
- * @default true
1290
- */
1291
- auto_refresh?: boolean;
1292
- /**
1293
- * Optional RFC 7009 token revocation endpoint
1294
- */
1295
- revocation_endpoint?: string;
1296
- /**
1297
- * Optional handler defaults (merged with per-call overrides in `handler`)
1298
- */
1299
- tokenUrl?: string;
1300
- validateUrl?: string;
1301
- jwksUrl?: string;
1302
- refreshUrl?: string;
1303
- validation?: {
1304
- jwtAssertionClaims?: StandardSchemaV1<unknown, JWTAssertionClaims>;
1305
- tokenResponse?: StandardSchemaV1<unknown, WorkloadTokenResponse>;
1306
- };
1307
- };
1308
- /**
1309
- * JWT Bearer Grant (RFC 7523) Configuration
1310
- *
1311
- * Used for SPIFFE-style workload identities where services have their own
1312
- * cryptographic identity and sign their own JWT assertions.
1313
- *
1314
- * @example
1315
- * ```json
1316
- * {
1317
- * "token_url": "https://auth.example.com/oauth/token",
1318
- * "jwks_uri": "https://auth.example.com/.well-known/jwks.json",
1319
- * "workload_id": "spiffe://trust-domain/ns/service",
1320
- * "audience": "https://auth.example.com/oauth/token",
1321
- * "private_key": "-----BEGIN PRIVATE KEY-----...",
1322
- * "algorithm": "RS256"
1323
- * }
1324
- * ```
1325
- */
1326
- type JwtBearerWorkloadConfig = WorkloadConfigBase & {
1327
- /**
1328
- * Workload identifier (e.g., SPIFFE ID: spiffe://trust-domain/namespace/service)
1329
- * REQUIRED for JWT Bearer Grant mode
1330
- */
1331
- workload_id?: string;
1332
- /**
1333
- * PEM-encoded private key for signing JWT assertions
1334
- * REQUIRED for client role in JWT Bearer Grant mode
1335
- */
1336
- private_key?: string;
1337
- /**
1338
- * Key ID (kid) to include in JWT header for key rotation support
1339
- */
1340
- key_id?: string;
1341
- /**
1342
- * JWT signing algorithm
1343
- * @default 'RS256'
1344
- */
1345
- algorithm?: 'RS256' | 'RS384' | 'RS512' | 'ES256' | 'ES384' | 'ES512';
1346
- };
1347
- /**
1348
- * OAuth2 Client Credentials Configuration
1349
- *
1350
- * Standard OAuth2 Client Credentials Grant (RFC 6749 Section 4.4).
1351
- * Used with identity providers like Keycloak for service-to-service authentication.
1352
- *
1353
- * @example
1354
- * ```json
1355
- * {
1356
- * "token_url": "https://sso.example.com/realms/myrealm/protocol/openid-connect/token",
1357
- * "jwks_uri": "https://sso.example.com/realms/myrealm/protocol/openid-connect/certs",
1358
- * "client_id": "my-service",
1359
- * "client_secret": "secret-from-idp",
1360
- * "issuer": "https://sso.example.com/realms/myrealm",
1361
- * "scope": "api:read api:write"
1362
- * }
1363
- * ```
1364
- */
1365
- type ClientCredentialsWorkloadConfig = WorkloadConfigBase & {
1366
- /**
1367
- * OAuth2 client identifier registered with the authorization server
1368
- * REQUIRED for Client Credentials mode
1369
- */
1370
- client_id?: string;
1371
- /**
1372
- * OAuth2 client secret
1373
- * REQUIRED for Client Credentials mode
1374
- */
1375
- client_secret?: string;
1376
- };
1377
- /**
1378
- * Server-Only Workload Configuration
1379
- *
1380
- * Used when a service only needs to validate incoming workload tokens,
1381
- * not acquire tokens for outbound calls. Requires only jwks_uri for
1382
- * public key retrieval.
1383
- *
1384
- * @example
1385
- * ```json
1386
- * {
1387
- * "jwks_uri": "https://sso.example.com/realms/myrealm/protocol/openid-connect/certs",
1388
- * "issuer": "https://sso.example.com/realms/myrealm"
1389
- * }
1390
- * ```
1391
- */
1392
- type ServerOnlyWorkloadConfig = WorkloadConfigBase;
1393
- /**
1394
- * Workload Identity Authentication Configuration
1395
- *
1396
- * Union type supporting multiple authentication modes. The mode is automatically
1397
- * detected based on which fields are present:
1398
- *
1399
- * - **JWT Bearer Grant**: Requires `workload_id` + `private_key`
1400
- * - **Client Credentials**: Requires `client_id` + `client_secret`
1401
- * - **Server-Only**: Only `jwks_uri` (and optionally `issuer`) for token validation
1402
- *
1403
- * The developer uses the same API regardless of mode - the library handles the details.
1404
- */
1405
- type WorkloadConfig = JwtBearerWorkloadConfig | ClientCredentialsWorkloadConfig | ServerOnlyWorkloadConfig;
1406
- /**
1407
- * Workload Identity extracted from validated tokens
1408
- */
1409
- type WorkloadIdentity = {
1410
- /**
1411
- * Workload identifier (for JWT Bearer Grant tokens)
1412
- */
1413
- workload_id?: string;
1414
- /**
1415
- * Client identifier (for OAuth2 Client Credentials tokens)
1416
- */
1417
- client_id?: string;
1418
- /**
1419
- * Granted scopes
1420
- */
1421
- scope?: string;
1422
- /**
1423
- * Full JWT claims from the token
1424
- */
1425
- claims: JWTAssertionClaims;
1426
- };
1427
- /**
1428
- * Workload Identity Authentication Interface
1429
- */
1430
- type Workload = WorkloadConfig & {
1431
- getToken: (scope?: string) => Promise<string>;
1432
- refreshToken: () => Promise<WorkloadTokenResponse>;
1433
- generateJWTAssertion: (scope?: string) => Promise<string>;
1434
- revokeToken: (token: string) => Promise<void>;
1435
- validateToken: (token: string, validation?: WorkloadConfig['validation']) => Promise<TokenValidationResult>;
1436
- getWorkload: (request: Request) => Promise<WorkloadIdentity | undefined>;
1437
- parseJWT: (token: string, validation?: WorkloadConfig['validation']) => Promise<JWTAssertionClaims>;
1438
- handler: (request: Request) => Promise<Response>;
1439
- };
1440
- /**
1441
- * Create a workload identity authentication instance
1442
- *
1443
- * @param config - Workload authentication configuration
1444
- * @returns Workload authentication interface
1445
- *
1446
- * @example
1447
- * ```typescript
1448
- * import { workload } from '@enterprisestandard/react';
1449
- *
1450
- * const workloadAuth = workload({
1451
- * token_url: 'https://auth.example.com/oauth/token',
1452
- * jwks_uri: 'https://auth.example.com/.well-known/jwks.json',
1453
- * workload_id: 'spiffe://trust-domain/ns/service',
1454
- * audience: 'https://auth.example.com/oauth/token',
1455
- * private_key: '-----BEGIN PRIVATE KEY-----...',
1456
- * algorithm: 'RS256',
1457
- * });
1458
- *
1459
- * // Get access token
1460
- * const token = await workloadAuth.getToken('api:read api:write');
1461
- * ```
1462
- */
1463
- declare function workload(config?: WorkloadConfig): Workload;
1464
-
1465
- /**
1466
- * SCIM Error response structure
1467
- */
1468
- interface ScimError {
1469
- schemas: string[];
1470
- status: string;
1471
- scimType?: string;
1472
- detail?: string;
1473
- }
1474
- /**
1475
- * SCIM List Response for bulk operations
1476
- */
1477
- interface ScimListResponse<T> {
1478
- schemas: string[];
1479
- totalResults: number;
1480
- startIndex?: number;
1481
- itemsPerPage?: number;
1482
- Resources: T[];
1483
- }
1484
- /**
1485
- * Result of a SCIM operation
1486
- */
1487
- interface ScimResult<T> {
1488
- success: boolean;
1489
- data?: T;
1490
- error?: ScimError;
1491
- status: number;
1492
- }
1493
- /**
1494
- * Handler configuration for IAM
1495
- */
1496
- interface IAMHandlerConfig {
1497
- /**
1498
- * Base path for the SCIM Users endpoints (e.g., '/api/iam/Users')
1499
- */
1500
- usersUrl?: string;
1501
- /**
1502
- * Base path for the SCIM Groups endpoints (e.g., '/api/iam/Groups')
1503
- */
1504
- groupsUrl?: string;
1505
- }
1506
- /**
1507
- * IAM configuration
1508
- *
1509
- * - If `url` is provided, groups_outbound is enabled (app calls external IAM)
1510
- * - If `group_store` is provided, groups_inbound is enabled (external IAM calls app)
1511
- * - If `user_store` is provided, users_inbound is enabled (external IAM calls app)
1512
- */
1513
- type IAMConfig = {
1514
- /**
1515
- * Base URL of the external SCIM endpoint (e.g., https://sailpoint.example.com/scim/v2)
1516
- * If provided, enables outbound SCIM operations (app -> external IAM)
1517
- */
1518
- url?: string;
1519
- /**
1520
- * Store for inbound user provisioning from external IAM providers.
1521
- * When configured, the app can receive user CRUD operations via SCIM.
1522
- */
1523
- user_store?: UserStore;
1524
- /**
1525
- * Store for inbound group provisioning from external IAM providers.
1526
- * When configured, enables groups_inbound (external IAM -> app).
1527
- */
1528
- group_store?: GroupStore;
1529
- /**
1530
- * Optional handler defaults. These are merged with per-call overrides in
1531
- * `iam.handler`, with per-call values taking precedence.
1532
- */
1533
- usersUrl?: string;
1534
- groupsUrl?: string;
1535
- };
1536
- /**
1537
- * Options for creating a group
1538
- */
1539
- interface CreateGroupOptions {
1540
- /**
1541
- * External identifier for the group
1542
- */
1543
- externalId?: string;
1544
- /**
1545
- * Initial members to add to the group
1546
- */
1547
- members?: GroupMember[];
1548
- /**
1549
- * Custom validation schema for the response
1550
- */
1551
- validation?: StandardSchemaV1<unknown, GroupResource>;
1552
- }
1553
- /**
1554
- * Options for creating a user
1555
- */
1556
- interface CreateUserOptions {
1557
- /**
1558
- * Custom validation schema for the response
1559
- */
1560
- validation?: StandardSchemaV1<unknown, User$1>;
1561
- }
1562
- /**
1563
- * Handler configuration for groups_inbound
1564
- */
1565
- interface GroupsInboundHandlerConfig {
1566
- /**
1567
- * Base path for the SCIM Groups endpoints (e.g., '/api/iam/Groups')
1568
- */
1569
- basePath?: string;
1570
- }
1571
- /**
1572
- * Handler configuration for users_inbound
1573
- */
1574
- interface UsersInboundHandlerConfig {
1575
- /**
1576
- * Base path for the SCIM Users endpoints (e.g., '/api/iam/Users')
1577
- */
1578
- basePath?: string;
1579
- }
1580
- /**
1581
- * Groups Outbound extension - for creating groups in external IAM providers.
1582
- * Enabled when `url` is configured in IAMConfig.
1583
- */
1584
- type IAMGroupsOutbound = {
1585
- /**
1586
- * Create a new group in the external IAM provider
1587
- * @param displayName - The display name for the group
1588
- * @param options - Optional configuration for the group creation
1589
- * @returns The created group resource from the provider
1590
- */
1591
- createGroup: (displayName: string, options?: CreateGroupOptions) => Promise<ScimResult<GroupResource>>;
1592
- };
1593
- /**
1594
- * Groups Inbound extension - for receiving group provisioning from external IAM providers.
1595
- * Enabled when `group_store` is configured in IAMConfig.
1596
- */
1597
- type IAMGroupsInbound = {
1598
- /**
1599
- * Handle inbound SCIM requests for group management.
1600
- * Routes: GET/POST /Groups, GET/PUT/PATCH/DELETE /Groups/:id
1601
- */
1602
- handler: (request: Request, config?: GroupsInboundHandlerConfig) => Promise<Response>;
1603
- };
1604
- /**
1605
- * Users Inbound extension - for receiving user provisioning from external IAM providers.
1606
- * Enabled when `user_store` is configured in IAMConfig.
1607
- */
1608
- type IAMUsersInbound = {
1609
- /**
1610
- * Handle inbound SCIM requests for user management.
1611
- * Routes: GET/POST /Users, GET/PUT/PATCH/DELETE /Users/:id
1612
- */
1613
- handler: (request: Request, config?: UsersInboundHandlerConfig) => Promise<Response>;
1614
- };
1615
- /**
1616
- * Core IAM service interface.
1617
- *
1618
- * - Core functions are user-related (outbound to external IAM)
1619
- * - `groups_outbound` is available when `url` is configured
1620
- * - `groups_inbound` is available when `group_store` is configured
1621
- * - `users_inbound` is available when `user_store` is configured
1622
- */
1623
- type IAM = IAMConfig & {
1624
- /**
1625
- * Create a new user/account in the external IAM provider
1626
- * Only available when `url` is configured.
1627
- */
1628
- createUser?: (user: User$1, options?: CreateUserOptions) => Promise<ScimResult<User$1>>;
1629
- /**
1630
- * Get the configured external SCIM base URL
1631
- */
1632
- getBaseUrl: () => string | undefined;
1633
- /**
1634
- * Groups Outbound extension - create groups in external IAM provider.
1635
- * Available when `url` is configured in IAMConfig.
1636
- */
1637
- groups_outbound?: IAMGroupsOutbound;
1638
- /**
1639
- * Groups Inbound extension - receive group provisioning from external IAM.
1640
- * Available when `group_store` is configured in IAMConfig.
1641
- */
1642
- groups_inbound?: IAMGroupsInbound;
1643
- /**
1644
- * Users Inbound extension - receive user provisioning from external IAM.
1645
- * Available when `user_store` is configured in IAMConfig.
1646
- */
1647
- users_inbound?: IAMUsersInbound;
1648
- /**
1649
- * Framework-agnostic request handler for IAM endpoints.
1650
- * Routes to users_inbound or groups_inbound handlers based on the request path.
1651
- */
1652
- handler: (request: Request, config?: IAMHandlerConfig) => Promise<Response>;
1653
- };
1654
- /**
1655
- * Creates an IAM service instance.
1656
- *
1657
- * - If `url` is configured, enables outbound SCIM operations to external IAM
1658
- * - If `group_store` is configured, enables inbound SCIM operations from external IAM
1659
- *
1660
- * @param config - IAM configuration
1661
- * @param workload - Workload instance for authentication
1662
- * @returns IAM service instance
1663
- */
1664
- declare function iam(config: IAMConfig, workload: Workload): IAM;
1665
-
1666
- /**
1667
- * Session management for tracking user sessions and enabling backchannel logout.
1668
- *
1669
- * Session stores are optional - the package works with JWT cookies alone.
1670
- * Sessions are only required for backchannel logout functionality.
1671
- *
1672
- * ## Session Validation Strategies
1673
- *
1674
- * When using a session store, you can configure when sessions are validated:
1675
- *
1676
- * ### 'always' (default)
1677
- * Validates session on every authenticated request.
1678
- * - **Security**: Maximum - immediate session revocation
1679
- * - **Performance**: InMemory ~0.00005ms, Redis ~1-2ms per request
1680
- * - **Backchannel Logout**: Takes effect immediately
1681
- * - **Use when**: Security is paramount, using InMemory or Redis backend
1682
- *
1683
- * ### 'refresh-only'
1684
- * Validates session only during token refresh (typically every 5-15 minutes).
1685
- * - **Security**: Good - 5-15 minute revocation window
1686
- * - **Performance**: 99% reduction in session lookups
1687
- * - **Backchannel Logout**: Takes effect within token TTL (5-15 min)
1688
- * - **Use when**: Performance is critical AND delayed revocation is acceptable
1689
- * - **WARNING**: Compromised sessions remain valid until next refresh
1690
- *
1691
- * ### 'disabled'
1692
- * Never validates sessions against the store.
1693
- * - **Security**: None - backchannel logout doesn't work
1694
- * - **Performance**: No overhead
1695
- * - **Use when**: Cookie-only mode without session store
1696
- * - **WARNING**: Do not use with session_store configured
1697
- *
1698
- * ## Performance Characteristics
1699
- *
1700
- * | Backend | Lookup Time | Impact on Request | Recommendation |
1701
- * |--------------|-------------|-------------------|------------------------|
1702
- * | InMemory | <0.00005ms | Negligible | Use 'always' |
1703
- * | Redis | 1-2ms | 2-4% increase | Use 'always' or test |
1704
- * | Database | 5-20ms | 10-40% increase | Use Redis cache layer |
1705
- *
1706
- * ## Example Usage
1707
- *
1708
- * ```typescript
1709
- * import { sso, InMemorySessionStore } from '@enterprisestandard/react/server';
1710
- *
1711
- * // Maximum security (default)
1712
- * const secure = sso({
1713
- * // ... other config
1714
- * session_store: new InMemorySessionStore(),
1715
- * session_validation: 'always', // Immediate revocation
1716
- * });
1717
- *
1718
- * // High performance
1719
- * const fast = sso({
1720
- * // ... other config
1721
- * session_store: new InMemorySessionStore(),
1722
- * session_validation: {
1723
- * strategy: 'refresh-only' // 5-15 min revocation delay
1724
- * }
1725
- * });
1726
- * ```
1727
- */
1728
- /**
1729
- * Core session data tracked for each authenticated user session.
1730
- *
1731
- * @template TExtended - Type-safe custom data that consumers can add to sessions
1732
- */
1733
- type Session<TExtended = {}> = {
1734
- /**
1735
- * Session ID from the Identity Provider (from `sid` claim in ID token).
1736
- * This is the unique identifier for the session.
1737
- */
1738
- sid: string;
1739
- /**
1740
- * Subject identifier (user ID) from the Identity Provider.
1741
- * From the `sub` claim in the ID token.
1742
- */
1743
- sub: string;
1744
- /**
1745
- * Timestamp when the session was created.
1746
- */
1747
- createdAt: Date;
1748
- /**
1749
- * Timestamp of the last activity in this session.
1750
- * Can be updated to track session activity.
1751
- */
1752
- lastActivityAt: Date;
1753
- /**
1754
- * Allow consumers to add runtime data to sessions.
1755
- */
1756
- [key: string]: unknown;
1757
- } & TExtended;
1758
- /**
1759
- * Abstract interface for session storage backends.
1760
- *
1761
- * Consumers can implement this interface to use different storage backends:
1762
- * - Redis
1763
- * - Database (PostgreSQL, MySQL, etc.)
1764
- * - Distributed cache
1765
- * - Custom solutions
1766
- *
1767
- * @template TExtended - Type-safe custom data that consumers can add to sessions
1768
- *
1769
- * @example
1770
- * ```typescript
1771
- * // Custom session data
1772
- * type MySessionData = {
1773
- * ipAddress: string;
1774
- * userAgent: string;
1775
- * };
1776
- *
1777
- * // Implement custom store
1778
- * class RedisSessionStore implements SessionStore<MySessionData> {
1779
- * async create(session: Session<MySessionData>): Promise<void> {
1780
- * await redis.set(`session:${session.sid}`, JSON.stringify(session));
1781
- * }
1782
- * // ... other methods
1783
- * }
1784
- * ```
1785
- */
1786
- interface SessionStore<TExtended = {}> {
1787
- /**
1788
- * Create a new session in the store.
1789
- *
1790
- * @param session - The session data to store
1791
- * @throws Error if session with same sid already exists
1792
- */
1793
- create(session: Session<TExtended>): Promise<void>;
1794
- /**
1795
- * Retrieve a session by its IdP session ID (sid).
1796
- *
1797
- * @param sid - The session.sid from the Identity Provider
1798
- * @returns The session if found, null otherwise
1799
- */
1800
- get(sid: string): Promise<Session<TExtended> | null>;
1801
- /**
1802
- * Update an existing session with partial data.
1803
- *
1804
- * Commonly used to update lastActivityAt or add custom fields.
1805
- *
1806
- * @param sid - The session.sid to update
1807
- * @param data - Partial session data to merge
1808
- * @throws Error if session not found
1809
- */
1810
- update(sid: string, data: Partial<Session<TExtended>>): Promise<void>;
1811
- /**
1812
- * Delete a session by its IdP session ID (sid).
1813
- *
1814
- * Used for both normal logout and backchannel logout flows.
1815
- *
1816
- * @param sid - The session.sid to delete
1817
- */
1818
- delete(sid: string): Promise<void>;
1819
- }
1820
- /**
1821
- * In-memory session store implementation using Maps.
1822
- *
1823
- * Suitable for:
1824
- * - Development and testing
1825
- * - Single-server deployments
1826
- * - Applications without high availability requirements
1827
- *
1828
- * NOT suitable for:
1829
- * - Multi-server deployments (sessions not shared)
1830
- * - High availability scenarios (sessions lost on restart)
1831
- * - Production applications with distributed architecture
1832
- *
1833
- * For production, implement SessionStore with Redis or a database.
1834
- *
1835
- * @template TExtended - Type-safe custom data that consumers can add to sessions
1836
- */
1837
- declare class InMemorySessionStore<TExtended = {}> implements SessionStore<TExtended> {
1838
- private sessions;
1839
- create(session: Session<TExtended>): Promise<void>;
1840
- get(sid: string): Promise<Session<TExtended> | null>;
1841
- update(sid: string, data: Partial<Session<TExtended>>): Promise<void>;
1842
- delete(sid: string): Promise<void>;
1843
- }
1844
-
1845
- type SSOConfig<TSessionData = {}, TUserData = {}> = {
1846
- authority?: string;
1847
- token_url?: string;
1848
- authorization_url?: string;
1849
- client_id?: string;
1850
- client_secret?: string;
1851
- redirect_uri?: string;
1852
- response_type?: 'code';
1853
- scope?: string;
1854
- silent_redirect_uri?: string;
1855
- jwks_uri?: string;
1856
- cookies_prefix?: string;
1857
- cookies_path?: string;
1858
- cookies_secure?: boolean;
1859
- cookies_same_site?: 'Strict' | 'Lax';
1860
- end_session_endpoint?: string;
1861
- revocation_endpoint?: string;
1862
- session_store?: SessionStore<TSessionData>;
1863
- /**
1864
- * Optional handler defaults. These are merged with per-call overrides in
1865
- * `sso.handler`, with per-call values taking precedence.
1866
- */
1867
- loginUrl?: string;
1868
- userUrl?: string;
1869
- errorUrl?: string;
1870
- landingUrl?: string;
1871
- tokenUrl?: string;
1872
- refreshUrl?: string;
1873
- jwksUrl?: string;
1874
- logoutUrl?: string;
1875
- logoutBackChannelUrl?: string;
1876
- validation?: {
1877
- callbackParams?: StandardSchemaV1<unknown, OidcCallbackParams>;
1878
- idTokenClaims?: StandardSchemaV1<unknown, IdTokenClaims>;
1879
- tokenResponse?: StandardSchemaV1<unknown, TokenResponse>;
1880
- };
1881
- /**
1882
- * Optional user store for persisting user profiles from SSO authentication.
1883
- * When configured, users are automatically stored/updated on each login.
1884
- */
1885
- user_store?: UserStore<TUserData>;
1886
- /**
1887
- * Enable Just-In-Time (JIT) user provisioning.
1888
- * When enabled, new users are automatically created in the user_store on their first login.
1889
- * When disabled (default), only existing users in the user_store are updated on login.
1890
- * Requires user_store to be configured.
1891
- * @default false
1892
- */
1893
- enable_jit_user_provisioning?: boolean;
1894
- };
1895
- type SSOConfigWithDefaults<TSessionData = {}, TUserData = {}> = SSOConfig<TSessionData, TUserData> & {
1896
- authority: string;
1897
- token_url: string;
1898
- authorization_url: string;
1899
- client_id: string;
1900
- redirect_uri: string;
1901
- response_type: 'code';
1902
- scope: string;
1903
- cookies_secure: boolean;
1904
- cookies_same_site: string;
1905
- cookies_prefix: string;
1906
- cookies_path: string;
1907
- };
1908
- type ESConfig$1 = {
1909
- es?: EnterpriseStandard;
1910
- };
1911
- type LoginConfig = {
1912
- landingUrl: string;
1913
- errorUrl?: string;
1914
- } & ESConfig$1;
1915
- type SSOHandlerConfig = {
1916
- loginUrl?: string;
1917
- userUrl?: string;
1918
- errorUrl?: string;
1919
- landingUrl?: string;
1920
- tokenUrl?: string;
1921
- refreshUrl?: string;
1922
- jwksUrl?: string;
1923
- logoutUrl?: string;
1924
- logoutBackChannelUrl?: string;
1925
- validation?: {
1926
- callbackParams?: StandardSchemaV1<unknown, OidcCallbackParams>;
1927
- idTokenClaims?: StandardSchemaV1<unknown, IdTokenClaims>;
1928
- tokenResponse?: StandardSchemaV1<unknown, TokenResponse>;
1929
- };
1930
- } & ESConfig$1;
1931
- type SSO<TSessionData = {}, TUserData = {}> = SSOConfigWithDefaults<TSessionData, TUserData> & {
1932
- getUser: (request: Request) => Promise<User | undefined>;
1933
- getRequiredUser: (request: Request) => Promise<User>;
1934
- getJwt: (request: Request) => Promise<string | undefined>;
1935
- initiateLogin: (config: LoginConfig, requestUrl?: string) => Promise<Response>;
1936
- logout: (request: Request, config?: LoginConfig) => Promise<Response>;
1937
- callbackHandler: (request: Request) => Promise<Response>;
1938
- handler: (request: Request, es?: EnterpriseStandard) => Promise<Response>;
1939
- };
1940
- declare function sso<TSessionData = {}, TUserData = {}>(config?: SSOConfig<TSessionData, TUserData>): SSO<TSessionData, TUserData>;
1941
-
1942
- type Secret<T> = {
1943
- data: T;
1944
- metadata: MetaData;
1945
- };
1946
- type MetaData = {
1947
- created_time: string;
1948
- deletion_time: string;
1949
- destroyed: boolean;
1950
- version: number;
1951
- };
1952
- type Vault = {
1953
- url: string;
1954
- getFullSecret: <T>(path: string, token: string) => Promise<Secret<T>>;
1955
- getSecret: <T>(path: string, token: string) => Promise<T>;
1956
- };
1957
- declare function vault(url: string): Vault;
1958
-
1959
- /**
1960
- * Tenant Management SDK
1961
- *
1962
- * Provides helper functions for applications to implement tenant creation endpoints
1963
- * that ESVS can test. Supports both synchronous (201) and asynchronous (202)
1964
- * tenant creation with webhook-based status updates.
1965
- */
1966
- /**
1967
- * Environment type for tenant creation
1968
- */
1969
- type EnvironmentType = 'POC' | 'DEV' | 'QA' | 'PROD';
1970
- /**
1971
- * Status of tenant creation process
1972
- */
1973
- type TenantStatus = 'pending' | 'processing' | 'completed' | 'failed';
1974
- /**
1975
- * Request payload from ESVS for creating a tenant
1976
- */
1977
- interface CreateTenantRequest {
1978
- /**
1979
- * Required app identifier to use when initializing EnterpriseStandard for this tenant.
1980
- * This is the primary identifier for tenant management. A company can have multiple
1981
- * applications (e.g., one instance on the east coast, one on the west coast).
1982
- */
1983
- appId: string;
1984
- /**
1985
- * Company ID (used for reporting purposes only, not for tenant identification)
1986
- */
1987
- companyId: string;
1988
- /**
1989
- * Company Name
1990
- */
1991
- companyName: string;
1992
- /**
1993
- * Environment Type (POC, DEV, QA, PROD)
1994
- */
1995
- environmentType: EnvironmentType;
1996
- /**
1997
- * Email (The email or distribution list used to communicate to the team)
1998
- */
1999
- email: string;
2000
- /**
2001
- * Webhook URL where the application can send updates around the creation of the tenant
2002
- */
2003
- webhookUrl: string;
2004
- }
2005
- /**
2006
- * Response payload for tenant creation
2007
- */
2008
- interface CreateTenantResponse {
2009
- /**
2010
- * URL that the tenant will be available at
2011
- */
2012
- tenantUrl: string;
2013
- /**
2014
- * Current status of tenant creation
2015
- */
2016
- status: TenantStatus;
2017
- }
2018
- /**
2019
- * Payload sent to webhook URL for status updates
2020
- */
2021
- interface TenantWebhookPayload {
2022
- /**
2023
- * Company ID
2024
- */
2025
- companyId: string;
2026
- /**
2027
- * Current status of tenant creation
2028
- */
2029
- status: TenantStatus;
2030
- /**
2031
- * URL that the tenant will be available at (provided once creation completes)
2032
- */
2033
- tenantUrl?: string;
2034
- /**
2035
- * Error message (only present if status is "failed")
2036
- */
2037
- error?: string;
2038
- }
2039
- /**
2040
- * Error thrown when tenant request validation fails
2041
- */
2042
- declare class TenantRequestError extends Error {
2043
- constructor(message: string);
2044
- }
2045
- /**
2046
- * Serializes an ESConfig or EnterpriseStandard instance to a JSON-serializable format
2047
- * by removing non-serializable properties like stores, validators, and functions.
2048
- *
2049
- * Since EnterpriseStandard now extends ESConfig, the config (including handler URLs)
2050
- * is accessible directly from the instance.
2051
- *
2052
- * @param configOrES - The ESConfig object or EnterpriseStandard instance to serialize
2053
- * @returns A JSON-serializable version of the config
2054
- */
2055
- declare function serializeESConfig(configOrES: any): any;
2056
- /**
2057
- * Parse and validate a tenant creation request from an HTTP request.
2058
- *
2059
- * @param request - The HTTP request containing the tenant creation data
2060
- * @returns The validated tenant creation request
2061
- * @throws {TenantRequestError} If the request is invalid or missing required fields
2062
- *
2063
- * @example
2064
- * ```typescript
2065
- * app.post('/api/tenant', async (c) => {
2066
- * try {
2067
- * const tenantRequest = await parseTenantRequest(c.req.raw);
2068
- * // Create tenant...
2069
- * } catch (error) {
2070
- * if (error instanceof TenantRequestError) {
2071
- * return c.json({ error: error.message }, 400);
2072
- * }
2073
- * throw error;
2074
- * }
2075
- * });
2076
- * ```
2077
- */
2078
- declare function parseTenantRequest(request: Request): Promise<CreateTenantRequest>;
2079
- /**
2080
- * Send a webhook update to ESVS with tenant creation status.
2081
- *
2082
- * @param webhookUrl - The webhook URL provided in the tenant creation request
2083
- * @param payload - The webhook payload with status and tenant information
2084
- * @throws Never throws - errors are logged but not propagated to avoid breaking tenant creation
2085
- *
2086
- * @example
2087
- * ```typescript
2088
- * // Send initial status
2089
- * await sendTenantWebhook(tenantRequest.webhookUrl, {
2090
- * companyId: tenantRequest.companyId,
2091
- * status: 'processing',
2092
- * });
2093
- *
2094
- * // Send completion status
2095
- * await sendTenantWebhook(tenantRequest.webhookUrl, {
2096
- * companyId: tenantRequest.companyId,
2097
- * status: 'completed',
2098
- * tenantUrl: 'https://app.example.com/tenants/tenant-123',
2099
- * });
2100
- * ```
2101
- */
2102
- declare function sendTenantWebhook(webhookUrl: string, payload: TenantWebhookPayload): Promise<void>;
2103
- /**
2104
- * Stored tenant data with required appId and tracking metadata.
2105
- *
2106
- * @template TExtended - Type-safe custom data that consumers can add to tenants
2107
- */
2108
- type StoredTenant<TExtended = {}> = {
2109
- /**
2110
- * Required app identifier used to initialize EnterpriseStandard for this tenant.
2111
- * This is the primary key for tenant storage. A company can have multiple
2112
- * applications (e.g., one instance on the east coast, one on the west coast).
2113
- */
2114
- appId: string;
2115
- /**
2116
- * Company ID (used for reporting purposes only, not for tenant identification)
2117
- */
2118
- companyId: string;
2119
- /**
2120
- * Company Name
2121
- */
2122
- companyName: string;
2123
- /**
2124
- * Environment Type (POC, DEV, QA, PROD)
2125
- */
2126
- environmentType: EnvironmentType;
2127
- /**
2128
- * Email (The email or distribution list used to communicate to the team)
2129
- */
2130
- email: string;
2131
- /**
2132
- * Webhook URL where the application can send updates around the creation of the tenant
2133
- */
2134
- webhookUrl: string;
2135
- /**
2136
- * URL that the tenant will be available at
2137
- */
2138
- tenantUrl?: string;
2139
- /**
2140
- * Current status of tenant creation
2141
- */
2142
- status: TenantStatus;
2143
- /**
2144
- * Error message (only present if status is "failed")
2145
- */
2146
- error?: string;
2147
- /**
2148
- * Timestamp when the tenant was first stored.
2149
- */
2150
- createdAt: Date;
2151
- /**
2152
- * Timestamp when the tenant was last updated.
2153
- */
2154
- updatedAt: Date;
2155
- /**
2156
- * Serialized Enterprise Standard configuration.
2157
- * This is a JSON-serializable version of the ESConfig with non-serializable items excluded.
2158
- */
2159
- config?: any;
2160
- } & TExtended;
2161
- /**
2162
- * Abstract interface for tenant storage backends.
2163
- *
2164
- * Consumers can implement this interface to use different storage backends:
2165
- * - In-memory (for development/testing)
2166
- * - Redis (for production with fast lookups)
2167
- * - Database (PostgreSQL, MySQL, etc.)
2168
- *
2169
- * @template TExtended - Type-safe custom data that consumers can add to tenants
2170
- */
2171
- interface TenantStore<TExtended = {}> {
2172
- /**
2173
- * Retrieve a tenant by its app identifier.
2174
- *
2175
- * @param appId - The tenant's app identifier (primary key)
2176
- * @returns The tenant if found, null otherwise
2177
- */
2178
- get(appId: string): Promise<StoredTenant<TExtended> | null>;
2179
- /**
2180
- * Retrieve all tenants for a company ID.
2181
- * Since a company can have multiple applications, this returns an array.
2182
- *
2183
- * @param companyId - The company ID (used for reporting, not primary identification)
2184
- * @returns Array of tenants for the company, empty array if none found
2185
- */
2186
- getByCompanyId(companyId: string): Promise<StoredTenant<TExtended>[]>;
2187
- /**
2188
- * List all tenants in the store.
2189
- *
2190
- * @returns Array of all stored tenants
2191
- */
2192
- list(): Promise<StoredTenant<TExtended>[]>;
2193
- /**
2194
- * Create or update a tenant in the store.
2195
- *
2196
- * If a tenant with the same `appId` exists, it will be updated.
2197
- * Otherwise, a new tenant will be created.
2198
- *
2199
- * @param tenant - The tenant data to store
2200
- * @returns The stored tenant
2201
- */
2202
- upsert(tenant: StoredTenant<TExtended>): Promise<StoredTenant<TExtended>>;
2203
- /**
2204
- * Delete a tenant by its app identifier.
2205
- *
2206
- * @param appId - The tenant's app identifier to delete
2207
- */
2208
- delete(appId: string): Promise<void>;
2209
- }
2210
- /**
2211
- * In-memory tenant store implementation using Maps.
2212
- *
2213
- * Suitable for:
2214
- * - Development and testing
2215
- * - Single-server deployments
2216
- * - Applications without high availability requirements
2217
- *
2218
- * NOT suitable for:
2219
- * - Multi-server deployments (tenants not shared)
2220
- * - High availability scenarios (tenants lost on restart)
2221
- * - Production applications with distributed architecture
2222
- *
2223
- * For production, implement TenantStore with Redis or a database.
2224
- *
2225
- * @template TExtended - Type-safe custom data that consumers can add to tenants
2226
- */
2227
- declare class InMemoryTenantStore<TExtended = {}> implements TenantStore<TExtended> {
2228
- /** Primary storage: appId -> tenant */
2229
- private tenants;
2230
- /** Secondary index: companyId -> Set of appIds (since one company can have multiple apps) */
2231
- private companyIdIndex;
2232
- get(appId: string): Promise<StoredTenant<TExtended> | null>;
2233
- getByCompanyId(companyId: string): Promise<StoredTenant<TExtended>[]>;
2234
- list(): Promise<StoredTenant<TExtended>[]>;
2235
- upsert(tenant: StoredTenant<TExtended>): Promise<StoredTenant<TExtended>>;
2236
- delete(appId: string): Promise<void>;
2237
- }
2238
-
2239
- /**
2240
- * Get the workload identity from an incoming request.
2241
- * Returns undefined if no valid workload token is present.
2242
- *
2243
- * @param request - Request with Authorization header
2244
- * @param config - Optional EnterpriseStandard configuration
2245
- * @returns WorkloadIdentity or undefined
2246
- *
2247
- * @example
2248
- * ```typescript
2249
- * import { getWorkload } from '@enterprisestandard/react';
2250
- *
2251
- * export async function handler(request: Request) {
2252
- * const workload = await getWorkload(request);
2253
- *
2254
- * if (!workload) {
2255
- * return new Response('Unauthorized', { status: 401 });
2256
- * }
2257
- *
2258
- * console.log('Request from workload:', workload.workload_id);
2259
- * // ... process authenticated request
2260
- * }
2261
- * ```
2262
- */
2263
- declare function getWorkload(request: Request, es?: EnterpriseStandard): Promise<WorkloadIdentity | undefined>;
2264
- /**
2265
- * Get an access token for the configured workload identity.
2266
- *
2267
- * @param scope - Optional OAuth2 scopes (space-delimited)
2268
- * @param config - Optional EnterpriseStandard configuration
2269
- * @returns Access token string
2270
- *
2271
- * @example
2272
- * ```typescript
2273
- * import { getWorkloadToken } from '@enterprisestandard/react/server';
2274
- *
2275
- * // Get token for API calls
2276
- * const token = await getWorkloadToken('api:read api:write');
2277
- *
2278
- * // Use in outbound requests
2279
- * const response = await fetch('https://api.example.com/data', {
2280
- * headers: { 'Authorization': `Bearer ${token}` },
2281
- * });
2282
- * ```
2283
- */
2284
- declare function getWorkloadToken(scope?: string, es?: EnterpriseStandard): Promise<string>;
2285
- /**
2286
- * Validate a workload token from an incoming request.
2287
- *
2288
- * @param request - Request with Authorization header
2289
- * @param config - Optional EnterpriseStandard configuration
2290
- * @returns Token validation result
2291
- *
2292
- * @example
2293
- * ```typescript
2294
- * import { validateWorkloadToken } from '@enterprisestandard/react/server';
2295
- *
2296
- * export async function handler(request: Request) {
2297
- * const result = await validateWorkloadToken(request);
2298
- *
2299
- * if (!result.valid) {
2300
- * return new Response(
2301
- * JSON.stringify({ error: result.error }),
2302
- * { status: 401 }
2303
- * );
2304
- * }
2305
- *
2306
- * const workloadId = result.claims?.iss;
2307
- * // ... process authenticated request
2308
- * }
2309
- * ```
2310
- */
2311
- declare function validateWorkloadToken(request: Request, es?: EnterpriseStandard): Promise<TokenValidationResult>;
2312
- /**
2313
- * Revoke a workload access token.
2314
- *
2315
- * @param token - The access token to revoke
2316
- * @param config - Optional EnterpriseStandard configuration
2317
- *
2318
- * @example
2319
- * ```typescript
2320
- * import { revokeWorkloadToken } from '@enterprisestandard/react/server';
2321
- *
2322
- * // Revoke token when workload is decommissioned
2323
- * await revokeWorkloadToken(accessToken);
2324
- * ```
2325
- */
2326
- declare function revokeWorkloadToken(token: string, es?: EnterpriseStandard): Promise<void>;
2327
- /**
2328
- * Framework-agnostic handler for workload authentication routes.
2329
- *
2330
- * The handler reads configuration (handler URLs, validation) directly from the
2331
- * EnterpriseStandard instance, so no config parameter is needed.
2332
- *
2333
- * @param request - Incoming request
2334
- * @param config - Optional ESConfig to specify which EnterpriseStandard instance to use
2335
- * @returns Response
2336
- *
2337
- * @example
2338
- * ```typescript
2339
- * import { workloadHandler } from '@enterprisestandard/react/server';
2340
- *
2341
- * // TanStack Start example
2342
- * export const Route = createFileRoute('/api/workload/$')({
2343
- * server: {
2344
- * handlers: ({ createHandlers }) =>
2345
- * createHandlers({
2346
- * GET: {
2347
- * handler: async ({ request }) => {
2348
- * return workloadHandler(request);
2349
- * },
2350
- * },
2351
- * POST: {
2352
- * handler: async ({ request }) => {
2353
- * return workloadHandler(request);
2354
- * },
2355
- * },
2356
- * }),
2357
- * },
2358
- * });
2359
- * ```
2360
- */
2361
- declare function workloadHandler(request: Request, es?: EnterpriseStandard): Promise<Response>;
2362
-
2363
- /**
2364
- * Helper gets the user from the Request using the supplied EnterpriseStandard or the default instance
2365
- */
2366
- declare function getUser(request: Request, es?: EnterpriseStandard): Promise<User | undefined>;
2367
- declare function getRequiredUser(request: Request, es?: EnterpriseStandard): Promise<User>;
2368
- declare function initiateLogin(config: LoginConfig, es?: EnterpriseStandard): Promise<Response>;
2369
- declare function callback(request: Request, es?: EnterpriseStandard): Promise<Response>;
2370
- declare function handler(request: Request, es?: EnterpriseStandard): Promise<Response>;
2371
-
2372
- /**
2373
- * Enterprise user with SCIM attributes.
2374
- * Extends BaseUser (simple fields) with optional complex SCIM fields.
2375
- * For IAM/provisioning and enterprise directory integration.
2376
- */
2377
- interface EnterpriseUser extends BaseUser {
2378
- /**
2379
- * External identifier from the provisioning system
2380
- */
2381
- externalId?: string;
2382
- /**
2383
- * Resource metadata
2384
- */
2385
- meta?: {
2386
- resourceType?: string;
2387
- created?: string;
2388
- lastModified?: string;
2389
- version?: string;
2390
- location?: string;
2391
- };
2392
- /**
2393
- * SCIM schemas supported by this user
2394
- */
2395
- schemas?: string[];
2396
- /**
2397
- * Structured name with family/given names, prefixes, suffixes.
2398
- * Use alongside the simple `name` string from BaseUser.
2399
- */
2400
- fullName?: Name;
2401
- /**
2402
- * Multiple email addresses with types (work, home, etc.).
2403
- * Use alongside the simple `email` string from BaseUser.
2404
- */
2405
- emails?: Email[];
2406
- /**
2407
- * Name for display purposes
2408
- */
2409
- displayName?: string;
2410
- /**
2411
- * Casual name to address the user
2412
- */
2413
- nickName?: string;
2414
- /**
2415
- * URL to user's online profile
2416
- */
2417
- profileUrl?: string;
2418
- /**
2419
- * Job title
2420
- */
2421
- title?: string;
2422
- /**
2423
- * User type (e.g., "Employee", "Contractor")
2424
- */
2425
- userType?: string;
2426
- /**
2427
- * Preferred language (e.g., "en-US")
2428
- */
2429
- preferredLanguage?: string;
2430
- /**
2431
- * Locale for localization (e.g., "en-US")
2432
- */
2433
- locale?: string;
2434
- /**
2435
- * Timezone (e.g., "America/New_York")
2436
- */
2437
- timezone?: string;
2438
- /**
2439
- * Whether the user account is active
2440
- */
2441
- active?: boolean;
2442
- /**
2443
- * Password (for provisioning only, should not be returned)
2444
- */
2445
- password?: string;
2446
- /**
2447
- * Phone numbers
2448
- */
2449
- phoneNumbers?: PhoneNumber[];
2450
- /**
2451
- * Instant messaging addresses
2452
- */
2453
- ims?: Array<{
2454
- value: string;
2455
- display?: string;
2456
- type?: string;
2457
- primary?: boolean;
2458
- }>;
2459
- /**
2460
- * Photo URLs
2461
- */
2462
- photos?: Array<{
2463
- value: string;
2464
- display?: string;
2465
- type?: string;
2466
- primary?: boolean;
2467
- }>;
2468
- /**
2469
- * Physical mailing addresses
2470
- */
2471
- addresses?: Address[];
2472
- /**
2473
- * Groups the user belongs to
2474
- */
2475
- groups?: Group[];
2476
- /**
2477
- * Entitlements
2478
- */
2479
- entitlements?: Array<{
2480
- value: string;
2481
- display?: string;
2482
- type?: string;
2483
- primary?: boolean;
2484
- }>;
2485
- /**
2486
- * Roles assigned to the user
2487
- */
2488
- roles?: Role[];
2489
- /**
2490
- * X.509 certificates
2491
- */
2492
- x509Certificates?: Array<{
2493
- value: string;
2494
- display?: string;
2495
- type?: string;
2496
- primary?: boolean;
2497
- }>;
2498
- /**
2499
- * Employee number
2500
- */
2501
- employeeNumber?: string;
2502
- /**
2503
- * Cost center
2504
- */
2505
- costCenter?: string;
2506
- /**
2507
- * Organization name
2508
- */
2509
- organization?: string;
2510
- /**
2511
- * Division name
2512
- */
2513
- division?: string;
2514
- /**
2515
- * Department name
2516
- */
2517
- department?: string;
2518
- /**
2519
- * User's manager
2520
- */
2521
- manager?: {
2522
- value: string;
2523
- $ref?: string;
2524
- displayName?: string;
2525
- };
2526
- }
2527
-
1
+ import { EnterpriseStandard, ESValidators, CreateGroupOptions, CreateUserOptions, GroupsInboundHandlerConfig, IAM, IAMConfig, IAMGroupsInbound, IAMGroupsOutbound, IAMHandlerConfig, IAMUsersInbound, IAMValidators, ScimError, ScimListResponse, ScimResult, UsersInboundHandlerConfig, SessionStore, SSO, SSOConfig, SSOHandlerConfig, SSOValidators, CreateTenantRequest, CreateTenantResponse, EnvironmentType, StoredTenant, Tenant, TenantConfig, TenantStatus, TenantStore, TenantValidators, TenantWebhookPayload, BaseUser, EnterpriseUser, IdTokenClaims, OidcCallbackParams, TokenResponse, User as User2, Address, Email, EnterpriseExtension, Group, GroupMember, GroupResource, Name, PhoneNumber, Role, User as User3, X509Certificate, ClientCredentialsWorkloadConfig, JwtBearerWorkloadConfig, ServerOnlyWorkloadConfig, Workload, WorkloadConfig, WorkloadIdentity, WorkloadValidators, JWTAssertionClaims, TokenValidationResult, WorkloadTokenResponse, GroupStore, StoredGroup, StoredUser, UserStore, CachedWorkloadToken, WorkloadTokenStore, Vault } from "@enterprisestandard/core";
2
+ import { PropsWithChildren } from "react";
2528
3
  declare function SignInLoading({ complete, children }: {
2529
- complete?: boolean;
2530
- } & PropsWithChildren): react_jsx_runtime.JSX.Element | null;
2531
-
2532
- declare function SignedIn({ children }: PropsWithChildren): react_jsx_runtime.JSX.Element | null;
2533
-
2534
- declare function SignedOut({ children }: PropsWithChildren): react_jsx_runtime.JSX.Element | null;
2535
-
2536
- type StorageType = 'local' | 'session' | 'memory';
4
+ complete?: boolean;
5
+ } & PropsWithChildren): React.ReactNode;
6
+ import { PropsWithChildren as PropsWithChildren2 } from "react";
7
+ declare function SignedIn({ children }: PropsWithChildren2): React.ReactNode;
8
+ import { PropsWithChildren as PropsWithChildren3 } from "react";
9
+ declare function SignedOut({ children }: PropsWithChildren3): React.ReactNode;
10
+ import { ReactNode as ReactNode2 } from "react";
11
+ import { User } from "@enterprisestandard/core";
12
+ type StorageType = "local" | "session" | "memory";
2537
13
  interface SSOProviderProps {
2538
- tenantId?: string;
2539
- storage?: StorageType;
2540
- storageKey?: string;
2541
- userUrl?: string;
2542
- tokenUrl?: string;
2543
- refreshUrl?: string;
2544
- disableListener?: boolean;
2545
- children: ReactNode;
14
+ tenantId?: string;
15
+ storage?: StorageType;
16
+ storageKey?: string;
17
+ userUrl?: string;
18
+ tokenUrl?: string;
19
+ refreshUrl?: string;
20
+ disableListener?: boolean;
21
+ children: ReactNode2;
2546
22
  }
2547
23
  interface SSOContext {
2548
- user: User | null;
2549
- setUser: (user: User | null) => void;
2550
- isLoading: boolean;
2551
- tokenUrl?: string;
2552
- refreshUrl?: string;
24
+ user: User | null;
25
+ setUser: (user: User | null) => void;
26
+ isLoading: boolean;
27
+ tokenUrl?: string;
28
+ refreshUrl?: string;
2553
29
  }
2554
- declare function SSOProvider({ tenantId, storage, storageKey, userUrl, tokenUrl, refreshUrl, disableListener, children, }: SSOProviderProps): react_jsx_runtime.JSX.Element;
30
+ declare function SSOProvider({ tenantId, storage, storageKey, userUrl, tokenUrl, refreshUrl, disableListener, children }: SSOProviderProps): React.ReactNode2;
2555
31
  declare function useUser(): SSOContext;
2556
32
  interface UseTokenReturn {
2557
- token: string | null;
2558
- isLoading: boolean;
2559
- error: Error | null;
2560
- refresh: () => Promise<void>;
33
+ token: string | null;
34
+ isLoading: boolean;
35
+ error: Error | null;
36
+ refresh: () => Promise<void>;
2561
37
  }
2562
38
  declare function useToken(): UseTokenReturn;
2563
39
  declare function logout(logoutUrl: string): Promise<{
2564
- success: boolean;
2565
- error?: string;
40
+ success: boolean;
41
+ error?: string;
2566
42
  }>;
2567
-
2568
- declare function getDefaultInstance(): EnterpriseStandard | undefined;
2569
-
2570
- type EnterpriseStandard = ESConfig & {
2571
- defaultInstance: boolean;
2572
- vault: Vault;
2573
- sso: SSO;
2574
- iam: IAM;
2575
- workload: Workload;
2576
- };
2577
- type ESConfig = {
2578
- defaultInstance?: boolean;
2579
- sso?: SSOConfig;
2580
- iam?: IAMConfig;
2581
- workload?: WorkloadConfig;
2582
- validation?: {
2583
- sso?: SSOHandlerConfig['validation'];
2584
- workload?: WorkloadConfig['validation'];
2585
- } | SSOHandlerConfig['validation'] | WorkloadConfig['validation'];
2586
- };
2587
- declare function enterpriseStandard(appId?: string, initConfig?: ESConfig): Promise<EnterpriseStandard>;
2588
-
2589
- export { type Address, type BaseUser, type CachedWorkloadToken, type ClientCredentialsWorkloadConfig, type CreateGroupOptions, type CreateTenantRequest, type CreateTenantResponse, type CreateUserOptions, type Email, type EnterpriseExtension, type EnterpriseStandard, type EnterpriseUser, type EnvironmentType, type Group, type GroupMember, type GroupResource, type GroupStore, type GroupsInboundHandlerConfig, type IAM, type IAMConfig, type IAMGroupsInbound, type IAMGroupsOutbound, type IAMHandlerConfig, type IAMUsersInbound, type IdTokenClaims, InMemoryGroupStore, InMemorySessionStore, InMemoryTenantStore, InMemoryUserStore, InMemoryWorkloadTokenStore, type JWTAssertionClaims, type JwtBearerWorkloadConfig, type Name, type OidcCallbackParams, type PhoneNumber, type Role, type SSO, type SSOConfig, type SSOHandlerConfig, SSOProvider, type ScimError, type ScimListResponse, type ScimResult, type User$1 as ScimUser, type ServerOnlyWorkloadConfig, type SessionStore, SignInLoading, SignedIn, SignedOut, StandardSchemaV1, type StoredGroup, type StoredTenant, type StoredUser, TenantRequestError, type TenantStatus, type TenantStore, type TenantWebhookPayload, type TokenResponse, type TokenValidationResult, type User, type UserStore, type UsersInboundHandlerConfig, type Vault, type Workload, type WorkloadConfig, type WorkloadIdentity, type WorkloadTokenResponse, type WorkloadTokenStore, type X509Certificate, callback, enterpriseStandard, getDefaultInstance, getRequiredUser, getUser, getWorkload, getWorkloadToken, groupResourceSchema, handler, iam, idTokenClaimsSchema, initiateLogin, jwtAssertionClaimsSchema, logout, oidcCallbackSchema, parseTenantRequest, revokeWorkloadToken, sendTenantWebhook, serializeESConfig, sso, tokenResponseSchema, useToken, useUser, userSchema, validateWorkloadToken, vault, workload, workloadHandler, workloadTokenResponseSchema };
43
+ export { useUser, useToken, logout, X509Certificate, WorkloadValidators, WorkloadTokenStore, WorkloadTokenResponse, WorkloadIdentity, WorkloadConfig, Workload, Vault, UsersInboundHandlerConfig, UserStore, User2 as User, TokenValidationResult, TokenResponse, TenantWebhookPayload, TenantValidators, TenantStore, TenantStatus, TenantConfig, Tenant, StoredUser, StoredTenant, StoredGroup, SignedOut, SignedIn, SignInLoading, SessionStore, ServerOnlyWorkloadConfig, User3 as ScimUser, ScimResult, ScimListResponse, ScimError, SSOValidators, SSOProvider, SSOHandlerConfig, SSOConfig, SSO, Role, PhoneNumber, OidcCallbackParams, Name, JwtBearerWorkloadConfig, JWTAssertionClaims, IdTokenClaims, IAMValidators, IAMUsersInbound, IAMHandlerConfig, IAMGroupsOutbound, IAMGroupsInbound, IAMConfig, IAM, GroupsInboundHandlerConfig, GroupStore, GroupResource, GroupMember, Group, EnvironmentType, EnterpriseUser, EnterpriseStandard, EnterpriseExtension, Email, ESValidators, CreateUserOptions, CreateTenantResponse, CreateTenantRequest, CreateGroupOptions, ClientCredentialsWorkloadConfig, CachedWorkloadToken, BaseUser, Address };