@enterprisestandard/react 0.0.4 → 0.0.5-beta.20260114.1

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/dist/group-store.d.ts +164 -0
  2. package/dist/group-store.d.ts.map +1 -0
  3. package/dist/iam.d.ts +205 -12
  4. package/dist/iam.d.ts.map +1 -1
  5. package/dist/index.d.ts +44 -11
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +3164 -572
  8. package/dist/index.js.map +29 -0
  9. package/dist/server.d.ts +6 -4
  10. package/dist/server.d.ts.map +1 -1
  11. package/dist/session-store.d.ts +179 -0
  12. package/dist/session-store.d.ts.map +1 -0
  13. package/dist/sso.d.ts +74 -16
  14. package/dist/sso.d.ts.map +1 -1
  15. package/dist/tenant-server.d.ts +8 -0
  16. package/dist/tenant-server.d.ts.map +1 -0
  17. package/dist/tenant.d.ts +280 -0
  18. package/dist/tenant.d.ts.map +1 -0
  19. package/dist/types/base-user.d.ts +27 -0
  20. package/dist/types/base-user.d.ts.map +1 -0
  21. package/dist/types/enterprise-user.d.ts +158 -0
  22. package/dist/types/enterprise-user.d.ts.map +1 -0
  23. package/dist/{oidc-schema.d.ts → types/oidc-schema.d.ts} +42 -0
  24. package/dist/types/oidc-schema.d.ts.map +1 -0
  25. package/dist/types/scim-schema.d.ts +419 -0
  26. package/dist/types/scim-schema.d.ts.map +1 -0
  27. package/dist/types/standard-schema.d.ts.map +1 -0
  28. package/dist/types/user.d.ts +41 -0
  29. package/dist/types/user.d.ts.map +1 -0
  30. package/dist/types/workload-schema.d.ts +106 -0
  31. package/dist/types/workload-schema.d.ts.map +1 -0
  32. package/dist/ui/sso-provider.d.ts +3 -3
  33. package/dist/ui/sso-provider.d.ts.map +1 -1
  34. package/dist/user-store.d.ts +161 -0
  35. package/dist/user-store.d.ts.map +1 -0
  36. package/dist/workload-server.d.ts +126 -0
  37. package/dist/workload-server.d.ts.map +1 -0
  38. package/dist/workload-token-store.d.ts +187 -0
  39. package/dist/workload-token-store.d.ts.map +1 -0
  40. package/dist/workload.d.ts +227 -0
  41. package/dist/workload.d.ts.map +1 -0
  42. package/package.json +2 -5
  43. package/dist/enterprise-user.d.ts +0 -125
  44. package/dist/enterprise-user.d.ts.map +0 -1
  45. package/dist/oidc-schema.d.ts.map +0 -1
  46. package/dist/standard-schema.d.ts.map +0 -1
  47. /package/dist/{standard-schema.d.ts → types/standard-schema.d.ts} +0 -0
