@enterprisestandard/core 0.0.9-beta.20260304.1 → 0.0.9
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 +84 -20
- package/dist/index.js +1 -1
- package/dist/server.d.ts +43 -14
- package/dist/server.js +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -789,7 +789,7 @@ interface User2 extends BaseUser {
|
|
|
789
789
|
*
|
|
790
790
|
* @template TExtended - Type-safe custom data that consumers can add to users
|
|
791
791
|
*/
|
|
792
|
-
type StoredUser<TExtended =
|
|
792
|
+
type StoredUser<TExtended = object> = User2 & {
|
|
793
793
|
/**
|
|
794
794
|
* Required unique identifier (the `sub` claim from the IdP).
|
|
795
795
|
* This is the primary key for user storage.
|
|
@@ -832,7 +832,7 @@ type StoredUser<TExtended = {}> = User2 & {
|
|
|
832
832
|
* }
|
|
833
833
|
* ```
|
|
834
834
|
*/
|
|
835
|
-
interface UserStore<TExtended =
|
|
835
|
+
interface UserStore<TExtended = object> {
|
|
836
836
|
/**
|
|
837
837
|
* Retrieve a user by their subject identifier (sub).
|
|
838
838
|
*
|
|
@@ -1328,13 +1328,27 @@ type WorkloadConfigMap = Record<string, WorkloadConfig>;
|
|
|
1328
1328
|
/**
|
|
1329
1329
|
* Workload config with separate incoming (server) and outgoing (client) roles.
|
|
1330
1330
|
* - **incoming**: Server-only config for validating tokens presented to this app (jwksUri, issuer).
|
|
1331
|
-
* - **outgoing**: Map of named clients for outbound calls; use getWorkloadToken(client
|
|
1331
|
+
* - **outgoing**: Map of named clients for outbound calls; use getWorkloadToken(client, es, scope?) from server (client is required and must be one of the outgoing names; pass the ES instance).
|
|
1332
1332
|
*/
|
|
1333
1333
|
type WorkloadIncomingOutgoing = {
|
|
1334
1334
|
incoming?: Partial<WorkloadConfig>;
|
|
1335
1335
|
outgoing?: Record<string, Partial<WorkloadConfig>>;
|
|
1336
1336
|
};
|
|
1337
1337
|
/**
|
|
1338
|
+
* Framework-level workload declarations used by app code to define the expected
|
|
1339
|
+
* incoming/outgoing workload shape without needing all remote credentials in code.
|
|
1340
|
+
*/
|
|
1341
|
+
type FrameworkWorkloadIncomingOutgoing = {
|
|
1342
|
+
incoming?: Partial<WorkloadConfig>;
|
|
1343
|
+
outgoing?: Record<string, Partial<WorkloadConfig>>;
|
|
1344
|
+
};
|
|
1345
|
+
/**
|
|
1346
|
+
* Workload config shape accepted from framework/app code.
|
|
1347
|
+
* Apps may provide a partial single config or an incoming/outgoing declaration
|
|
1348
|
+
* to expose named outgoing clients in the type system.
|
|
1349
|
+
*/
|
|
1350
|
+
type FrameworkWorkloadConfig = Partial<WorkloadConfig> | FrameworkWorkloadIncomingOutgoing;
|
|
1351
|
+
/**
|
|
1338
1352
|
* Workload Identity extracted from validated tokens
|
|
1339
1353
|
*/
|
|
1340
1354
|
type WorkloadIdentity = {
|
|
@@ -1359,10 +1373,11 @@ type WorkloadIdentity = {
|
|
|
1359
1373
|
* Workload Identity Authentication Interface
|
|
1360
1374
|
*/
|
|
1361
1375
|
type Workload = WorkloadConfig & {
|
|
1362
|
-
/**
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1376
|
+
/**
|
|
1377
|
+
* Returns a token for this workload configuration.
|
|
1378
|
+
* The optional argument overrides the configured default scope.
|
|
1379
|
+
*/
|
|
1380
|
+
getToken: (scope?: string) => Promise<string>;
|
|
1366
1381
|
refreshToken: (scope?: string) => Promise<WorkloadTokenResponse>;
|
|
1367
1382
|
generateJWTAssertion: (scope?: string) => Promise<string>;
|
|
1368
1383
|
revokeToken: (token: string) => Promise<void>;
|
|
@@ -1372,6 +1387,7 @@ type Workload = WorkloadConfig & {
|
|
|
1372
1387
|
/** Framework-agnostic request handler for the Workload module (token, validate, jwks, refresh). */
|
|
1373
1388
|
handler: (request: Request) => Promise<Response>;
|
|
1374
1389
|
};
|
|
1390
|
+
type WorkloadClient = Pick<Workload, "getToken" | "refreshToken" | "generateJWTAssertion" | "revokeToken">;
|
|
1375
1391
|
/**
|
|
1376
1392
|
* SCIM Error response structure
|
|
1377
1393
|
*/
|
|
@@ -1629,7 +1645,7 @@ import { StandardSchemaV1 as StandardSchemaV16 } from "@standard-schema/spec";
|
|
|
1629
1645
|
*
|
|
1630
1646
|
* @template TExtended - Type-safe custom data that consumers can add to sessions
|
|
1631
1647
|
*/
|
|
1632
|
-
type Session<TExtended =
|
|
1648
|
+
type Session<TExtended = object> = {
|
|
1633
1649
|
/**
|
|
1634
1650
|
* Session ID from the Identity Provider (from `sid` claim in ID token).
|
|
1635
1651
|
* This is the unique identifier for the session.
|
|
@@ -1682,7 +1698,7 @@ type Session<TExtended = {}> = {
|
|
|
1682
1698
|
* }
|
|
1683
1699
|
* ```
|
|
1684
1700
|
*/
|
|
1685
|
-
interface SessionStore<TExtended =
|
|
1701
|
+
interface SessionStore<TExtended = object> {
|
|
1686
1702
|
/**
|
|
1687
1703
|
* Create a new session in the store.
|
|
1688
1704
|
*
|
|
@@ -1914,6 +1930,16 @@ type Secrets = {
|
|
|
1914
1930
|
handleLfvEvents?(request: Request): Promise<Response>;
|
|
1915
1931
|
};
|
|
1916
1932
|
/**
|
|
1933
|
+
* Partial secrets source config used in framework/app code to declare expected source names.
|
|
1934
|
+
* ConfigSource-backed values may still provide the actual source details at runtime.
|
|
1935
|
+
*/
|
|
1936
|
+
type FrameworkSecretsSourceConfig = Partial<SecretsSourceConfig>;
|
|
1937
|
+
/**
|
|
1938
|
+
* Framework-level named secrets source declarations keyed by source name.
|
|
1939
|
+
* Values may be partial or empty when the app only wants to declare expected names/types.
|
|
1940
|
+
*/
|
|
1941
|
+
type FrameworkSecretsModuleConfig = Record<string, FrameworkSecretsSourceConfig>;
|
|
1942
|
+
/**
|
|
1917
1943
|
* TODO: Let's see if we can do some clean inference and remove this!!!
|
|
1918
1944
|
*/
|
|
1919
1945
|
type SecretsSourceMap = Record<string, SecretsSource>;
|
|
@@ -1961,6 +1987,15 @@ type LfvSecretsConfig = {
|
|
|
1961
1987
|
*/
|
|
1962
1988
|
logger?: Logger;
|
|
1963
1989
|
};
|
|
1990
|
+
/**
|
|
1991
|
+
* Runtime-ready LFV source config.
|
|
1992
|
+
* Input config can be partially declared/merged, but LFV operations require these fields.
|
|
1993
|
+
*/
|
|
1994
|
+
type ResolvedLfvSecretsConfig = Omit<LfvSecretsConfig, "lfvServerUrl" | "clientId" | "path"> & {
|
|
1995
|
+
lfvServerUrl: string;
|
|
1996
|
+
clientId: string;
|
|
1997
|
+
path: string;
|
|
1998
|
+
};
|
|
1964
1999
|
type VaultSecretsConfig = {
|
|
1965
2000
|
type: "vault";
|
|
1966
2001
|
url?: string;
|
|
@@ -2080,8 +2115,8 @@ type FrameworkConfig = {
|
|
|
2080
2115
|
logger?: Logger;
|
|
2081
2116
|
sso?: SSOConfig | null;
|
|
2082
2117
|
iam?: IAMConfig | null;
|
|
2083
|
-
workload?:
|
|
2084
|
-
secrets?:
|
|
2118
|
+
workload?: FrameworkWorkloadConfig | null;
|
|
2119
|
+
secrets?: FrameworkSecretsModuleConfig | null;
|
|
2085
2120
|
ciam?: CIAMConfig | null;
|
|
2086
2121
|
validators: ESValidators;
|
|
2087
2122
|
};
|
|
@@ -2151,6 +2186,19 @@ type ESModuleFromConfig<
|
|
|
2151
2186
|
K extends keyof FrameworkConfig,
|
|
2152
2187
|
T
|
|
2153
2188
|
> = C[K] extends null ? never : [Exclude<C[K], undefined>] extends [never] ? T : [Exclude<C[K], undefined>] extends [null] ? never : T;
|
|
2189
|
+
type StringKeys<T> = Extract<keyof T, string>;
|
|
2190
|
+
type EmptyNamedModule = Record<string, never>;
|
|
2191
|
+
type NamedSecretsFromConfig<C extends FrameworkConfig> = Exclude<C["secrets"], null | undefined> extends infer S ? S extends Record<string, unknown> ? { [K in Exclude<StringKeys<S>, keyof Secrets>] : SecretsSource } : EmptyNamedModule : EmptyNamedModule;
|
|
2192
|
+
type NamedWorkloadClientsFromConfig<C extends FrameworkConfig> = Exclude<C["workload"], null | undefined> extends infer W ? W extends {
|
|
2193
|
+
outgoing?: infer O;
|
|
2194
|
+
} ? O extends Record<string, unknown> ? { [K in Exclude<StringKeys<O>, keyof Workload>] : WorkloadClient } : EmptyNamedModule : EmptyNamedModule : EmptyNamedModule;
|
|
2195
|
+
type AggregateWorkload = Omit<Workload, "getToken"> & {
|
|
2196
|
+
getToken: (client: string, scope?: string) => Promise<string>;
|
|
2197
|
+
getServerToken: (scope?: string) => Promise<string>;
|
|
2198
|
+
};
|
|
2199
|
+
type WorkloadModuleFromConfig<C extends FrameworkConfig> = Exclude<C["workload"], null | undefined> extends infer W ? W extends {
|
|
2200
|
+
outgoing?: infer O;
|
|
2201
|
+
} ? O extends Record<string, unknown> ? AggregateWorkload & NamedWorkloadClientsFromConfig<C> : Workload : Workload : Workload;
|
|
2154
2202
|
/**
|
|
2155
2203
|
* EnterpriseStandard type driven by the config type C.
|
|
2156
2204
|
* Module properties are:
|
|
@@ -2168,7 +2216,7 @@ type EnterpriseStandardBase = {
|
|
|
2168
2216
|
secrets?: Secrets;
|
|
2169
2217
|
sso?: SSO;
|
|
2170
2218
|
iam?: IAM;
|
|
2171
|
-
workload?: Workload;
|
|
2219
|
+
workload?: Workload | AggregateWorkload;
|
|
2172
2220
|
ciam?: CIAM;
|
|
2173
2221
|
/**
|
|
2174
2222
|
* Framework-agnostic request handler that routes requests to the appropriate
|
|
@@ -2189,10 +2237,10 @@ type EnterpriseStandardStrict<C extends FrameworkConfig> = {
|
|
|
2189
2237
|
logger?: Logger;
|
|
2190
2238
|
tenantId?: string;
|
|
2191
2239
|
config?: RemoteConfig;
|
|
2192
|
-
secrets: ESModuleFromConfig<C, "secrets", Secrets
|
|
2240
|
+
secrets: ESModuleFromConfig<C, "secrets", Secrets & NamedSecretsFromConfig<C>>;
|
|
2193
2241
|
sso: ESModuleFromConfig<C, "sso", SSO>;
|
|
2194
2242
|
iam: ESModuleFromConfig<C, "iam", IAM>;
|
|
2195
|
-
workload: ESModuleFromConfig<C, "workload",
|
|
2243
|
+
workload: ESModuleFromConfig<C, "workload", WorkloadModuleFromConfig<C>>;
|
|
2196
2244
|
ciam: ESModuleFromConfig<C, "ciam", CIAM>;
|
|
2197
2245
|
handler: (request: Request) => Promise<Response>;
|
|
2198
2246
|
ready(timeout?: number): Promise<void>;
|
|
@@ -2245,7 +2293,7 @@ type ESConfigChangeOptions = {
|
|
|
2245
2293
|
*
|
|
2246
2294
|
* @template TExtended - Type-safe custom data that consumers can add to magic links
|
|
2247
2295
|
*/
|
|
2248
|
-
type MagicLink<TExtended =
|
|
2296
|
+
type MagicLink<TExtended = object> = {
|
|
2249
2297
|
/**
|
|
2250
2298
|
* The magic link token (unique identifier)
|
|
2251
2299
|
*/
|
|
@@ -2303,7 +2351,7 @@ type MagicLink<TExtended = {}> = {
|
|
|
2303
2351
|
* }
|
|
2304
2352
|
* ```
|
|
2305
2353
|
*/
|
|
2306
|
-
interface MagicLinkStore<TExtended =
|
|
2354
|
+
interface MagicLinkStore<TExtended = object> {
|
|
2307
2355
|
/**
|
|
2308
2356
|
* Create a new magic link in the store.
|
|
2309
2357
|
*
|
|
@@ -2486,7 +2534,7 @@ interface UpsertTenantRequest {
|
|
|
2486
2534
|
webhookUrl: string;
|
|
2487
2535
|
callbackUrl: string;
|
|
2488
2536
|
tenantUrl?: string;
|
|
2489
|
-
|
|
2537
|
+
configSource: TenantSecretsConfig;
|
|
2490
2538
|
}
|
|
2491
2539
|
type UpsertTenantResponse = {
|
|
2492
2540
|
tenantUrl?: string;
|
|
@@ -2560,6 +2608,22 @@ type TenantConfigEnv = {
|
|
|
2560
2608
|
ES_AWS_TTL?: string;
|
|
2561
2609
|
ES_GCP_TTL?: string;
|
|
2562
2610
|
};
|
|
2611
|
+
type TenantSecretsConfig = LfvSecretsConfig | (VaultSecretsConfig & {
|
|
2612
|
+
path: string;
|
|
2613
|
+
retryInterval?: number;
|
|
2614
|
+
}) | (DevSecretsConfig & {
|
|
2615
|
+
path?: string;
|
|
2616
|
+
appId?: string;
|
|
2617
|
+
}) | (AwsSecretsConfig & {
|
|
2618
|
+
ttl?: number;
|
|
2619
|
+
}) | AzureSecretsConfig | (GcpSecretsConfig & {
|
|
2620
|
+
ttl?: number;
|
|
2621
|
+
}) | {
|
|
2622
|
+
type: "localFile";
|
|
2623
|
+
path?: string;
|
|
2624
|
+
watch?: boolean;
|
|
2625
|
+
ttl?: number;
|
|
2626
|
+
};
|
|
2563
2627
|
type StoredTenant<TExtended extends object = Record<string, never>> = {
|
|
2564
2628
|
tenantId: string;
|
|
2565
2629
|
companyId: string;
|
|
@@ -2576,8 +2640,8 @@ type StoredTenant<TExtended extends object = Record<string, never>> = {
|
|
|
2576
2640
|
expiresAt?: string;
|
|
2577
2641
|
createdAt: Date;
|
|
2578
2642
|
updatedAt: Date;
|
|
2579
|
-
/** Persisted
|
|
2580
|
-
|
|
2643
|
+
/** Persisted typed config used to construct a ConfigSource at runtime. */
|
|
2644
|
+
configSource: TenantSecretsConfig;
|
|
2581
2645
|
/** Runtime helper that returns a ConfigSource for this tenant. */
|
|
2582
2646
|
config: () => ConfigSource;
|
|
2583
2647
|
} & TExtended;
|
|
@@ -2793,4 +2857,4 @@ declare function parseJsonc<T>(content: string): T;
|
|
|
2793
2857
|
* @returns A promise that resolves when the service is ready.
|
|
2794
2858
|
*/
|
|
2795
2859
|
declare function waitOn(url: string, pingInterval?: number, warnInterval?: number, timeout?: number): Promise<void>;
|
|
2796
|
-
export { workloadTokenResponseSchema, withValidate, waitOn, version, validationFailureResponse, userSchema, tokenResponseSchema, stripJsonComments, silentLogger, setActiveSession, serializeESConfig, sendTenantWebhook, parseJsonc, oidcCallbackSchema, must, mergeConfig, list, jwtAssertionClaimsSchema, infoLogger, idTokenClaimsSchema, groupResourceSchema, getActiveSession, findTenantFromStateParam, defaultLogger, decodeUser, debugLogger, consoleLogger, claimsToUser, X509Certificate, WorkloadValidators, WorkloadTokenStore, WorkloadTokenResponse, WorkloadIncomingOutgoing, WorkloadIdentity, WorkloadConfigMap, WorkloadConfig, Workload, VaultSecretsConfig, ValidateResult, UsersInboundHandlerConfig, UserStore, UserSortOptions, UserSortField, UserListOptions, User2 as User, UpsertTenantResponse, UpsertTenantRequest, TokenValidationResult, TokenResponse, TenantWebhookPayload, TenantValidators, TenantStore, TenantStatus, TenantRequestError, TenantConfigEnv, StoredUser, StoredTenant, StoredGroup, StateCookie, StandardSchemaWithValidate, SortDirection, SessionStore, Session, ServerOnlyWorkloadConfig, SecretsValidators, SecretsSourceType, SecretsSourceMap, SecretsSourceConfig, SecretsSource, SecretsOperationOptions, SecretsModuleConfig, Secrets, SecretRequestSeverity, SecretLifecycleRequest, Secret, User as ScimUser, ScimResult, ScimListResponse, ScimError, SSOValidators, SSOHandlerConfig, SSOConfig, SSO, Role, RemoteConfig, Photo, PhoneNumber, OidcCallbackParams, Name, MetaData, MagicLinkStore, MagicLink, LoginConfig, Logger, ListResult, LfvSecretsConfig, JwtBearerWorkloadConfig, JWTAssertionClaims, InMemoryTenantStore, IdTokenClaims, IAMValidators, IAMUsersInbound, IAMHandlerConfig, IAMGroupsOutbound, IAMGroupsInbound, IAMConfig, IAM, GroupsInboundHandlerConfig, GroupStore, GroupSortOptions, GroupSortField, GroupResource, GroupMember, GroupListOptions, Group, GcpSecretsConfig, FrameworkConfig, EnvironmentType, EnterpriseUser, EnterpriseStandardFromConfig, EnterpriseStandardBase, EnterpriseStandard, EnterpriseExtension, Email, ESValidators, ESRoutingOptions, ESRouteModule, ESRouteFilterResult, ESResolvedRoute, ESModuleFromConfig, ESConfigChangeResult, ESConfigChangeOptions, ESConfigChangeCallback, ESConfig, DevSecretsConfig, CreateUserOptions, CreateTenantResponse, CreateTenantRequest, CreateGroupOptions, ConfigSourceType, ConfigSource, ClientCredentialsWorkloadConfig, CachedWorkloadToken, CIAMValidators, CIAMConfigFromCode, CIAMConfig, CIAM, BaseUser, AzureSecretsConfig, AwsSecretsConfig, AwsAuthMethod, Address };
|
|
2860
|
+
export { workloadTokenResponseSchema, withValidate, waitOn, version, validationFailureResponse, userSchema, tokenResponseSchema, stripJsonComments, silentLogger, setActiveSession, serializeESConfig, sendTenantWebhook, parseJsonc, oidcCallbackSchema, must, mergeConfig, list, jwtAssertionClaimsSchema, infoLogger, idTokenClaimsSchema, groupResourceSchema, getActiveSession, findTenantFromStateParam, defaultLogger, decodeUser, debugLogger, consoleLogger, claimsToUser, X509Certificate, WorkloadValidators, WorkloadTokenStore, WorkloadTokenResponse, WorkloadIncomingOutgoing, WorkloadIdentity, WorkloadConfigMap, WorkloadConfig, WorkloadClient, Workload, VaultSecretsConfig, ValidateResult, UsersInboundHandlerConfig, UserStore, UserSortOptions, UserSortField, UserListOptions, User2 as User, UpsertTenantResponse, UpsertTenantRequest, TokenValidationResult, TokenResponse, TenantWebhookPayload, TenantValidators, TenantStore, TenantStatus, TenantSecretsConfig, TenantRequestError, TenantConfigEnv, StoredUser, StoredTenant, StoredGroup, StateCookie, StandardSchemaWithValidate, SortDirection, SessionStore, Session, ServerOnlyWorkloadConfig, SecretsValidators, SecretsSourceType, SecretsSourceMap, SecretsSourceConfig, SecretsSource, SecretsOperationOptions, SecretsModuleConfig, Secrets, SecretRequestSeverity, SecretLifecycleRequest, Secret, User as ScimUser, ScimResult, ScimListResponse, ScimError, SSOValidators, SSOHandlerConfig, SSOConfig, SSO, Role, ResolvedLfvSecretsConfig, RemoteConfig, Photo, PhoneNumber, OidcCallbackParams, Name, MetaData, MagicLinkStore, MagicLink, LoginConfig, Logger, ListResult, LfvSecretsConfig, JwtBearerWorkloadConfig, JWTAssertionClaims, InMemoryTenantStore, IdTokenClaims, IAMValidators, IAMUsersInbound, IAMHandlerConfig, IAMGroupsOutbound, IAMGroupsInbound, IAMConfig, IAM, GroupsInboundHandlerConfig, GroupStore, GroupSortOptions, GroupSortField, GroupResource, GroupMember, GroupListOptions, Group, GcpSecretsConfig, FrameworkWorkloadIncomingOutgoing, FrameworkWorkloadConfig, FrameworkSecretsSourceConfig, FrameworkSecretsModuleConfig, FrameworkConfig, EnvironmentType, EnterpriseUser, EnterpriseStandardFromConfig, EnterpriseStandardBase, EnterpriseStandard, EnterpriseExtension, Email, ESValidators, ESRoutingOptions, ESRouteModule, ESRouteFilterResult, ESResolvedRoute, ESModuleFromConfig, ESConfigChangeResult, ESConfigChangeOptions, ESConfigChangeCallback, ESConfig, DevSecretsConfig, CreateUserOptions, CreateTenantResponse, CreateTenantRequest, CreateGroupOptions, ConfigSourceType, ConfigSource, ClientCredentialsWorkloadConfig, CachedWorkloadToken, CIAMValidators, CIAMConfigFromCode, CIAMConfig, CIAM, BaseUser, AzureSecretsConfig, AwsSecretsConfig, AwsAuthMethod, Address };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as j,b as S,c as P,d as p,e as g,f as b,g as h,h as m,i as d,j as o,k as n,l as v,m as r,n as l,o as t,p as i,q as u,t as a,u as s,v as e}from"./shared/core-q2xp5jrk.js";var W="0.0.9-beta.20260304.1";var B=["sessionStore","userStore","groupStore","tokenStore","magicLinkStore"];function _(H){if(H===null||typeof H!=="object")return H;let C={};for(let[D,x]of Object.entries(H)){if(B.includes(D)||D==="validators")continue;C[D]=x!==null&&typeof x==="object"&&!Array.isArray(x)&&Object.getPrototypeOf(x)===Object.prototype?_(x):x}return C}function E(H){return _(H)}function I(H,C,D,x){let J=C.length,$=x??H,Q=$>0?Math.floor(D/$)+1:1,Z=$>0?Math.ceil(H/$):0;return{total:H,count:J,items:C,size:$,page:Q,pages:Z}}class Y extends Error{constructor(H,C){super(H,C);this.name="TenantRequestError",Object.setPrototypeOf(this,Y.prototype)}}class M{tenants=new Map;async get(H){return this.tenants.get(H)??null}async upsert(H){let C=new Date,D=this.tenants.get(H.tenantId),x={...D??{},...H,status:H.status??D?.status??"completed",createdAt:H.createdAt??D?.createdAt??C,updatedAt:H.updatedAt??C};return this.tenants.set(x.tenantId,x),x}async delete(H){this.tenants.delete(H)}}function K(H,C,D){return(async()=>{try{let x=await fetch(H,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(C)});if(!x.ok)D.error(`Failed to send webhook update: ${x.status} ${x.statusText}`)}catch(x){D.error("Failed to send webhook update:",x)}})()}async function R(H,C,D){return K(H,C,D)}function X(H,C,D,x,J){if(H===void 0||H===null){if(D)x.push({message:`${C} is required`,path:J});return}if(typeof H!=="string"){x.push({message:`${C} must be a string`,path:J});return}return H}function L(H,C,D,x){if(H===void 0||H===null)return;if(typeof H!=="boolean"){D.push({message:`${C} must be a boolean`,path:x});return}return H}function z(H,C,D){if(H===void 0||H===null)return;if(typeof H!=="object"||H===null){C.push({message:"name must be an object",path:D});return}let x=H,J={};return J.formatted=X(x.formatted,"formatted",!1,C,[...D,"formatted"]),J.familyName=X(x.familyName,"familyName",!1,C,[...D,"familyName"]),J.givenName=X(x.givenName,"givenName",!1,C,[...D,"givenName"]),J.middleName=X(x.middleName,"middleName",!1,C,[...D,"middleName"]),J.honorificPrefix=X(x.honorificPrefix,"honorificPrefix",!1,C,[...D,"honorificPrefix"]),J.honorificSuffix=X(x.honorificSuffix,"honorificSuffix",!1,C,[...D,"honorificSuffix"]),J}function U(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"emails must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"email must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function q(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"phoneNumbers must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"phoneNumber must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function w(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"addresses must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"address must be an object",path:Q});continue}let Z=$;x.push({formatted:X(Z.formatted,"formatted",!1,C,[...Q,"formatted"]),streetAddress:X(Z.streetAddress,"streetAddress",!1,C,[...Q,"streetAddress"]),locality:X(Z.locality,"locality",!1,C,[...Q,"locality"]),region:X(Z.region,"region",!1,C,[...Q,"region"]),postalCode:X(Z.postalCode,"postalCode",!1,C,[...Q,"postalCode"]),country:X(Z.country,"country",!1,C,[...Q,"country"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function T(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"groups must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"group must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,$ref:X(Z.$ref,"$ref",!1,C,[...Q,"$ref"]),display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"])})}return x.length>0?x:void 0}function V(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"roles must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"role must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function k(H,C,D){if(H===void 0||H===null)return;if(typeof H!=="object"||H===null){C.push({message:"Enterprise User extension must be an object",path:D});return}let x=H,J={};if(J.employeeNumber=X(x.employeeNumber,"employeeNumber",!1,C,[...D,"employeeNumber"]),J.costCenter=X(x.costCenter,"costCenter",!1,C,[...D,"costCenter"]),J.organization=X(x.organization,"organization",!1,C,[...D,"organization"]),J.division=X(x.division,"division",!1,C,[...D,"division"]),J.department=X(x.department,"department",!1,C,[...D,"department"]),x.manager!==void 0&&x.manager!==null)if(typeof x.manager!=="object"||x.manager===null)C.push({message:"manager must be an object",path:[...D,"manager"]});else{let $=x.manager;J.manager={value:X($.value,"value",!1,C,[...D,"manager","value"]),$ref:X($.$ref,"$ref",!1,C,[...D,"manager","$ref"]),displayName:X($.displayName,"displayName",!1,C,[...D,"manager","displayName"])}}return J}function y(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={},$=X(D.userName,"userName",!0,x,["userName"]);if(!$)return{issues:x};J.userName=$,J.id=X(D.id,"id",!1,x,["id"]),J.externalId=X(D.externalId,"externalId",!1,x,["externalId"]),J.displayName=X(D.displayName,"displayName",!1,x,["displayName"]),J.nickName=X(D.nickName,"nickName",!1,x,["nickName"]),J.profileUrl=X(D.profileUrl,"profileUrl",!1,x,["profileUrl"]),J.title=X(D.title,"title",!1,x,["title"]),J.userType=X(D.userType,"userType",!1,x,["userType"]),J.preferredLanguage=X(D.preferredLanguage,"preferredLanguage",!1,x,["preferredLanguage"]),J.locale=X(D.locale,"locale",!1,x,["locale"]),J.timezone=X(D.timezone,"timezone",!1,x,["timezone"]),J.password=X(D.password,"password",!1,x,["password"]),J.active=L(D.active,"active",x,["active"]),J.name=z(D.name,x,["name"]),J.emails=U(D.emails,x,["emails"]),J.phoneNumbers=q(D.phoneNumbers,x,["phoneNumbers"]),J.addresses=w(D.addresses,x,["addresses"]),J.groups=T(D.groups,x,["groups"]),J.roles=V(D.roles,x,["roles"]);let Q="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User";if(D[Q]!==void 0)J[Q]=k(D[Q],x,[Q]);if(D.schemas!==void 0)if(Array.isArray(D.schemas))J.schemas=D.schemas.filter((Z)=>typeof Z==="string");else x.push({message:"schemas must be an array",path:["schemas"]});if(D.meta!==void 0)if(typeof D.meta==="object"&&D.meta!==null){let Z=D.meta;J.meta={resourceType:typeof Z.resourceType==="string"?Z.resourceType:void 0,created:typeof Z.created==="string"?Z.created:void 0,lastModified:typeof Z.lastModified==="string"?Z.lastModified:void 0,location:typeof Z.location==="string"?Z.location:void 0,version:typeof Z.version==="string"?Z.version:void 0}}else x.push({message:"meta must be an object",path:["meta"]});if(x.length>0)return{issues:x};return{value:J}}}}}function N(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"members must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"member must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A){let G=X(Z.type,"type",!1,C,[...Q,"type"]);x.push({value:A,$ref:X(Z.$ref,"$ref",!1,C,[...Q,"$ref"]),display:X(Z.display,"display",!1,C,[...Q,"display"]),type:G==="User"||G==="Group"?G:void 0})}}return x.length>0?x:void 0}function c(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={},$=X(D.displayName,"displayName",!0,x,["displayName"]);if(!$)return{issues:x};if(J.displayName=$,J.id=X(D.id,"id",!1,x,["id"]),J.externalId=X(D.externalId,"externalId",!1,x,["externalId"]),J.members=N(D.members,x,["members"]),D.schemas!==void 0)if(Array.isArray(D.schemas))J.schemas=D.schemas.filter((Q)=>typeof Q==="string");else x.push({message:"schemas must be an array",path:["schemas"]});if(D.meta!==void 0)if(typeof D.meta==="object"&&D.meta!==null){let Q=D.meta;J.meta={resourceType:typeof Q.resourceType==="string"?Q.resourceType:void 0,created:typeof Q.created==="string"?Q.created:void 0,lastModified:typeof Q.lastModified==="string"?Q.lastModified:void 0,location:typeof Q.location==="string"?Q.location:void 0,version:typeof Q.version==="string"?Q.version:void 0}}else x.push({message:"meta must be an object",path:["meta"]});if(x.length>0)return{issues:x};return{value:J}}}}}function f(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={...D},$=["iss","sub"];for(let A of $)if(A in D){if(typeof D[A]!=="string")x.push({message:`${A} must be a string`,path:[A]})}else x.push({message:`${A} is required`,path:[A]});if("aud"in D&&D.aud!==void 0){let A=D.aud;if(typeof A!=="string"&&!Array.isArray(A))x.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(A)&&!A.every((G)=>typeof G==="string"))x.push({message:"aud array must contain only strings",path:["aud"]})}let Q=["jti","scope"];for(let A of Q)if(A in D&&D[A]!==void 0){if(typeof D[A]!=="string")x.push({message:`${A} must be a string`,path:[A]})}let Z=["exp","iat"];for(let A of Z)if(A in D){if(typeof D[A]!=="number")x.push({message:`${A} must be a number`,path:[A]})}else x.push({message:`${A} is required`,path:[A]});if(x.length>0)return{issues:x};return{value:J}}}}}function O(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={};if("access_token"in D)if(typeof D.access_token==="string")J.access_token=D.access_token;else x.push({message:"access_token must be a string",path:["access_token"]});else x.push({message:"access_token is required",path:["access_token"]});if("token_type"in D)if(typeof D.token_type==="string")J.token_type=D.token_type;else x.push({message:"token_type must be a string",path:["token_type"]});else x.push({message:"token_type is required",path:["token_type"]});if("scope"in D)if(typeof D.scope==="string"||D.scope===void 0)J.scope=D.scope;else x.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in D)if(typeof D.refresh_token==="string"||D.refresh_token===void 0)J.refresh_token=D.refresh_token;else x.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in D)if(typeof D.expires==="string"||D.expires===void 0)J.expires=D.expires;else x.push({message:"expires must be a string",path:["expires"]});if("expires_in"in D)if(typeof D.expires_in==="number"||D.expires_in===void 0)J.expires_in=D.expires_in;else x.push({message:"expires_in must be a number",path:["expires_in"]});if(x.length>0)return{issues:x};return{value:J}}}}}export{O as workloadTokenResponseSchema,p as withValidate,o as waitOn,W as version,b as validationFailureResponse,y as userSchema,S as tokenResponseSchema,m as stripJsonComments,l as silentLogger,s as setActiveSession,E as serializeESConfig,R as sendTenantWebhook,d as parseJsonc,j as oidcCallbackSchema,g as must,h as mergeConfig,I as list,f as jwtAssertionClaimsSchema,t as infoLogger,P as idTokenClaimsSchema,c as groupResourceSchema,a as getActiveSession,e as findTenantFromStateParam,r as defaultLogger,v as decodeUser,i as debugLogger,u as consoleLogger,n as claimsToUser,Y as TenantRequestError,M as InMemoryTenantStore};
|
|
1
|
+
import{a as j,b as S,c as P,d as p,e as g,f as b,g as h,h as m,i as d,j as o,k as n,l as v,m as r,n as l,o as t,p as i,q as u,t as a,u as s,v as e}from"./shared/core-q2xp5jrk.js";var W="0.0.9";var B=["sessionStore","userStore","groupStore","tokenStore","magicLinkStore"];function _(H){if(H===null||typeof H!=="object")return H;let C={};for(let[D,x]of Object.entries(H)){if(B.includes(D)||D==="validators")continue;C[D]=x!==null&&typeof x==="object"&&!Array.isArray(x)&&Object.getPrototypeOf(x)===Object.prototype?_(x):x}return C}function E(H){return _(H)}function I(H,C,D,x){let J=C.length,$=x??H,Q=$>0?Math.floor(D/$)+1:1,Z=$>0?Math.ceil(H/$):0;return{total:H,count:J,items:C,size:$,page:Q,pages:Z}}class Y extends Error{constructor(H,C){super(H,C);this.name="TenantRequestError",Object.setPrototypeOf(this,Y.prototype)}}class M{tenants=new Map;async get(H){return this.tenants.get(H)??null}async upsert(H){let C=new Date,D=this.tenants.get(H.tenantId),x={...D??{},...H,status:H.status??D?.status??"completed",createdAt:H.createdAt??D?.createdAt??C,updatedAt:H.updatedAt??C};return this.tenants.set(x.tenantId,x),x}async delete(H){this.tenants.delete(H)}}function K(H,C,D){return(async()=>{try{let x=await fetch(H,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(C)});if(!x.ok)D.error(`Failed to send webhook update: ${x.status} ${x.statusText}`)}catch(x){D.error("Failed to send webhook update:",x)}})()}async function R(H,C,D){return K(H,C,D)}function X(H,C,D,x,J){if(H===void 0||H===null){if(D)x.push({message:`${C} is required`,path:J});return}if(typeof H!=="string"){x.push({message:`${C} must be a string`,path:J});return}return H}function L(H,C,D,x){if(H===void 0||H===null)return;if(typeof H!=="boolean"){D.push({message:`${C} must be a boolean`,path:x});return}return H}function z(H,C,D){if(H===void 0||H===null)return;if(typeof H!=="object"||H===null){C.push({message:"name must be an object",path:D});return}let x=H,J={};return J.formatted=X(x.formatted,"formatted",!1,C,[...D,"formatted"]),J.familyName=X(x.familyName,"familyName",!1,C,[...D,"familyName"]),J.givenName=X(x.givenName,"givenName",!1,C,[...D,"givenName"]),J.middleName=X(x.middleName,"middleName",!1,C,[...D,"middleName"]),J.honorificPrefix=X(x.honorificPrefix,"honorificPrefix",!1,C,[...D,"honorificPrefix"]),J.honorificSuffix=X(x.honorificSuffix,"honorificSuffix",!1,C,[...D,"honorificSuffix"]),J}function U(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"emails must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"email must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function q(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"phoneNumbers must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"phoneNumber must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function w(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"addresses must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"address must be an object",path:Q});continue}let Z=$;x.push({formatted:X(Z.formatted,"formatted",!1,C,[...Q,"formatted"]),streetAddress:X(Z.streetAddress,"streetAddress",!1,C,[...Q,"streetAddress"]),locality:X(Z.locality,"locality",!1,C,[...Q,"locality"]),region:X(Z.region,"region",!1,C,[...Q,"region"]),postalCode:X(Z.postalCode,"postalCode",!1,C,[...Q,"postalCode"]),country:X(Z.country,"country",!1,C,[...Q,"country"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function T(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"groups must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"group must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,$ref:X(Z.$ref,"$ref",!1,C,[...Q,"$ref"]),display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"])})}return x.length>0?x:void 0}function V(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"roles must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"role must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function k(H,C,D){if(H===void 0||H===null)return;if(typeof H!=="object"||H===null){C.push({message:"Enterprise User extension must be an object",path:D});return}let x=H,J={};if(J.employeeNumber=X(x.employeeNumber,"employeeNumber",!1,C,[...D,"employeeNumber"]),J.costCenter=X(x.costCenter,"costCenter",!1,C,[...D,"costCenter"]),J.organization=X(x.organization,"organization",!1,C,[...D,"organization"]),J.division=X(x.division,"division",!1,C,[...D,"division"]),J.department=X(x.department,"department",!1,C,[...D,"department"]),x.manager!==void 0&&x.manager!==null)if(typeof x.manager!=="object"||x.manager===null)C.push({message:"manager must be an object",path:[...D,"manager"]});else{let $=x.manager;J.manager={value:X($.value,"value",!1,C,[...D,"manager","value"]),$ref:X($.$ref,"$ref",!1,C,[...D,"manager","$ref"]),displayName:X($.displayName,"displayName",!1,C,[...D,"manager","displayName"])}}return J}function y(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={},$=X(D.userName,"userName",!0,x,["userName"]);if(!$)return{issues:x};J.userName=$,J.id=X(D.id,"id",!1,x,["id"]),J.externalId=X(D.externalId,"externalId",!1,x,["externalId"]),J.displayName=X(D.displayName,"displayName",!1,x,["displayName"]),J.nickName=X(D.nickName,"nickName",!1,x,["nickName"]),J.profileUrl=X(D.profileUrl,"profileUrl",!1,x,["profileUrl"]),J.title=X(D.title,"title",!1,x,["title"]),J.userType=X(D.userType,"userType",!1,x,["userType"]),J.preferredLanguage=X(D.preferredLanguage,"preferredLanguage",!1,x,["preferredLanguage"]),J.locale=X(D.locale,"locale",!1,x,["locale"]),J.timezone=X(D.timezone,"timezone",!1,x,["timezone"]),J.password=X(D.password,"password",!1,x,["password"]),J.active=L(D.active,"active",x,["active"]),J.name=z(D.name,x,["name"]),J.emails=U(D.emails,x,["emails"]),J.phoneNumbers=q(D.phoneNumbers,x,["phoneNumbers"]),J.addresses=w(D.addresses,x,["addresses"]),J.groups=T(D.groups,x,["groups"]),J.roles=V(D.roles,x,["roles"]);let Q="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User";if(D[Q]!==void 0)J[Q]=k(D[Q],x,[Q]);if(D.schemas!==void 0)if(Array.isArray(D.schemas))J.schemas=D.schemas.filter((Z)=>typeof Z==="string");else x.push({message:"schemas must be an array",path:["schemas"]});if(D.meta!==void 0)if(typeof D.meta==="object"&&D.meta!==null){let Z=D.meta;J.meta={resourceType:typeof Z.resourceType==="string"?Z.resourceType:void 0,created:typeof Z.created==="string"?Z.created:void 0,lastModified:typeof Z.lastModified==="string"?Z.lastModified:void 0,location:typeof Z.location==="string"?Z.location:void 0,version:typeof Z.version==="string"?Z.version:void 0}}else x.push({message:"meta must be an object",path:["meta"]});if(x.length>0)return{issues:x};return{value:J}}}}}function N(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"members must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"member must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A){let G=X(Z.type,"type",!1,C,[...Q,"type"]);x.push({value:A,$ref:X(Z.$ref,"$ref",!1,C,[...Q,"$ref"]),display:X(Z.display,"display",!1,C,[...Q,"display"]),type:G==="User"||G==="Group"?G:void 0})}}return x.length>0?x:void 0}function c(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={},$=X(D.displayName,"displayName",!0,x,["displayName"]);if(!$)return{issues:x};if(J.displayName=$,J.id=X(D.id,"id",!1,x,["id"]),J.externalId=X(D.externalId,"externalId",!1,x,["externalId"]),J.members=N(D.members,x,["members"]),D.schemas!==void 0)if(Array.isArray(D.schemas))J.schemas=D.schemas.filter((Q)=>typeof Q==="string");else x.push({message:"schemas must be an array",path:["schemas"]});if(D.meta!==void 0)if(typeof D.meta==="object"&&D.meta!==null){let Q=D.meta;J.meta={resourceType:typeof Q.resourceType==="string"?Q.resourceType:void 0,created:typeof Q.created==="string"?Q.created:void 0,lastModified:typeof Q.lastModified==="string"?Q.lastModified:void 0,location:typeof Q.location==="string"?Q.location:void 0,version:typeof Q.version==="string"?Q.version:void 0}}else x.push({message:"meta must be an object",path:["meta"]});if(x.length>0)return{issues:x};return{value:J}}}}}function f(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={...D},$=["iss","sub"];for(let A of $)if(A in D){if(typeof D[A]!=="string")x.push({message:`${A} must be a string`,path:[A]})}else x.push({message:`${A} is required`,path:[A]});if("aud"in D&&D.aud!==void 0){let A=D.aud;if(typeof A!=="string"&&!Array.isArray(A))x.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(A)&&!A.every((G)=>typeof G==="string"))x.push({message:"aud array must contain only strings",path:["aud"]})}let Q=["jti","scope"];for(let A of Q)if(A in D&&D[A]!==void 0){if(typeof D[A]!=="string")x.push({message:`${A} must be a string`,path:[A]})}let Z=["exp","iat"];for(let A of Z)if(A in D){if(typeof D[A]!=="number")x.push({message:`${A} must be a number`,path:[A]})}else x.push({message:`${A} is required`,path:[A]});if(x.length>0)return{issues:x};return{value:J}}}}}function O(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={};if("access_token"in D)if(typeof D.access_token==="string")J.access_token=D.access_token;else x.push({message:"access_token must be a string",path:["access_token"]});else x.push({message:"access_token is required",path:["access_token"]});if("token_type"in D)if(typeof D.token_type==="string")J.token_type=D.token_type;else x.push({message:"token_type must be a string",path:["token_type"]});else x.push({message:"token_type is required",path:["token_type"]});if("scope"in D)if(typeof D.scope==="string"||D.scope===void 0)J.scope=D.scope;else x.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in D)if(typeof D.refresh_token==="string"||D.refresh_token===void 0)J.refresh_token=D.refresh_token;else x.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in D)if(typeof D.expires==="string"||D.expires===void 0)J.expires=D.expires;else x.push({message:"expires must be a string",path:["expires"]});if("expires_in"in D)if(typeof D.expires_in==="number"||D.expires_in===void 0)J.expires_in=D.expires_in;else x.push({message:"expires_in must be a number",path:["expires_in"]});if(x.length>0)return{issues:x};return{value:J}}}}}export{O as workloadTokenResponseSchema,p as withValidate,o as waitOn,W as version,b as validationFailureResponse,y as userSchema,S as tokenResponseSchema,m as stripJsonComments,l as silentLogger,s as setActiveSession,E as serializeESConfig,R as sendTenantWebhook,d as parseJsonc,j as oidcCallbackSchema,g as must,h as mergeConfig,I as list,f as jwtAssertionClaimsSchema,t as infoLogger,P as idTokenClaimsSchema,c as groupResourceSchema,a as getActiveSession,e as findTenantFromStateParam,r as defaultLogger,v as decodeUser,i as debugLogger,u as consoleLogger,n as claimsToUser,Y as TenantRequestError,M as InMemoryTenantStore};
|
package/dist/server.d.ts
CHANGED
|
@@ -719,7 +719,7 @@ interface User2 extends BaseUser {
|
|
|
719
719
|
*
|
|
720
720
|
* @template TExtended - Type-safe custom data that consumers can add to users
|
|
721
721
|
*/
|
|
722
|
-
type StoredUser<TExtended =
|
|
722
|
+
type StoredUser<TExtended = object> = User2 & {
|
|
723
723
|
/**
|
|
724
724
|
* Required unique identifier (the `sub` claim from the IdP).
|
|
725
725
|
* This is the primary key for user storage.
|
|
@@ -762,7 +762,7 @@ type StoredUser<TExtended = {}> = User2 & {
|
|
|
762
762
|
* }
|
|
763
763
|
* ```
|
|
764
764
|
*/
|
|
765
|
-
interface UserStore<TExtended =
|
|
765
|
+
interface UserStore<TExtended = object> {
|
|
766
766
|
/**
|
|
767
767
|
* Retrieve a user by their subject identifier (sub).
|
|
768
768
|
*
|
|
@@ -1245,13 +1245,27 @@ type WorkloadConfigMap = Record<string, WorkloadConfig>;
|
|
|
1245
1245
|
/**
|
|
1246
1246
|
* Workload config with separate incoming (server) and outgoing (client) roles.
|
|
1247
1247
|
* - **incoming**: Server-only config for validating tokens presented to this app (jwksUri, issuer).
|
|
1248
|
-
* - **outgoing**: Map of named clients for outbound calls; use getWorkloadToken(client
|
|
1248
|
+
* - **outgoing**: Map of named clients for outbound calls; use getWorkloadToken(client, es, scope?) from server (client is required and must be one of the outgoing names; pass the ES instance).
|
|
1249
1249
|
*/
|
|
1250
1250
|
type WorkloadIncomingOutgoing = {
|
|
1251
1251
|
incoming?: Partial<WorkloadConfig>;
|
|
1252
1252
|
outgoing?: Record<string, Partial<WorkloadConfig>>;
|
|
1253
1253
|
};
|
|
1254
1254
|
/**
|
|
1255
|
+
* Framework-level workload declarations used by app code to define the expected
|
|
1256
|
+
* incoming/outgoing workload shape without needing all remote credentials in code.
|
|
1257
|
+
*/
|
|
1258
|
+
type FrameworkWorkloadIncomingOutgoing = {
|
|
1259
|
+
incoming?: Partial<WorkloadConfig>;
|
|
1260
|
+
outgoing?: Record<string, Partial<WorkloadConfig>>;
|
|
1261
|
+
};
|
|
1262
|
+
/**
|
|
1263
|
+
* Workload config shape accepted from framework/app code.
|
|
1264
|
+
* Apps may provide a partial single config or an incoming/outgoing declaration
|
|
1265
|
+
* to expose named outgoing clients in the type system.
|
|
1266
|
+
*/
|
|
1267
|
+
type FrameworkWorkloadConfig = Partial<WorkloadConfig> | FrameworkWorkloadIncomingOutgoing;
|
|
1268
|
+
/**
|
|
1255
1269
|
* Workload Identity extracted from validated tokens
|
|
1256
1270
|
*/
|
|
1257
1271
|
type WorkloadIdentity = {
|
|
@@ -1276,10 +1290,11 @@ type WorkloadIdentity = {
|
|
|
1276
1290
|
* Workload Identity Authentication Interface
|
|
1277
1291
|
*/
|
|
1278
1292
|
type Workload = WorkloadConfig & {
|
|
1279
|
-
/**
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1293
|
+
/**
|
|
1294
|
+
* Returns a token for this workload configuration.
|
|
1295
|
+
* The optional argument overrides the configured default scope.
|
|
1296
|
+
*/
|
|
1297
|
+
getToken: (scope?: string) => Promise<string>;
|
|
1283
1298
|
refreshToken: (scope?: string) => Promise<WorkloadTokenResponse>;
|
|
1284
1299
|
generateJWTAssertion: (scope?: string) => Promise<string>;
|
|
1285
1300
|
revokeToken: (token: string) => Promise<void>;
|
|
@@ -1557,7 +1572,7 @@ import { StandardSchemaV1 as StandardSchemaV16 } from "@standard-schema/spec";
|
|
|
1557
1572
|
*
|
|
1558
1573
|
* @template TExtended - Type-safe custom data that consumers can add to sessions
|
|
1559
1574
|
*/
|
|
1560
|
-
type Session<TExtended =
|
|
1575
|
+
type Session<TExtended = object> = {
|
|
1561
1576
|
/**
|
|
1562
1577
|
* Session ID from the Identity Provider (from `sid` claim in ID token).
|
|
1563
1578
|
* This is the unique identifier for the session.
|
|
@@ -1610,7 +1625,7 @@ type Session<TExtended = {}> = {
|
|
|
1610
1625
|
* }
|
|
1611
1626
|
* ```
|
|
1612
1627
|
*/
|
|
1613
|
-
interface SessionStore<TExtended =
|
|
1628
|
+
interface SessionStore<TExtended = object> {
|
|
1614
1629
|
/**
|
|
1615
1630
|
* Create a new session in the store.
|
|
1616
1631
|
*
|
|
@@ -1840,6 +1855,16 @@ type Secrets = {
|
|
|
1840
1855
|
handleLfvEvents?(request: Request): Promise<Response>;
|
|
1841
1856
|
};
|
|
1842
1857
|
/**
|
|
1858
|
+
* Partial secrets source config used in framework/app code to declare expected source names.
|
|
1859
|
+
* ConfigSource-backed values may still provide the actual source details at runtime.
|
|
1860
|
+
*/
|
|
1861
|
+
type FrameworkSecretsSourceConfig = Partial<SecretsSourceConfig>;
|
|
1862
|
+
/**
|
|
1863
|
+
* Framework-level named secrets source declarations keyed by source name.
|
|
1864
|
+
* Values may be partial or empty when the app only wants to declare expected names/types.
|
|
1865
|
+
*/
|
|
1866
|
+
type FrameworkSecretsModuleConfig = Record<string, FrameworkSecretsSourceConfig>;
|
|
1867
|
+
/**
|
|
1843
1868
|
* TODO: Let's see if we can do some clean inference and remove this!!!
|
|
1844
1869
|
*/
|
|
1845
1870
|
type SecretsSourceMap = Record<string, SecretsSource>;
|
|
@@ -2005,8 +2030,8 @@ type FrameworkConfig = {
|
|
|
2005
2030
|
logger?: Logger;
|
|
2006
2031
|
sso?: SSOConfig | null;
|
|
2007
2032
|
iam?: IAMConfig | null;
|
|
2008
|
-
workload?:
|
|
2009
|
-
secrets?:
|
|
2033
|
+
workload?: FrameworkWorkloadConfig | null;
|
|
2034
|
+
secrets?: FrameworkSecretsModuleConfig | null;
|
|
2010
2035
|
ciam?: CIAMConfig | null;
|
|
2011
2036
|
validators: ESValidators;
|
|
2012
2037
|
};
|
|
@@ -2029,6 +2054,10 @@ type RemoteConfig = {
|
|
|
2029
2054
|
secrets?: SecretsModuleConfig;
|
|
2030
2055
|
ciam?: CIAMConfig;
|
|
2031
2056
|
};
|
|
2057
|
+
type AggregateWorkload = Omit<Workload, "getToken"> & {
|
|
2058
|
+
getToken: (client: string, scope?: string) => Promise<string>;
|
|
2059
|
+
getServerToken: (scope?: string) => Promise<string>;
|
|
2060
|
+
};
|
|
2032
2061
|
/** Base shape shared by all EnterpriseStandard variants (modules optional for backward compatibility). */
|
|
2033
2062
|
type EnterpriseStandardBase = {
|
|
2034
2063
|
logger?: Logger;
|
|
@@ -2039,7 +2068,7 @@ type EnterpriseStandardBase = {
|
|
|
2039
2068
|
secrets?: Secrets;
|
|
2040
2069
|
sso?: SSO;
|
|
2041
2070
|
iam?: IAM;
|
|
2042
|
-
workload?: Workload;
|
|
2071
|
+
workload?: Workload | AggregateWorkload;
|
|
2043
2072
|
ciam?: CIAM;
|
|
2044
2073
|
/**
|
|
2045
2074
|
* Framework-agnostic request handler that routes requests to the appropriate
|
|
@@ -2061,7 +2090,7 @@ type EnterpriseStandard = EnterpriseStandardBase;
|
|
|
2061
2090
|
*
|
|
2062
2091
|
* @template TExtended - Type-safe custom data that consumers can add to magic links
|
|
2063
2092
|
*/
|
|
2064
|
-
type MagicLink<TExtended =
|
|
2093
|
+
type MagicLink<TExtended = object> = {
|
|
2065
2094
|
/**
|
|
2066
2095
|
* The magic link token (unique identifier)
|
|
2067
2096
|
*/
|
|
@@ -2119,7 +2148,7 @@ type MagicLink<TExtended = {}> = {
|
|
|
2119
2148
|
* }
|
|
2120
2149
|
* ```
|
|
2121
2150
|
*/
|
|
2122
|
-
interface MagicLinkStore<TExtended =
|
|
2151
|
+
interface MagicLinkStore<TExtended = object> {
|
|
2123
2152
|
/**
|
|
2124
2153
|
* Create a new magic link in the store.
|
|
2125
2154
|
*
|
package/dist/server.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as JM,B as LM,C as DM,D as jM,c as XM,d as YM,e,k as ZM,r as $M,s as HM,w as NM,x as VM,y as _M,z as GM}from"./shared/core-q2xp5jrk.js";function zM(O,L,D,h,q){if(!D&&!h)return;let E={...D,...h},Y={...E,signingKey:D?.signingKey,magicLinkTtl:E.magicLinkTtl??3600,sessionTtl:E.sessionTtl??86400,cookiesSecure:E.cookiesSecure!==void 0?E.cookiesSecure:!0,cookiesSameSite:E.cookiesSameSite!==void 0?E.cookiesSameSite:"Strict",cookiesPrefix:E.cookiesPrefix??(E.ciamId?`es.ciam.${E.ciamId}`:"es.ciam"),cookiesPath:E.cookiesPath??"/",sessionValidation:E.sessionValidation??"always"};function U(){if(!Y.signingKey)throw Error("Missing CIAM configuration field: signingKey. CIAM signingKey is required for JWT token signing and must be provided via Vault (ciam.signingKey).")}function g(){if(!Y.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and backchannel logout.");return Y.sessionStore}function m(){U(),g()}function i(M=32){let A=new Uint8Array(M);return crypto.getRandomValues(A),Array.from(A,(X)=>X.toString(16).padStart(2,"0")).join("").substring(0,M)}function l(M){let A=typeof M==="string"?new TextEncoder().encode(M):M,X="";return A.forEach((Z)=>{X+=String.fromCharCode(Z)}),btoa(X).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function t(M){let A=M.replace(/-/g,"+").replace(/_/g,"/"),X=A.padEnd(A.length+(4-A.length%4)%4,"=");return atob(X)}async function x(){U();let M=new TextEncoder().encode(Y.signingKey??"");return crypto.subtle.importKey("raw",M,{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}async function k(M){let X=l(JSON.stringify({alg:"HS256",typ:"JWT"})),Z=l(JSON.stringify(M)),W=`${X}.${Z}`,_=await x(),S=await crypto.subtle.sign("HMAC",_,new TextEncoder().encode(W)),I=l(new Uint8Array(S));return`${W}.${I}`}async function f(M){let A=M.split(".");if(A.length!==3)throw Error("Invalid JWT");let[X,Z,W]=A,_=`${X}.${Z}`,S=await x(),I=new Uint8Array(t(W).split("").map((T)=>T.charCodeAt(0)));if(!await crypto.subtle.verify("HMAC",S,I,new TextEncoder().encode(_)))throw Error("Invalid JWT signature");let u=t(Z),c=JSON.parse(u);if(typeof c.exp==="number"&&c.exp<Math.floor(Date.now()/1000))throw Error("Token expired");return c}function B(M,A,X){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");if(M=`${Y.cookiesPrefix}.${M}`,typeof A!=="string")A=btoa(JSON.stringify(A));let Z;if(X instanceof Date)Z=`Expires=${X.toUTCString()}`;else if(typeof X==="number")Z=`Max-Age=${X}`;else throw Error("Invalid expires type",X);if(A.length>4000)throw Error(`Error setting cookie: ${M}. Cookie length is: ${A.length}`);return`${M}=${A}; ${Z}; Path=${Y.cookiesPath}; HttpOnly;${Y.cookiesSecure?" Secure;":""} SameSite=${Y.cookiesSameSite};`}function j(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");return`${Y.cookiesPrefix}.${M}=; Max-Age=0; Path=${Y.cookiesPath}; HttpOnly;${Y.cookiesSecure?" Secure;":""} SameSite=${Y.cookiesSameSite};`}function G(M,A,X=!1){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");let Z=A.headers.get("cookie");if(!Z)return null;let W=`${Y.cookiesPrefix}.${M}`,_=Z.split(";").find((C)=>C.trim().startsWith(`${W}=`));if(!_)return null;let S=_.indexOf("="),I=_.substring(S+1).trim();if(!X)return I;try{let C=atob(I);return JSON.parse(C)}catch(C){return console.error(`[CIAM] Failed to parse cookie '${W}':`,C),null}}function P(M,A,X){let Z={expires_in:Y.sessionTtl??86400,token_type:"Bearer",expires:X.toISOString()};return[["Set-Cookie",B("access",M,X)],["Set-Cookie",B("id",A,X)],["Set-Cookie",B("control",Z,X)]]}function v(M){let A=G("access",M),X=G("id",M),Z=G("control",M,!0);if(!A||!X||!Z)return;if(Z.expires&&Date.now()>new Date(Z.expires).getTime())return;return{access:A,id:X,control:Z}}async function w(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let A=v(M);if(!A)return;let X=await f(A.access),Z=await f(A.id);if(!X.sid||!Z.sub)return;if(Y.sessionValidation!=="disabled"){if(!await g().get(X.sid))return}return z(Z)}catch(A){return}}async function b(M){let A=await w(M);if(A)return A;throw new Response("Unauthorized",{status:401,statusText:"Unauthorized"})}async function p(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let S=v(M);if(S){let I=await f(S.access);if(I.sid)await g().delete(I.sid)}}catch(S){console.warn("Failed to delete CIAM session:",S)}let A=[["Set-Cookie",j("access")],["Set-Cookie",j("id")],["Set-Cookie",j("control")]],Z=new URL(M.url).searchParams.get("redirect");if(Z)return new Response("Logged out",{status:302,headers:[["Location",Z],...A]});let W=M.headers.get("accept");if(W?.includes("application/json")||W?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out"}),{status:200,headers:[["Content-Type","application/json"],...A]});return new Response("Logout Complete",{status:200,headers:[["Content-Type","text/plain"],...A]})}async function y(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let A=M.headers.get("content-type");if(!A||!A.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let X=await M.text(),W=new URLSearchParams(X).get("logout_token");if(!W)return new Response("Missing logout_token parameter",{status:400});let S=(await f(W)).sid;if(!S)return new Response("Invalid logout_token: missing sid claim",{status:400});return await g().delete(S),new Response("OK",{status:200})}catch(A){return console.error("Error during CIAM back-channel logout:",A),new Response("Internal Server Error",{status:500})}}function K(M){return M.id||M.email||`ciam-${M.userName}`}function V(M,A,X){return{sub:K(M),iss:"ciam",aud:"ciam",exp:Math.floor(X.getTime()/1000),iat:Math.floor(Date.now()/1000),email:M.email,name:M.name,preferred_username:M.userName,picture:M.avatar,sid:A}}function Q(M,A,X){return{sub:M,iss:"ciam",aud:"ciam",exp:Math.floor(X.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:A,scope:"openid profile email"}}function z(M){let A=M.exp?new Date(M.exp*1000):new Date;return{id:M.sub,userName:M.preferred_username??"",name:M.name??"",email:M.email??"",avatar:M.picture,userType:"customer",sso:{profile:M,tenant:{id:"ciam",name:"CIAM"},scope:"openid profile email",tokenType:"Bearer",expires:A}}}async function F(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");if(!q)return new Response(JSON.stringify({error:"Workload authentication required"}),{status:401,headers:{"Content-Type":"application/json"}});if(!await q.getWorkloadIdentity(M))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let X,Z;try{let n=M.headers.get("content-type");if(!n||!n.includes("application/json"))return new Response(JSON.stringify({error:"Content-Type must be application/json"}),{status:400,headers:{"Content-Type":"application/json"}});let a=await M.text(),R=JSON.parse(a);if(Z=typeof R?.redirect==="string"&&R.redirect.length>0?R.redirect:void 0,X={userName:R.userName,name:R.name,email:R.email,avatar:R.avatar},!X.userName||!X.name||!X.email)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}})}catch(n){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let _=new URL(M.url).searchParams.get("ttl"),S=_?parseInt(_,10):Y.magicLinkTtl??3600;if(Number.isNaN(S)||S<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let I=i(32),C=new Date(Date.now()+S*1000);if(!Y.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:500,headers:{"Content-Type":"application/json"}});try{await Y.magicLinkStore.create(I,X,C)}catch(n){return console.error("Error creating magic link:",n),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let u=new URL(M.url),c=Y.magicLinkLoginUrl||"/magic-link/login",T=new URL(c,u.origin);if(T.searchParams.set("token",I),Z)T.searchParams.set("redirect",Z);return new Response(JSON.stringify({magicLink:T.toString(),expiresAt:C.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function H(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();let A=new URL(M.url),X=A.searchParams.get("token");if(!X){let J=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:J}})}if(!Y.magicLinkStore){let J=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:J}})}let Z=await Y.magicLinkStore.get(X);if(!Z){let J=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:J}})}let W=new Date(Date.now()+(Y.sessionTtl??86400)*1000),_=i(32),S=K(Z.user),I=V(Z.user,_,W),C=Q(S,_,W),u=z(I);try{let J={sid:_,sub:S,createdAt:new Date,lastActivityAt:new Date};await g().create(J)}catch(J){console.warn("Failed to create session:",J)}if(Y.userStore)try{let J=u.id;if(J){let r=new Date,s=await Y.userStore.get(J);if(s||Y.enableJitUserProvisioning){let FM={...s??{},...u,id:J,createdAt:s?.createdAt??r,updatedAt:r,userType:s?.userType??"customer"};await Y.userStore.upsert(FM)}}}catch(J){console.warn("Failed to store user:",J)}try{await Y.magicLinkStore.delete(X)}catch(J){console.warn("Failed to delete magic link:",J)}let c=await k(C),T=await k(I),n=Y.landingUrl||"/",a=A.searchParams.get("redirect"),R=n;if(a)if(a.startsWith("/"))R=a;else try{if(new URL(a).origin===new URL(M.url).origin)R=a}catch{}return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",R],...P(c,T,W)]})}async function $(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();let A=Y.magicLinkUrl||"/magic-link",X=Y.magicLinkLoginUrl||"/magic-link/login",Z=Y.logoutUrl||"/auth/logout",W=Y.logoutBackChannelUrl||"/auth/logout/backchannel",_=new URL(M.url).pathname,S=(T)=>{if(!T)return;try{return new URL(T).pathname}catch{return T.startsWith("/")?T:`/${T}`}};if(S(A)===_&&M.method==="POST")return F(M);if(S(X)===_&&M.method==="GET")return H(M);if(S(Z)===_&&M.method==="GET")return p(M);if(S(W)===_&&M.method==="POST")return y(M);return new Response("Not Found",{status:404})}return{...Y,getUser:w,getRequiredUser:b,logout:p,logoutBackChannel:y,handler:$}}async function BM(O,L){return e(L,"EnterpriseStandard instance is required. Create one with enterpriseStandard(source, config) and pass it to this function."),L.ciam?.getUser(O)}function N(O,L,D){return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:String(O),scimType:D,detail:L}),{status:O,headers:{"Content-Type":"application/scim+json"}})}function MM(O,L){let D=L?.totalResults??O.length,h=L?.startIndex??1,q=L?.itemsPerPage??O.length;return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:ListResponse"],totalResults:D,startIndex:h,itemsPerPage:q,Resources:O}),{status:200,headers:{"Content-Type":"application/scim+json"}})}function d(O,L=200){return new Response(JSON.stringify(O),{status:L,headers:{"Content-Type":"application/scim+json"}})}function o(O){return{schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],id:O.id,externalId:O.externalId,displayName:O.displayName,members:O.members,meta:{resourceType:"Group",created:O.createdAt.toISOString(),lastModified:O.updatedAt.toISOString()}}}function AM(){return crypto.randomUUID()}function KM(O,L,D,h,q){if(!h&&!q)return;let Y={...h,...q};function U(){if(!D)throw L.error?.("IAM requires workload configuration before use"),Error("IAM requires workload configuration");return D}async function g(){let B=await U().getToken();return new Headers({"Content-Type":"application/scim+json",Accept:"application/scim+json",Authorization:`Bearer ${B}`})}async function m(B,j,G,P){if(!Y.url)throw Error("IAM URL not configured for outgoing requests");let v=`${Y.url}${j}`;try{let w=await g(),b=await fetch(v,{method:B,headers:w,body:G?JSON.stringify(G):void 0}),p=await b.json();if(!b.ok)return{success:!1,error:p,status:b.status};let y=await P["~standard"].validate(p);if(y.issues)return console.error("SCIM response validation failed:",y.issues),{success:!1,error:{schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${y.issues.map((K)=>K.message).join("; ")}`},status:400};return{success:!0,data:y.value,status:b.status}}catch(w){return{success:!1,error:{schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:"500",detail:w instanceof Error?w.message:"Unknown error occurred"},status:500}}}function i(){return Y.url}let l,t;if(Y.url)t=async(j,G)=>{let P={...j,schemas:j.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return m("POST","/Users",P,O.user)},l={createGroup:async(j,G)=>{let P={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:j,externalId:G?.externalId,members:G?.members};return m("POST","/Groups",P,O.group)}};let x;if(Y.groupStore){let B=Y.groupStore,j=async(K)=>{let V=U(),Q=K.headers.get("Authorization");if(!Q||!Q.startsWith("Bearer "))return!1;try{let z=Q.substring(7);return(await V.validateToken(z)).valid}catch{return!1}},G=async(K,V)=>{if(!await j(K))return N(401,"Authorization required");let z=new URL(K.url),F=V?.basePath??"/Groups",H=z.pathname;if(H.startsWith(F))H=H.substring(F.length);let M=H.match(/^\/([^/]+)$/)?.[1],A=K.method;try{if(M)switch(A){case"GET":return await v(M);case"PUT":return await b(K,M);case"PATCH":return await p(K,M);case"DELETE":return await y(M);default:return N(405,"Method not allowed")}else if(H===""||H==="/")switch(A){case"GET":return await P(K);case"POST":return await w(K);default:return N(405,"Method not allowed")}return N(404,"Resource not found")}catch(X){return console.error("Groups inbound handler error:",X),N(500,X instanceof Error?X.message:"Internal server error")}},P=async(K)=>{let V=new URL(K.url),Q=V.searchParams.get("startIndex"),z=V.searchParams.get("count"),F=Q!=null?parseInt(Q,10):void 0,H=z!=null?parseInt(z,10):void 0,$=F!=null&&!Number.isNaN(F)?Math.max(0,F-1):0,M=H!=null&&!Number.isNaN(H)?H:void 0,A=await B.list({start:$,limit:M}),X=A.items.map(o);return MM(X,{totalResults:A.total,startIndex:$+1,itemsPerPage:A.count})},v=async(K)=>{let V=await B.get(K);if(!V)return N(404,`Group ${K} not found`,"invalidValue");return d(o(V))},w=async(K)=>{let V=await K.json(),Q=await O.group["~standard"].validate(V);if(Q.issues)return console.error("Group creation validation failed:",Q.issues),N(400,`Request validation failed: ${Q.issues.map(($)=>$.message).join("; ")}`,"invalidValue");let z=Q.value;if(!z.displayName)return N(400,"displayName is required","invalidValue");let F=new Date,H={id:AM(),displayName:z.displayName,externalId:z.externalId,members:z.members,createdAt:F,updatedAt:F};return await B.upsert(H),d(o(H),201)},b=async(K,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let z=await K.json(),F=await O.group["~standard"].validate(z);if(F.issues)return console.error("Group replacement validation failed:",F.issues),N(400,`Request validation failed: ${F.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let H=F.value,$={...Q,displayName:H.displayName??Q.displayName,externalId:H.externalId,members:H.members,updatedAt:new Date};return await B.upsert($),d(o($))},p=async(K,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let F=(await K.json()).Operations??[],H={...Q};for(let $ of F)if($.op==="replace"&&$.path&&$.value!==void 0){if($.path==="displayName")H.displayName=$.value}else if($.op==="add"&&$.path&&$.value!==void 0){if($.path==="members"){let M=$.value;H.members=[...H.members??[],...M]}}else if($.op==="remove"&&$.path){if($.path.startsWith("members[")){let M=$.path.match(/members\[value eq "([^"]+)"\]/);if(M)H.members=(H.members??[]).filter((A)=>A.value!==M[1])}}return H.updatedAt=new Date,await B.upsert(H),d(o(H))},y=async(K)=>{if(!await B.get(K))return N(404,`Group ${K} not found`,"invalidValue");return await B.delete(K),new Response(null,{status:204})};x={handler:G}}let k;if(Y.userStore){let B=Y.userStore,j=async(Q)=>{let z=U(),F=Q.headers.get("Authorization");if(!F||!F.startsWith("Bearer "))return!1;try{let H=F.substring(7);return(await z.validateToken(H)).valid}catch{return!1}},G=(Q)=>{return{schemas:["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"],id:Q.id,userName:Q.userName||Q.email||Q.id,displayName:Q.name||Q.userName||Q.email,name:Q.name?{givenName:Q.name.split(" ")[0],familyName:Q.name.split(" ").slice(1).join(" ")||void 0}:void 0,emails:Q.email?[{value:Q.email,primary:!0}]:[],active:!0,...Q.userType!=null&&{userType:Q.userType},meta:{resourceType:"User",created:Q.createdAt.toISOString(),lastModified:Q.updatedAt.toISOString()}}},P=(Q)=>{let z=new Date,F=Q.emails?.find((A)=>A.primary)?.value||Q.emails?.[0]?.value,H=Q.name?`${Q.name.givenName||""} ${Q.name.familyName||""}`.trim():Q.displayName,$=Q.id||AM(),M=Q.userName||F||$;return{id:$,userName:M,name:H||Q.displayName||M,email:F||M,avatar:Q.profileUrl,sso:{profile:{sub:$,iss:"iam-provisioned",aud:"iam-provisioned",exp:Math.floor(Date.now()/1000)+3600,iat:Math.floor(Date.now()/1000),email:F||M,email_verified:!0,name:H||Q.displayName||M,preferred_username:M},tenant:{id:"iam-provisioned",name:"IAM Provisioned"},scope:"openid profile email",tokenType:"Bearer",expires:new Date(Date.now()+3600000)},createdAt:Q.meta?.created?new Date(Q.meta.created):z,updatedAt:Q.meta?.lastModified?new Date(Q.meta.lastModified):z,...Q.userType!=null&&{userType:Q.userType}}},v=async(Q,z)=>{if(!await j(Q))return N(401,"Authorization required");let H=new URL(Q.url),$=z?.basePath??"/Users",M=H.pathname;if(M.startsWith($))M=M.substring($.length);let X=M.match(/^\/([^/]+)$/)?.[1],Z=Q.method;try{if(X)switch(Z){case"GET":return await b(X);case"PUT":return await y(Q,X);case"PATCH":return await K(Q,X);case"DELETE":return await V(X);default:return N(405,"Method not allowed")}else if(M===""||M==="/")switch(Z){case"GET":return await w(Q);case"POST":return await p(Q);default:return N(405,"Method not allowed")}return N(404,"Resource not found")}catch(W){return console.error("Users inbound handler error:",W),N(500,W instanceof Error?W.message:"Internal server error")}},w=async(Q)=>{let z=new URL(Q.url),F=z.searchParams.get("startIndex"),H=z.searchParams.get("count"),$=F!=null?parseInt(F,10):void 0,M=H!=null?parseInt(H,10):void 0,A=$!=null&&!Number.isNaN($)?Math.max(0,$-1):0,X=M!=null&&!Number.isNaN(M)?M:void 0,Z=await B.list({start:A,limit:X}),W=Z.items.map(G);return MM(W,{totalResults:Z.total,startIndex:A+1,itemsPerPage:Z.count})},b=async(Q)=>{let z=await B.get(Q);if(!z)return N(404,`User ${Q} not found`,"invalidValue");return d(G(z))},p=async(Q)=>{let z=await Q.json(),F=await O.user["~standard"].validate(z);if(F.issues)return console.error("User creation validation failed:",F.issues),N(400,`Request validation failed: ${F.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let H=F.value;if(!H.userName&&!H.emails?.[0]?.value)return N(400,"userName or email is required","invalidValue");let $=P(H);return await B.upsert($),d(G($),201)},y=async(Q,z)=>{let F=await B.get(z);if(!F)return N(404,`User ${z} not found`,"invalidValue");let H=await Q.json(),$=await O.user["~standard"].validate(H);if($.issues)return console.error("User replacement validation failed:",$.issues),N(400,`Request validation failed: ${$.issues.map((X)=>X.message).join("; ")}`,"invalidValue");let M=$.value,A=P({...M,id:z});return A.createdAt=F.createdAt,A.updatedAt=new Date,await B.upsert(A),d(G(A))},K=async(Q,z)=>{let F=await B.get(z);if(!F)return N(404,`User ${z} not found`,"invalidValue");let $=(await Q.json()).Operations??[],M={...F};for(let A of $)if(A.op==="replace"&&A.path&&A.value!==void 0){if(A.path==="displayName")M.name=A.value;else if(A.path==="userName")M.userName=A.value;else if(A.path.startsWith("name.")){let X=A.path.split(".")[1];if(!M.name)M.name="";if(X==="givenName")M.name=`${A.value} ${M.name.split(" ").slice(1).join(" ")}`.trim();else if(X==="familyName")M.name=`${M.name.split(" ")[0]} ${A.value}`.trim()}else if(A.path==="emails"){let X=A.value,Z=X?.find((W)=>W.primary)?.value||X?.[0]?.value;if(Z)M.email=Z}}else if(A.op==="add"&&A.path&&A.value!==void 0){if(A.path==="emails"){let X=A.value,Z=X?.find((W)=>W.primary)?.value||X?.[0]?.value;if(Z)M.email=Z}}else if(A.op==="remove"&&A.path){if(A.path==="displayName")M.name=""}return M.updatedAt=new Date,await B.upsert(M),d(G(M))},V=async(Q)=>{if(!await B.get(Q))return N(404,`User ${Q} not found`,"invalidValue");return await B.delete(Q),new Response(null,{status:204})};k={handler:v}}async function f(B,j){U();let P=new URL(B.url).pathname,v=j?.usersUrl??Y.usersUrl??"/api/iam/Users",w=j?.groupsUrl??Y.groupsUrl??"/api/iam/Groups";if(P.startsWith(v)&&k)return k.handler(B,{basePath:v});if(P.startsWith(w)&&x)return x.handler(B,{basePath:w});return N(404,"Resource not found")}return{...Y,createUser:t,getBaseUrl:i,groups_outbound:l,groups_inbound:x,users_inbound:k,handler:f}}var WM="@enterprisestandard/core",OM=YM(XM(WM));function QM(O){let L=O.replace(/-/g,"+").replace(/_/g,"/");return atob(L)}async function SM(O,L){let D=O.split(".");if(D.length!==3)throw Error("Invalid JWT");let h=JSON.parse(QM(D[0])),q=JSON.parse(QM(D[1])),E=D[2].replace(/-/g,"+").replace(/_/g,"/"),Y=h.kid;if(!Y)throw Error("JWT header missing kid");let U=await $M(L),g=await HM(U,Y),i=new TextEncoder().encode(`${D[0]}.${D[1]}`),l=Uint8Array.from(atob(E),(B)=>B.charCodeAt(0));if(!await crypto.subtle.verify("RSASSA-PKCS1-v1_5",g,l,i))throw Error("Invalid JWT signature");let x=await OM.validate(q);if(x.issues)throw Error(`ID token claims validation failed: ${x.issues.map((B)=>B.message).join("; ")}`);let k=x.value;if(k===void 0)throw Error("ID token claims missing");let f=k;if(typeof f.exp==="number"&&f.exp<Math.floor(Date.now()/1000))throw Error("Token expired");return ZM(f)}export{SM as verifyUser,NM as sso,jM as logoutBackChannel,DM as logout,JM as initiateLogin,KM as iam,_M as getSSOorCIAMUser,VM as getSSOUser,GM as getRequiredSSOorCIAMUser,BM as getCIAMUser,zM as ciam,LM as callback};
|
|
1
|
+
import{A as JM,B as LM,C as DM,D as jM,c as XM,d as YM,e,k as ZM,r as $M,s as HM,w as NM,x as VM,y as _M,z as GM}from"./shared/core-q2xp5jrk.js";function zM(O,D,j,h,q){if(!j&&!h)return;let E={...j,...h},Y={...E,signingKey:j?.signingKey,magicLinkTtl:E.magicLinkTtl??3600,sessionTtl:E.sessionTtl??86400,cookiesSecure:E.cookiesSecure!==void 0?E.cookiesSecure:!0,cookiesSameSite:E.cookiesSameSite!==void 0?E.cookiesSameSite:"Strict",cookiesPrefix:E.cookiesPrefix??(E.ciamId?`es.ciam.${E.ciamId}`:"es.ciam"),cookiesPath:E.cookiesPath??"/",sessionValidation:E.sessionValidation??"always"};function U(){if(!Y.signingKey)throw Error("Missing CIAM configuration field: signingKey. CIAM signingKey is required for JWT token signing and must be provided via Vault (ciam.signingKey).")}function g(){if(!Y.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and backchannel logout.");return Y.sessionStore}function m(){U(),g()}function i(M=32){let A=new Uint8Array(M);return crypto.getRandomValues(A),Array.from(A,(X)=>X.toString(16).padStart(2,"0")).join("").substring(0,M)}function l(M){let A=typeof M==="string"?new TextEncoder().encode(M):M,X="";return A.forEach((Z)=>{X+=String.fromCharCode(Z)}),btoa(X).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function t(M){let A=M.replace(/-/g,"+").replace(/_/g,"/"),X=A.padEnd(A.length+(4-A.length%4)%4,"=");return atob(X)}async function x(){U();let M=new TextEncoder().encode(Y.signingKey??"");return crypto.subtle.importKey("raw",M,{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}async function f(M){let X=l(JSON.stringify({alg:"HS256",typ:"JWT"})),Z=l(JSON.stringify(M)),W=`${X}.${Z}`,_=await x(),S=await crypto.subtle.sign("HMAC",_,new TextEncoder().encode(W)),I=l(new Uint8Array(S));return`${W}.${I}`}async function k(M){let A=M.split(".");if(A.length!==3)throw Error("Invalid JWT");let[X,Z,W]=A,_=`${X}.${Z}`,S=await x(),I=new Uint8Array(t(W).split("").map((T)=>T.charCodeAt(0)));if(!await crypto.subtle.verify("HMAC",S,I,new TextEncoder().encode(_)))throw Error("Invalid JWT signature");let u=t(Z),c=JSON.parse(u);if(typeof c.exp==="number"&&c.exp<Math.floor(Date.now()/1000))throw Error("Token expired");return c}function B(M,A,X){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");if(M=`${Y.cookiesPrefix}.${M}`,typeof A!=="string")A=btoa(JSON.stringify(A));let Z;if(X instanceof Date)Z=`Expires=${X.toUTCString()}`;else if(typeof X==="number")Z=`Max-Age=${X}`;else throw Error("Invalid expires type",X);if(A.length>4000)throw Error(`Error setting cookie: ${M}. Cookie length is: ${A.length}`);return`${M}=${A}; ${Z}; Path=${Y.cookiesPath}; HttpOnly;${Y.cookiesSecure?" Secure;":""} SameSite=${Y.cookiesSameSite};`}function G(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");return`${Y.cookiesPrefix}.${M}=; Max-Age=0; Path=${Y.cookiesPath}; HttpOnly;${Y.cookiesSecure?" Secure;":""} SameSite=${Y.cookiesSameSite};`}function J(M,A,X=!1){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");let Z=A.headers.get("cookie");if(!Z)return null;let W=`${Y.cookiesPrefix}.${M}`,_=Z.split(";").find((C)=>C.trim().startsWith(`${W}=`));if(!_)return null;let S=_.indexOf("="),I=_.substring(S+1).trim();if(!X)return I;try{let C=atob(I);return JSON.parse(C)}catch(C){return console.error(`[CIAM] Failed to parse cookie '${W}':`,C),null}}function P(M,A,X){let Z={expires_in:Y.sessionTtl??86400,token_type:"Bearer",expires:X.toISOString()};return[["Set-Cookie",B("access",M,X)],["Set-Cookie",B("id",A,X)],["Set-Cookie",B("control",Z,X)]]}function v(M){let A=J("access",M),X=J("id",M),Z=J("control",M,!0);if(!A||!X||!Z)return;if(Z.expires&&Date.now()>new Date(Z.expires).getTime())return;return{access:A,id:X,control:Z}}async function w(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let A=v(M);if(!A)return;let X=await k(A.access),Z=await k(A.id);if(!X.sid||!Z.sub)return;if(Y.sessionValidation!=="disabled"){if(!await g().get(X.sid))return}return z(Z)}catch(A){return}}async function b(M){let A=await w(M);if(A)return A;throw new Response("Unauthorized",{status:401,statusText:"Unauthorized"})}async function p(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let S=v(M);if(S){let I=await k(S.access);if(I.sid)await g().delete(I.sid)}}catch(S){console.warn("Failed to delete CIAM session:",S)}let A=[["Set-Cookie",G("access")],["Set-Cookie",G("id")],["Set-Cookie",G("control")]],Z=new URL(M.url).searchParams.get("redirect");if(Z)return new Response("Logged out",{status:302,headers:[["Location",Z],...A]});let W=M.headers.get("accept");if(W?.includes("application/json")||W?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out"}),{status:200,headers:[["Content-Type","application/json"],...A]});return new Response("Logout Complete",{status:200,headers:[["Content-Type","text/plain"],...A]})}async function y(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let A=M.headers.get("content-type");if(!A||!A.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let X=await M.text(),W=new URLSearchParams(X).get("logout_token");if(!W)return new Response("Missing logout_token parameter",{status:400});let S=(await k(W)).sid;if(!S)return new Response("Invalid logout_token: missing sid claim",{status:400});return await g().delete(S),new Response("OK",{status:200})}catch(A){return console.error("Error during CIAM back-channel logout:",A),new Response("Internal Server Error",{status:500})}}function K(M){return M.id||M.email||`ciam-${M.userName}`}function V(M,A,X){return{sub:K(M),iss:"ciam",aud:"ciam",exp:Math.floor(X.getTime()/1000),iat:Math.floor(Date.now()/1000),email:M.email,name:M.name,preferred_username:M.userName,picture:M.avatar,sid:A}}function Q(M,A,X){return{sub:M,iss:"ciam",aud:"ciam",exp:Math.floor(X.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:A,scope:"openid profile email"}}function z(M){let A=M.exp?new Date(M.exp*1000):new Date;return{id:M.sub,userName:M.preferred_username??"",name:M.name??"",email:M.email??"",avatar:M.picture,userType:"customer",sso:{profile:M,tenant:{id:"ciam",name:"CIAM"},scope:"openid profile email",tokenType:"Bearer",expires:A}}}async function F(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");if(!q)return new Response(JSON.stringify({error:"Workload authentication required"}),{status:401,headers:{"Content-Type":"application/json"}});if(!await q.getWorkloadIdentity(M))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let X,Z;try{let n=M.headers.get("content-type");if(!n||!n.includes("application/json"))return new Response(JSON.stringify({error:"Content-Type must be application/json"}),{status:400,headers:{"Content-Type":"application/json"}});let a=await M.text(),R=JSON.parse(a);if(Z=typeof R?.redirect==="string"&&R.redirect.length>0?R.redirect:void 0,X={userName:R.userName,name:R.name,email:R.email,avatar:R.avatar},!X.userName||!X.name||!X.email)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}})}catch(n){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let _=new URL(M.url).searchParams.get("ttl"),S=_?parseInt(_,10):Y.magicLinkTtl??3600;if(Number.isNaN(S)||S<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let I=i(32),C=new Date(Date.now()+S*1000);if(!Y.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:500,headers:{"Content-Type":"application/json"}});try{await Y.magicLinkStore.create(I,X,C)}catch(n){return console.error("Error creating magic link:",n),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let u=new URL(M.url),c=Y.magicLinkLoginUrl||"/magic-link/login",T=new URL(c,u.origin);if(T.searchParams.set("token",I),Z)T.searchParams.set("redirect",Z);return new Response(JSON.stringify({magicLink:T.toString(),expiresAt:C.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function H(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();let A=new URL(M.url),X=A.searchParams.get("token");if(!X){let L=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:L}})}if(!Y.magicLinkStore){let L=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:L}})}let Z=await Y.magicLinkStore.get(X);if(!Z){let L=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:L}})}let W=new Date(Date.now()+(Y.sessionTtl??86400)*1000),_=i(32),S=K(Z.user),I=V(Z.user,_,W),C=Q(S,_,W),u=z(I);try{let L={sid:_,sub:S,createdAt:new Date,lastActivityAt:new Date};await g().create(L)}catch(L){console.warn("Failed to create session:",L)}if(Y.userStore)try{let L=u.id;if(L){let r=new Date,s=await Y.userStore.get(L);if(s||Y.enableJitUserProvisioning){let FM={...s??{},...u,id:L,createdAt:s?.createdAt??r,updatedAt:r,userType:s?.userType??"customer"};await Y.userStore.upsert(FM)}}}catch(L){console.warn("Failed to store user:",L)}try{await Y.magicLinkStore.delete(X)}catch(L){console.warn("Failed to delete magic link:",L)}let c=await f(C),T=await f(I),n=Y.landingUrl||"/",a=A.searchParams.get("redirect"),R=n;if(a)if(a.startsWith("/"))R=a;else try{if(new URL(a).origin===new URL(M.url).origin)R=a}catch{}return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",R],...P(c,T,W)]})}async function $(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();let A=Y.magicLinkUrl||"/magic-link",X=Y.magicLinkLoginUrl||"/magic-link/login",Z=Y.logoutUrl||"/auth/logout",W=Y.logoutBackChannelUrl||"/auth/logout/backchannel",_=new URL(M.url).pathname,S=(T)=>{if(!T)return;try{return new URL(T).pathname}catch{return T.startsWith("/")?T:`/${T}`}};if(S(A)===_&&M.method==="POST")return F(M);if(S(X)===_&&M.method==="GET")return H(M);if(S(Z)===_&&M.method==="GET")return p(M);if(S(W)===_&&M.method==="POST")return y(M);return new Response("Not Found",{status:404})}return{...Y,getUser:w,getRequiredUser:b,logout:p,logoutBackChannel:y,handler:$}}async function BM(O,D){return e(D,"EnterpriseStandard instance is required. Create one with enterpriseStandard(source, config) and pass it to this function."),D.ciam?.getUser(O)}function N(O,D,j){return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:String(O),scimType:j,detail:D}),{status:O,headers:{"Content-Type":"application/scim+json"}})}function MM(O,D){let j=D?.totalResults??O.length,h=D?.startIndex??1,q=D?.itemsPerPage??O.length;return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:ListResponse"],totalResults:j,startIndex:h,itemsPerPage:q,Resources:O}),{status:200,headers:{"Content-Type":"application/scim+json"}})}function d(O,D=200){return new Response(JSON.stringify(O),{status:D,headers:{"Content-Type":"application/scim+json"}})}function o(O){return{schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],id:O.id,externalId:O.externalId,displayName:O.displayName,members:O.members,meta:{resourceType:"Group",created:O.createdAt.toISOString(),lastModified:O.updatedAt.toISOString()}}}function AM(){return crypto.randomUUID()}function KM(O,D,j,h,q){if(!h&&!q)return;let Y={...h,...q};function U(){if(!j)throw D.error?.("IAM requires workload configuration before use"),Error("IAM requires workload configuration");return j}async function g(){let B=U(),G=typeof B.getServerToken==="function"?await B.getServerToken():await B.getToken();return new Headers({"Content-Type":"application/scim+json",Accept:"application/scim+json",Authorization:`Bearer ${G}`})}async function m(B,G,J,P){if(!Y.url)throw Error("IAM URL not configured for outgoing requests");let v=`${Y.url}${G}`;try{let w=await g(),b=await fetch(v,{method:B,headers:w,body:J?JSON.stringify(J):void 0}),p=await b.json();if(!b.ok)return{success:!1,error:p,status:b.status};let y=await P["~standard"].validate(p);if(y.issues)return console.error("SCIM response validation failed:",y.issues),{success:!1,error:{schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${y.issues.map((K)=>K.message).join("; ")}`},status:400};return{success:!0,data:y.value,status:b.status}}catch(w){return{success:!1,error:{schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:"500",detail:w instanceof Error?w.message:"Unknown error occurred"},status:500}}}function i(){return Y.url}let l,t;if(Y.url)t=async(G,J)=>{let P={...G,schemas:G.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return m("POST","/Users",P,O.user)},l={createGroup:async(G,J)=>{let P={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:G,externalId:J?.externalId,members:J?.members};return m("POST","/Groups",P,O.group)}};let x;if(Y.groupStore){let B=Y.groupStore,G=async(K)=>{let V=U(),Q=K.headers.get("Authorization");if(!Q||!Q.startsWith("Bearer "))return!1;try{let z=Q.substring(7);return(await V.validateToken(z)).valid}catch{return!1}},J=async(K,V)=>{if(!await G(K))return N(401,"Authorization required");let z=new URL(K.url),F=V?.basePath??"/Groups",H=z.pathname;if(H.startsWith(F))H=H.substring(F.length);let M=H.match(/^\/([^/]+)$/)?.[1],A=K.method;try{if(M)switch(A){case"GET":return await v(M);case"PUT":return await b(K,M);case"PATCH":return await p(K,M);case"DELETE":return await y(M);default:return N(405,"Method not allowed")}else if(H===""||H==="/")switch(A){case"GET":return await P(K);case"POST":return await w(K);default:return N(405,"Method not allowed")}return N(404,"Resource not found")}catch(X){return console.error("Groups inbound handler error:",X),N(500,X instanceof Error?X.message:"Internal server error")}},P=async(K)=>{let V=new URL(K.url),Q=V.searchParams.get("startIndex"),z=V.searchParams.get("count"),F=Q!=null?parseInt(Q,10):void 0,H=z!=null?parseInt(z,10):void 0,$=F!=null&&!Number.isNaN(F)?Math.max(0,F-1):0,M=H!=null&&!Number.isNaN(H)?H:void 0,A=await B.list({start:$,limit:M}),X=A.items.map(o);return MM(X,{totalResults:A.total,startIndex:$+1,itemsPerPage:A.count})},v=async(K)=>{let V=await B.get(K);if(!V)return N(404,`Group ${K} not found`,"invalidValue");return d(o(V))},w=async(K)=>{let V=await K.json(),Q=await O.group["~standard"].validate(V);if(Q.issues)return console.error("Group creation validation failed:",Q.issues),N(400,`Request validation failed: ${Q.issues.map(($)=>$.message).join("; ")}`,"invalidValue");let z=Q.value;if(!z.displayName)return N(400,"displayName is required","invalidValue");let F=new Date,H={id:AM(),displayName:z.displayName,externalId:z.externalId,members:z.members,createdAt:F,updatedAt:F};return await B.upsert(H),d(o(H),201)},b=async(K,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let z=await K.json(),F=await O.group["~standard"].validate(z);if(F.issues)return console.error("Group replacement validation failed:",F.issues),N(400,`Request validation failed: ${F.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let H=F.value,$={...Q,displayName:H.displayName??Q.displayName,externalId:H.externalId,members:H.members,updatedAt:new Date};return await B.upsert($),d(o($))},p=async(K,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let F=(await K.json()).Operations??[],H={...Q};for(let $ of F)if($.op==="replace"&&$.path&&$.value!==void 0){if($.path==="displayName")H.displayName=$.value}else if($.op==="add"&&$.path&&$.value!==void 0){if($.path==="members"){let M=$.value;H.members=[...H.members??[],...M]}}else if($.op==="remove"&&$.path){if($.path.startsWith("members[")){let M=$.path.match(/members\[value eq "([^"]+)"\]/);if(M)H.members=(H.members??[]).filter((A)=>A.value!==M[1])}}return H.updatedAt=new Date,await B.upsert(H),d(o(H))},y=async(K)=>{if(!await B.get(K))return N(404,`Group ${K} not found`,"invalidValue");return await B.delete(K),new Response(null,{status:204})};x={handler:J}}let f;if(Y.userStore){let B=Y.userStore,G=async(Q)=>{let z=U(),F=Q.headers.get("Authorization");if(!F||!F.startsWith("Bearer "))return!1;try{let H=F.substring(7);return(await z.validateToken(H)).valid}catch{return!1}},J=(Q)=>{return{schemas:["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"],id:Q.id,userName:Q.userName||Q.email||Q.id,displayName:Q.name||Q.userName||Q.email,name:Q.name?{givenName:Q.name.split(" ")[0],familyName:Q.name.split(" ").slice(1).join(" ")||void 0}:void 0,emails:Q.email?[{value:Q.email,primary:!0}]:[],active:!0,...Q.userType!=null&&{userType:Q.userType},meta:{resourceType:"User",created:Q.createdAt.toISOString(),lastModified:Q.updatedAt.toISOString()}}},P=(Q)=>{let z=new Date,F=Q.emails?.find((A)=>A.primary)?.value||Q.emails?.[0]?.value,H=Q.name?`${Q.name.givenName||""} ${Q.name.familyName||""}`.trim():Q.displayName,$=Q.id||AM(),M=Q.userName||F||$;return{id:$,userName:M,name:H||Q.displayName||M,email:F||M,avatar:Q.profileUrl,sso:{profile:{sub:$,iss:"iam-provisioned",aud:"iam-provisioned",exp:Math.floor(Date.now()/1000)+3600,iat:Math.floor(Date.now()/1000),email:F||M,email_verified:!0,name:H||Q.displayName||M,preferred_username:M},tenant:{id:"iam-provisioned",name:"IAM Provisioned"},scope:"openid profile email",tokenType:"Bearer",expires:new Date(Date.now()+3600000)},createdAt:Q.meta?.created?new Date(Q.meta.created):z,updatedAt:Q.meta?.lastModified?new Date(Q.meta.lastModified):z,...Q.userType!=null&&{userType:Q.userType}}},v=async(Q,z)=>{if(!await G(Q))return N(401,"Authorization required");let H=new URL(Q.url),$=z?.basePath??"/Users",M=H.pathname;if(M.startsWith($))M=M.substring($.length);let X=M.match(/^\/([^/]+)$/)?.[1],Z=Q.method;try{if(X)switch(Z){case"GET":return await b(X);case"PUT":return await y(Q,X);case"PATCH":return await K(Q,X);case"DELETE":return await V(X);default:return N(405,"Method not allowed")}else if(M===""||M==="/")switch(Z){case"GET":return await w(Q);case"POST":return await p(Q);default:return N(405,"Method not allowed")}return N(404,"Resource not found")}catch(W){return console.error("Users inbound handler error:",W),N(500,W instanceof Error?W.message:"Internal server error")}},w=async(Q)=>{let z=new URL(Q.url),F=z.searchParams.get("startIndex"),H=z.searchParams.get("count"),$=F!=null?parseInt(F,10):void 0,M=H!=null?parseInt(H,10):void 0,A=$!=null&&!Number.isNaN($)?Math.max(0,$-1):0,X=M!=null&&!Number.isNaN(M)?M:void 0,Z=await B.list({start:A,limit:X}),W=Z.items.map(J);return MM(W,{totalResults:Z.total,startIndex:A+1,itemsPerPage:Z.count})},b=async(Q)=>{let z=await B.get(Q);if(!z)return N(404,`User ${Q} not found`,"invalidValue");return d(J(z))},p=async(Q)=>{let z=await Q.json(),F=await O.user["~standard"].validate(z);if(F.issues)return console.error("User creation validation failed:",F.issues),N(400,`Request validation failed: ${F.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let H=F.value;if(!H.userName&&!H.emails?.[0]?.value)return N(400,"userName or email is required","invalidValue");let $=P(H);return await B.upsert($),d(J($),201)},y=async(Q,z)=>{let F=await B.get(z);if(!F)return N(404,`User ${z} not found`,"invalidValue");let H=await Q.json(),$=await O.user["~standard"].validate(H);if($.issues)return console.error("User replacement validation failed:",$.issues),N(400,`Request validation failed: ${$.issues.map((X)=>X.message).join("; ")}`,"invalidValue");let M=$.value,A=P({...M,id:z});return A.createdAt=F.createdAt,A.updatedAt=new Date,await B.upsert(A),d(J(A))},K=async(Q,z)=>{let F=await B.get(z);if(!F)return N(404,`User ${z} not found`,"invalidValue");let $=(await Q.json()).Operations??[],M={...F};for(let A of $)if(A.op==="replace"&&A.path&&A.value!==void 0){if(A.path==="displayName")M.name=A.value;else if(A.path==="userName")M.userName=A.value;else if(A.path.startsWith("name.")){let X=A.path.split(".")[1];if(!M.name)M.name="";if(X==="givenName")M.name=`${A.value} ${M.name.split(" ").slice(1).join(" ")}`.trim();else if(X==="familyName")M.name=`${M.name.split(" ")[0]} ${A.value}`.trim()}else if(A.path==="emails"){let X=A.value,Z=X?.find((W)=>W.primary)?.value||X?.[0]?.value;if(Z)M.email=Z}}else if(A.op==="add"&&A.path&&A.value!==void 0){if(A.path==="emails"){let X=A.value,Z=X?.find((W)=>W.primary)?.value||X?.[0]?.value;if(Z)M.email=Z}}else if(A.op==="remove"&&A.path){if(A.path==="displayName")M.name=""}return M.updatedAt=new Date,await B.upsert(M),d(J(M))},V=async(Q)=>{if(!await B.get(Q))return N(404,`User ${Q} not found`,"invalidValue");return await B.delete(Q),new Response(null,{status:204})};f={handler:v}}async function k(B,G){U();let P=new URL(B.url).pathname,v=G?.usersUrl??Y.usersUrl??"/api/iam/Users",w=G?.groupsUrl??Y.groupsUrl??"/api/iam/Groups";if(P.startsWith(v)&&f)return f.handler(B,{basePath:v});if(P.startsWith(w)&&x)return x.handler(B,{basePath:w});return N(404,"Resource not found")}return{...Y,createUser:t,getBaseUrl:i,groups_outbound:l,groups_inbound:x,users_inbound:f,handler:k}}var WM="@enterprisestandard/core",OM=YM(XM(WM));function QM(O){let D=O.replace(/-/g,"+").replace(/_/g,"/");return atob(D)}async function SM(O,D){let j=O.split(".");if(j.length!==3)throw Error("Invalid JWT");let h=JSON.parse(QM(j[0])),q=JSON.parse(QM(j[1])),E=j[2].replace(/-/g,"+").replace(/_/g,"/"),Y=h.kid;if(!Y)throw Error("JWT header missing kid");let U=await $M(D),g=await HM(U,Y),i=new TextEncoder().encode(`${j[0]}.${j[1]}`),l=Uint8Array.from(atob(E),(B)=>B.charCodeAt(0));if(!await crypto.subtle.verify("RSASSA-PKCS1-v1_5",g,l,i))throw Error("Invalid JWT signature");let x=await OM.validate(q);if(x.issues)throw Error(`ID token claims validation failed: ${x.issues.map((B)=>B.message).join("; ")}`);let f=x.value;if(f===void 0)throw Error("ID token claims missing");let k=f;if(typeof k.exp==="number"&&k.exp<Math.floor(Date.now()/1000))throw Error("Token expired");return ZM(k)}export{SM as verifyUser,NM as sso,jM as logoutBackChannel,DM as logout,JM as initiateLogin,KM as iam,_M as getSSOorCIAMUser,VM as getSSOUser,GM as getRequiredSSOorCIAMUser,BM as getCIAMUser,zM as ciam,LM as callback};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enterprisestandard/core",
|
|
3
|
-
"version": "0.0.9
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Enterprise Standard Core (Server-only)",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "enterprisestandard",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@enterprisestandard/zod": "0.0.9
|
|
31
|
-
"@enterprisestandard/valibot": "0.0.9
|
|
30
|
+
"@enterprisestandard/zod": "^0.0.9",
|
|
31
|
+
"@enterprisestandard/valibot": "^0.0.9"
|
|
32
32
|
}
|
|
33
33
|
}
|