@@ -0,0 +1,106 @@
1
+ import type { StandardSchemaV1 } from './standard-schema';
2
+ /**
3
+ * JWT Assertion Claims for OAuth2 JWT Bearer Grant (RFC 7523) and OAuth2 Access Tokens
4
+ * @see https://datatracker.ietf.org/doc/html/rfc7523
5
+ * @see https://datatracker.ietf.org/doc/html/rfc9068
6
+ */
7
+ export interface JWTAssertionClaims {
8
+ /**
9
+ * REQUIRED. Issuer - the workload identity (e.g., SPIFFE ID) or authorization server
10
+ */
11
+ iss: string;
12
+ /**
13
+ * REQUIRED. Subject - the workload identity or service account
14
+ */
15
+ sub: string;
16
+ /**
17
+ * OPTIONAL. Audience - may be a string or array of strings
18
+ * Note: Required for JWT assertions, but may be absent in OAuth2 access tokens
19
+ */
20
+ aud?: string | string[];
21
+ /**
22
+ * REQUIRED. Expiration time (Unix timestamp)
23
+ */
24
+ exp: number;
25
+ /**
26
+ * REQUIRED. Issued at time (Unix timestamp)
27
+ */
28
+ iat: number;
29
+ /**
30
+ * OPTIONAL. JWT ID - unique identifier for this token
31
+ * Note: Required for JWT assertions, optional for access tokens
32
+ */
33
+ jti?: string;
34
+ /**
35
+ * OPTIONAL. Requested OAuth scopes (space-delimited)
36
+ */
37
+ scope?: string;
38
+ /**
39
+ * Allow additional claims for extensibility
40
+ */
41
+ [key: string]: unknown;
42
+ }
43
+ /**
44
+ * Creates a StandardSchemaV1 for validating JWT Assertion Claims.
45
+ * @param vendor - The name of the vendor creating this schema
46
+ * @returns A StandardSchemaV1 instance for JWT Assertion Claims validation
47
+ */
48
+ export declare function jwtAssertionClaimsSchema(vendor: string): StandardSchemaV1<Record<string, unknown>, JWTAssertionClaims>;
49
+ /**
50
+ * Workload Token Response from OAuth2 token endpoint
51
+ * @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.1
52
+ */
53
+ export interface WorkloadTokenResponse {
54
+ /**
55
+ * REQUIRED. The access token issued by the authorization server.
56
+ */
57
+ access_token: string;
58
+ /**
59
+ * REQUIRED. The type of the token (typically "Bearer").
60
+ */
61
+ token_type: string;
62
+ /**
63
+ * RECOMMENDED. The lifetime in seconds of the access token.
64
+ */
65
+ expires_in?: number;
66
+ /**
67
+ * OPTIONAL. The scope of the access token.
68
+ */
69
+ scope?: string;
70
+ /**
71
+ * OPTIONAL. The refresh token (rarely used for workload identities).
72
+ */
73
+ refresh_token?: string;
74
+ /**
75
+ * OPTIONAL. The expiration time as an ISO 8601 string.
76
+ */
77
+ expires?: string;
78
+ }
79
+ /**
80
+ * Creates a StandardSchemaV1 for validating Workload Token Responses.
81
+ * @param vendor - The name of the vendor creating this schema
82
+ * @returns A StandardSchemaV1 instance for Workload Token Response validation
83
+ */
84
+ export declare function workloadTokenResponseSchema(vendor: string): StandardSchemaV1<Record<string, unknown>, WorkloadTokenResponse>;
85
+ /**
86
+ * Token Validation Result
87
+ */
88
+ export interface TokenValidationResult {
89
+ /**
90
+ * Whether the token is valid
91
+ */
92
+ valid: boolean;
93
+ /**
94
+ * The decoded and validated claims (if valid)
95
+ */
96
+ claims?: JWTAssertionClaims;
97
+ /**
98
+ * Error message (if invalid)
99
+ */
100
+ error?: string;
101
+ /**
102
+ * Token expiration time (if valid)
103
+ */
104
+ expiresAt?: Date;
105
+ }
106
+ //# sourceMappingURL=workload-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workload-schema.d.ts","sourceRoot":"","sources":["../../src/types/workload-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,GACb,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,CAAC,CA6F/D;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,GACb,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,CAAC,CA4GlE;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAE5B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB"}
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from 'react';
2
- import type { EnterpriseUser } from '../enterprise-user';
2
+ import type { User } from '../types/user';
3
3
  type StorageType = 'local' | 'session' | 'memory';
4
4
  interface SSOProviderProps {
5
5
  tenantId?: string;
@@ -12,8 +12,8 @@ interface SSOProviderProps {
12
12
  children: ReactNode;
13
13
  }
14
14
  interface SSOContext {
15
- user: EnterpriseUser | null;
16
- setUser: (user: EnterpriseUser | null) => void;
15
+ user: User | null;
16
+ setUser: (user: User | null) => void;
17
17
  isLoading: boolean;
18
18
  tokenUrl?: string;
19
19
  refreshUrl?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"sso-provider.d.ts","sourceRoot":"","sources":["../../src/ui/sso-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAgD,MAAM,OAAO,CAAC;AACpG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,KAAK,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElD,UAAU,gBAAgB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAWD,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAkB,EAClB,UAAU,EACV,OAAO,EACP,QAAQ,EACR,UAAU,EACV,eAAuB,EACvB,QAAQ,GACT,EAAE,gBAAgB,2CA8JlB;AAED,wBAAgB,OAAO,IAAI,UAAU,CAMpC;AAOD,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAgB,QAAQ,IAAI,cAAc,CAiGzC;AAED,wBAAsB,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6C7F"}
1
+ {"version":3,"file":"sso-provider.d.ts","sourceRoot":"","sources":["../../src/ui/sso-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAgD,MAAM,OAAO,CAAC;AACpG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,KAAK,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElD,UAAU,gBAAgB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAWD,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAkB,EAClB,UAAU,EACV,OAAO,EACP,QAAQ,EACR,UAAU,EACV,eAAuB,EACvB,QAAQ,GACT,EAAE,gBAAgB,2CA8JlB;AAED,wBAAgB,OAAO,IAAI,UAAU,CAMpC;AAOD,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAgB,QAAQ,IAAI,cAAc,CAiGzC;AAED,wBAAsB,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6C7F"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * User storage for persisting user profiles from SSO authentication.
3
+ *
4
+ * User stores are optional - the package works with JWT cookies alone.
5
+ * User stores are useful when you want to:
6
+ * - Cache user profiles for fast lookup
7
+ * - Store users close to your application (in-memory, Redis, etc.)
8
+ * - Avoid custom IAM/SCIM integration for simple use cases
9
+ *
10
+ * ## When to Use UserStore vs IAM
11
+ *
12
+ * **Use UserStore when:**
13
+ * - You just need fast user lookups without external systems
14
+ * - Users are managed by an external IdP and you just cache them locally
15
+ * - You want simple in-memory or Redis storage
16
+ *
17
+ * **Use IAM (SCIM) when:**
18
+ * - You need to provision users to an external identity provider
19
+ * - You need custom user attributes beyond what SSO provides
20
+ * - You need to sync users with enterprise directories
21
+ *
22
+ * ## Example Usage
23
+ *
24
+ * ```typescript
25
+ * import { sso, InMemoryUserStore } from '@enterprisestandard/react/server';
26
+ *
27
+ * const userStore = new InMemoryUserStore();
28
+ *
29
+ * const auth = sso({
30
+ * // ... other config
31
+ * user_store: userStore,
32
+ * });
33
+ *
34
+ * // Later, look up users
35
+ * const user = await userStore.get('user-sub-id');
36
+ * const userByEmail = await userStore.getByEmail('user@example.com');
37
+ * ```
38
+ */
39
+ import type { User } from './types/user';
40
+ /**
41
+ * Stored user data with required id and tracking metadata.
42
+ *
43
+ * Extends the SSO User type with:
44
+ * - Required `id` (the `sub` claim from the IdP)
45
+ * - Timestamps for tracking when users were first seen and last updated
46
+ * - Optional custom extended data
47
+ *
48
+ * @template TExtended - Type-safe custom data that consumers can add to users
49
+ */
50
+ export type StoredUser<TExtended = {}> = User & {
51
+ /**
52
+ * Required unique identifier (the `sub` claim from the IdP).
53
+ * This is the primary key for user storage.
54
+ */
55
+ id: string;
56
+ /**
57
+ * Timestamp when the user was first stored.
58
+ */
59
+ createdAt: Date;
60
+ /**
61
+ * Timestamp when the user was last updated (e.g., on re-login).
62
+ */
63
+ updatedAt: Date;
64
+ } & TExtended;
65
+ /**
66
+ * Abstract interface for user storage backends.
67
+ *
68
+ * Consumers can implement this interface to use different storage backends:
69
+ * - In-memory (for development/testing)
70
+ * - Redis (for production with fast lookups)
71
+ * - Database (PostgreSQL, MySQL, etc.)
72
+ *
73
+ * @template TExtended - Type-safe custom data that consumers can add to users
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * // Custom user data
78
+ * type MyUserData = {
79
+ * department: string;
80
+ * roles: string[];
81
+ * };
82
+ *
83
+ * // Implement custom store
84
+ * class RedisUserStore implements UserStore<MyUserData> {
85
+ * async get(sub: string): Promise<StoredUser<MyUserData> | null> {
86
+ * const data = await redis.get(`user:${sub}`);
87
+ * return data ? JSON.parse(data) : null;
88
+ * }
89
+ * // ... other methods
90
+ * }
91
+ * ```
92
+ */
93
+ export interface UserStore<TExtended = {}> {
94
+ /**
95
+ * Retrieve a user by their subject identifier (sub).
96
+ *
97
+ * @param sub - The user's unique identifier from the IdP
98
+ * @returns The user if found, null otherwise
99
+ */
100
+ get(sub: string): Promise<StoredUser<TExtended> | null>;
101
+ /**
102
+ * Retrieve a user by their email address.
103
+ *
104
+ * @param email - The user's email address
105
+ * @returns The user if found, null otherwise
106
+ */
107
+ getByEmail(email: string): Promise<StoredUser<TExtended> | null>;
108
+ /**
109
+ * Retrieve a user by their username.
110
+ *
111
+ * @param userName - The user's username
112
+ * @returns The user if found, null otherwise
113
+ */
114
+ getByUserName(userName: string): Promise<StoredUser<TExtended> | null>;
115
+ /**
116
+ * Create or update a user in the store.
117
+ *
118
+ * If a user with the same `id` (sub) exists, it will be updated.
119
+ * Otherwise, a new user will be created.
120
+ *
121
+ * @param user - The user data to store
122
+ */
123
+ upsert(user: StoredUser<TExtended>): Promise<void>;
124
+ /**
125
+ * Delete a user by their subject identifier (sub).
126
+ *
127
+ * @param sub - The user's unique identifier to delete
128
+ */
129
+ delete(sub: string): Promise<void>;
130
+ }
131
+ /**
132
+ * In-memory user store implementation using Maps.
133
+ *
134
+ * Suitable for:
135
+ * - Development and testing
136
+ * - Single-server deployments
137
+ * - Applications without high availability requirements
138
+ *
139
+ * NOT suitable for:
140
+ * - Multi-server deployments (users not shared)
141
+ * - High availability scenarios (users lost on restart)
142
+ * - Production applications with distributed architecture
143
+ *
144
+ * For production, implement UserStore with Redis or a database.
145
+ *
146
+ * @template TExtended - Type-safe custom data that consumers can add to users
147
+ */
148
+ export declare class InMemoryUserStore<TExtended = {}> implements UserStore<TExtended> {
149
+ /** Primary storage: sub -> user */
150
+ private users;
151
+ /** Secondary index: email -> sub */
152
+ private emailIndex;
153
+ /** Secondary index: userName -> sub */
154
+ private userNameIndex;
155
+ get(sub: string): Promise<StoredUser<TExtended> | null>;
156
+ getByEmail(email: string): Promise<StoredUser<TExtended> | null>;
157
+ getByUserName(userName: string): Promise<StoredUser<TExtended> | null>;
158
+ upsert(user: StoredUser<TExtended>): Promise<void>;
159
+ delete(sub: string): Promise<void>;
160
+ }
161
+ //# sourceMappingURL=user-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-store.d.ts","sourceRoot":"","sources":["../src/user-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,CAAC,SAAS,GAAG,EAAE,IAAI,IAAI,GAAG;IAC9C;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,SAAS,EAAE,IAAI,CAAC;IAEhB;;OAEG;IACH,SAAS,EAAE,IAAI,CAAC;CACjB,GAAG,SAAS,CAAC;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,SAAS,CAAC,SAAS,GAAG,EAAE;IACvC;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IAExD;;;;;OAKG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IAEjE;;;;;OAKG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IAEvE;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,iBAAiB,CAAC,SAAS,GAAG,EAAE,CAAE,YAAW,SAAS,CAAC,SAAS,CAAC;IAC5E,mCAAmC;IACnC,OAAO,CAAC,KAAK,CAA4C;IAEzD,oCAAoC;IACpC,OAAO,CAAC,UAAU,CAA6B;IAE/C,uCAAuC;IACvC,OAAO,CAAC,aAAa,CAA6B;IAE5C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAIvD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAMhE,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAMtE,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBlD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAazC"}
@@ -0,0 +1,126 @@
1
+ import type { TokenValidationResult } from './types/workload-schema';
2
+ import type { ESConfig, WorkloadIdentity } from './workload';
3
+ /**
4
+ * Get the workload identity from an incoming request.
5
+ * Returns undefined if no valid workload token is present.
6
+ *
7
+ * @param request - Request with Authorization header
8
+ * @param config - Optional EnterpriseStandard configuration
9
+ * @returns WorkloadIdentity or undefined
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { getWorkload } from '@enterprisestandard/react';
14
+ *
15
+ * export async function handler(request: Request) {
16
+ * const workload = await getWorkload(request);
17
+ *
18
+ * if (!workload) {
19
+ * return new Response('Unauthorized', { status: 401 });
20
+ * }
21
+ *
22
+ * console.log('Request from workload:', workload.workload_id);
23
+ * // ... process authenticated request
24
+ * }
25
+ * ```
26
+ */
27
+ export declare function getWorkload(request: Request, config?: ESConfig): Promise<WorkloadIdentity | undefined>;
28
+ /**
29
+ * Get an access token for the configured workload identity.
30
+ *
31
+ * @param scope - Optional OAuth2 scopes (space-delimited)
32
+ * @param config - Optional EnterpriseStandard configuration
33
+ * @returns Access token string
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * import { getWorkloadToken } from '@enterprisestandard/react/server';
38
+ *
39
+ * // Get token for API calls
40
+ * const token = await getWorkloadToken('api:read api:write');
41
+ *
42
+ * // Use in outbound requests
43
+ * const response = await fetch('https://api.example.com/data', {
44
+ * headers: { 'Authorization': `Bearer ${token}` },
45
+ * });
46
+ * ```
47
+ */
48
+ export declare function getWorkloadToken(scope?: string, config?: ESConfig): Promise<string>;
49
+ /**
50
+ * Validate a workload token from an incoming request.
51
+ *
52
+ * @param request - Request with Authorization header
53
+ * @param config - Optional EnterpriseStandard configuration
54
+ * @returns Token validation result
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * import { validateWorkloadToken } from '@enterprisestandard/react/server';
59
+ *
60
+ * export async function handler(request: Request) {
61
+ * const result = await validateWorkloadToken(request);
62
+ *
63
+ * if (!result.valid) {
64
+ * return new Response(
65
+ * JSON.stringify({ error: result.error }),
66
+ * { status: 401 }
67
+ * );
68
+ * }
69
+ *
70
+ * const workloadId = result.claims?.iss;
71
+ * // ... process authenticated request
72
+ * }
73
+ * ```
74
+ */
75
+ export declare function validateWorkloadToken(request: Request, config?: ESConfig): Promise<TokenValidationResult>;
76
+ /**
77
+ * Revoke a workload access token.
78
+ *
79
+ * @param token - The access token to revoke
80
+ * @param config - Optional EnterpriseStandard configuration
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * import { revokeWorkloadToken } from '@enterprisestandard/react/server';
85
+ *
86
+ * // Revoke token when workload is decommissioned
87
+ * await revokeWorkloadToken(accessToken);
88
+ * ```
89
+ */
90
+ export declare function revokeWorkloadToken(token: string, config?: ESConfig): Promise<void>;
91
+ /**
92
+ * Framework-agnostic handler for workload authentication routes.
93
+ *
94
+ * The handler reads configuration (handler URLs, validation) directly from the
95
+ * EnterpriseStandard instance, so no config parameter is needed.
96
+ *
97
+ * @param request - Incoming request
98
+ * @param config - Optional ESConfig to specify which EnterpriseStandard instance to use
99
+ * @returns Response
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * import { workloadHandler } from '@enterprisestandard/react/server';
104
+ *
105
+ * // TanStack Start example
106
+ * export const Route = createFileRoute('/api/workload/$')({
107
+ * server: {
108
+ * handlers: ({ createHandlers }) =>
109
+ * createHandlers({
110
+ * GET: {
111
+ * handler: async ({ request }) => {
112
+ * return workloadHandler(request);
113
+ * },
114
+ * },
115
+ * POST: {
116
+ * handler: async ({ request }) => {
117
+ * return workloadHandler(request);
118
+ * },
119
+ * },
120
+ * }),
121
+ * },
122
+ * });
123
+ * ```
124
+ */
125
+ export declare function workloadHandler(request: Request, config?: ESConfig): Promise<Response>;
126
+ //# sourceMappingURL=workload-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workload-server.d.ts","sourceRoot":"","sources":["../src/workload-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAErE,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAmB7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAM5G;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAIzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAa/G;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAIzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAI5F"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Token caching for workload identity authentication.
3
+ *
4
+ * Token stores are optional but recommended for performance - they enable:
5
+ * - Token caching to avoid repeated token acquisition
6
+ * - Automatic token refresh before expiration
7
+ * - Reduced load on authorization servers
8
+ *
9
+ * ## Token Caching Strategy
10
+ *
11
+ * Unlike session stores for user authentication, workload token stores cache
12
+ * short-lived access tokens (typically 5 minutes) for service-to-service calls.
13
+ *
14
+ * **Default Behavior:**
15
+ * - Tokens cached with 5-minute TTL
16
+ * - Auto-refresh 60 seconds before expiration
17
+ * - Expired tokens automatically removed
18
+ *
19
+ * ## Performance Characteristics
20
+ *
21
+ * | Backend | Lookup Time | Use Case |
22
+ * |--------------|-------------|----------------------------|
23
+ * | InMemory | <0.00005ms | Single-server deployments |
24
+ * | Redis | 1-2ms | Multi-server deployments |
25
+ * | Database | 5-20ms | Persistent token storage |
26
+ *
27
+ * ## Example Usage
28
+ *
29
+ * ```typescript
30
+ * import { workload, InMemoryWorkloadTokenStore } from '@enterprisestandard/react/server';
31
+ *
32
+ * // With token caching
33
+ * const workloadAuth = workload({
34
+ * // ... other config
35
+ * token_store: new InMemoryWorkloadTokenStore(),
36
+ * auto_refresh: true, // Refresh before expiry
37
+ * });
38
+ *
39
+ * // Without token caching (fetch new token each time)
40
+ * const workloadAuth = workload({
41
+ * // ... config without token_store
42
+ * });
43
+ * ```
44
+ */
45
+ /**
46
+ * Cached workload token data.
47
+ *
48
+ * @template TExtended - Type-safe custom data that consumers can add to cached tokens
49
+ */
50
+ export type CachedWorkloadToken<TExtended = object> = {
51
+ /**
52
+ * Workload identifier (typically SPIFFE ID).
53
+ * Used as the primary key for token lookup.
54
+ */
55
+ workload_id: string;
56
+ /**
57
+ * OAuth2 access token (Bearer token)
58
+ */
59
+ access_token: string;
60
+ /**
61
+ * Token type (always "Bearer" for OAuth2)
62
+ */
63
+ token_type: string;
64
+ /**
65
+ * OAuth2 scopes granted for this token
66
+ */
67
+ scope?: string;
68
+ /**
69
+ * Timestamp when the token expires.
70
+ * Used for automatic cleanup and refresh logic.
71
+ */
72
+ expires_at: Date;
73
+ /**
74
+ * Timestamp when the token was created/cached.
75
+ */
76
+ created_at: Date;
77
+ /**
78
+ * Optional refresh token (rarely used for workload identities)
79
+ */
80
+ refresh_token?: string;
81
+ } & TExtended;
82
+ /**
83
+ * Abstract interface for workload token storage backends.
84
+ *
85
+ * Consumers can implement this interface to use different storage backends:
86
+ * - Redis (recommended for multi-server deployments)
87
+ * - Database (PostgreSQL, MySQL, etc. for persistence)
88
+ * - Distributed cache (Memcached, etc.)
89
+ * - Custom solutions
90
+ *
91
+ * @template TExtended - Type-safe custom data that consumers can add to cached tokens
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * // Custom token cache data
96
+ * type MyTokenData = {
97
+ * environment: string;
98
+ * region: string;
99
+ * };
100
+ *
101
+ * // Implement custom store with Redis
102
+ * class RedisWorkloadTokenStore implements WorkloadTokenStore<MyTokenData> {
103
+ * async set(token: CachedWorkloadToken<MyTokenData>): Promise<void> {
104
+ * const ttl = Math.floor((token.expires_at.getTime() - Date.now()) / 1000);
105
+ * await redis.setex(
106
+ * `workload:token:${token.workload_id}`,
107
+ * ttl,
108
+ * JSON.stringify(token)
109
+ * );
110
+ * }
111
+ *
112
+ * async get(workload_id: string): Promise<CachedWorkloadToken<MyTokenData> | null> {
113
+ * const data = await redis.get(`workload:token:${workload_id}`);
114
+ * if (!data) return null;
115
+ * const token = JSON.parse(data);
116
+ * // Convert date strings back to Date objects
117
+ * token.expires_at = new Date(token.expires_at);
118
+ * token.created_at = new Date(token.created_at);
119
+ * return token;
120
+ * }
121
+ *
122
+ * // ... other methods
123
+ * }
124
+ * ```
125
+ */
126
+ export interface WorkloadTokenStore<TExtended = object> {
127
+ /**
128
+ * Store or update a workload token in the cache.
129
+ *
130
+ * @param token - The token data to cache
131
+ */
132
+ set(token: CachedWorkloadToken<TExtended>): Promise<void>;
133
+ /**
134
+ * Retrieve a cached token by workload ID.
135
+ *
136
+ * @param workload_id - The workload identifier (e.g., SPIFFE ID)
137
+ * @returns The cached token if found and not expired, null otherwise
138
+ */
139
+ get(workload_id: string): Promise<CachedWorkloadToken<TExtended> | null>;
140
+ /**
141
+ * Delete a cached token by workload ID.
142
+ *
143
+ * Used when explicitly revoking tokens or clearing cache.
144
+ *
145
+ * @param workload_id - The workload identifier to remove
146
+ */
147
+ delete(workload_id: string): Promise<void>;
148
+ /**
149
+ * Check if a valid (non-expired) token exists for a workload.
150
+ *
151
+ * @param workload_id - The workload identifier to check
152
+ * @returns true if a valid token exists, false otherwise
153
+ */
154
+ isValid(workload_id: string): Promise<boolean>;
155
+ /**
156
+ * Remove all expired tokens from the cache.
157
+ *
158
+ * Should be called periodically to prevent memory leaks.
159
+ */
160
+ cleanup(): Promise<void>;
161
+ }
162
+ /**
163
+ * In-memory workload token store implementation using Maps.
164
+ *
165
+ * Suitable for:
166
+ * - Development and testing
167
+ * - Single-server deployments
168
+ * - Applications without high availability requirements
169
+ *
170
+ * NOT suitable for:
171
+ * - Multi-server deployments (tokens not shared across instances)
172
+ * - High availability scenarios (tokens lost on restart)
173
+ * - Production applications with distributed architecture
174
+ *
175
+ * For production multi-server deployments, implement WorkloadTokenStore with Redis.
176
+ *
177
+ * @template TExtended - Type-safe custom data that consumers can add to cached tokens
178
+ */
179
+ export declare class InMemoryWorkloadTokenStore<TExtended = object> implements WorkloadTokenStore<TExtended> {
180
+ private tokens;
181
+ set(token: CachedWorkloadToken<TExtended>): Promise<void>;
182
+ get(workload_id: string): Promise<CachedWorkloadToken<TExtended> | null>;
183
+ delete(workload_id: string): Promise<void>;
184
+ isValid(workload_id: string): Promise<boolean>;
185
+ cleanup(): Promise<void>;
186
+ }
187
+ //# sourceMappingURL=workload-token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workload-token-store.d.ts","sourceRoot":"","sources":["../src/workload-token-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,CAAC,SAAS,GAAG,MAAM,IAAI;IACpD;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,UAAU,EAAE,IAAI,CAAC;IAEjB;;OAEG;IACH,UAAU,EAAE,IAAI,CAAC;IAEjB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,SAAS,CAAC;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,WAAW,kBAAkB,CAAC,SAAS,GAAG,MAAM;IACpD;;;;OAIG;IACH,GAAG,CAAC,KAAK,EAAE,mBAAmB,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D;;;;;OAKG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IAEzE;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3C;;;;;OAKG;IACH,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/C;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,0BAA0B,CAAC,SAAS,GAAG,MAAM,CAAE,YAAW,kBAAkB,CAAC,SAAS,CAAC;IAClG,OAAO,CAAC,MAAM,CAAqD;IAE7D,GAAG,CAAC,KAAK,EAAE,mBAAmB,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzD,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAaxE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK9C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ/B"}