@enterprisestandard/core 0.0.9-beta.20260303.7 → 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 +269 -430
- package/dist/index.js +1 -1
- package/dist/server.d.ts +60 -181
- package/dist/server.js +1 -1
- package/dist/shared/{core-5zzt9q6h.js → core-q2xp5jrk.js} +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as j,b as S,c,d as B,e as L0,f as x0,g as _0,h as A0,i as B0,j as W0,k as K0,l as z0,m as C0,n as D0,o as R0,p as w0,q as U0,t as q0,u as E0,v as T0}from"./shared/core-5zzt9q6h.js";var r="0.0.9-beta.20260303.7";function J($,X,Q,Z,G){if($===void 0||$===null){if(Q)Z.push({message:`${X} is required`,path:G});return}if(typeof $!=="string"){Z.push({message:`${X} must be a string`,path:G});return}return $}function T($,X,Q,Z){if($===void 0||$===null)return;if(typeof $!=="boolean"){Q.push({message:`${X} must be a boolean`,path:Z});return}return $}function l($,X,Q){if($===void 0||$===null)return;if(typeof $!=="object"||$===null){X.push({message:"name must be an object",path:Q});return}let Z=$,G={};return G.formatted=J(Z.formatted,"formatted",!1,X,[...Q,"formatted"]),G.familyName=J(Z.familyName,"familyName",!1,X,[...Q,"familyName"]),G.givenName=J(Z.givenName,"givenName",!1,X,[...Q,"givenName"]),G.middleName=J(Z.middleName,"middleName",!1,X,[...Q,"middleName"]),G.honorificPrefix=J(Z.honorificPrefix,"honorificPrefix",!1,X,[...Q,"honorificPrefix"]),G.honorificSuffix=J(Z.honorificSuffix,"honorificSuffix",!1,X,[...Q,"honorificSuffix"]),G}function u($,X,Q){if($===void 0||$===null)return;if(!Array.isArray($)){X.push({message:"emails must be an array",path:Q});return}let Z=[];for(let G=0;G<$.length;G++){let F=$[G],H=[...Q,G];if(typeof F!=="object"||F===null){X.push({message:"email must be an object",path:H});continue}let M=F,Y=J(M.value,"value",!0,X,[...H,"value"]);if(Y)Z.push({value:Y,display:J(M.display,"display",!1,X,[...H,"display"]),type:J(M.type,"type",!1,X,[...H,"type"]),primary:T(M.primary,"primary",X,[...H,"primary"])})}return Z.length>0?Z:void 0}function i($,X,Q){if($===void 0||$===null)return;if(!Array.isArray($)){X.push({message:"phoneNumbers must be an array",path:Q});return}let Z=[];for(let G=0;G<$.length;G++){let F=$[G],H=[...Q,G];if(typeof F!=="object"||F===null){X.push({message:"phoneNumber must be an object",path:H});continue}let M=F,Y=J(M.value,"value",!0,X,[...H,"value"]);if(Y)Z.push({value:Y,display:J(M.display,"display",!1,X,[...H,"display"]),type:J(M.type,"type",!1,X,[...H,"type"]),primary:T(M.primary,"primary",X,[...H,"primary"])})}return Z.length>0?Z:void 0}function t($,X,Q){if($===void 0||$===null)return;if(!Array.isArray($)){X.push({message:"addresses must be an array",path:Q});return}let Z=[];for(let G=0;G<$.length;G++){let F=$[G],H=[...Q,G];if(typeof F!=="object"||F===null){X.push({message:"address must be an object",path:H});continue}let M=F;Z.push({formatted:J(M.formatted,"formatted",!1,X,[...H,"formatted"]),streetAddress:J(M.streetAddress,"streetAddress",!1,X,[...H,"streetAddress"]),locality:J(M.locality,"locality",!1,X,[...H,"locality"]),region:J(M.region,"region",!1,X,[...H,"region"]),postalCode:J(M.postalCode,"postalCode",!1,X,[...H,"postalCode"]),country:J(M.country,"country",!1,X,[...H,"country"]),type:J(M.type,"type",!1,X,[...H,"type"]),primary:T(M.primary,"primary",X,[...H,"primary"])})}return Z.length>0?Z:void 0}function a($,X,Q){if($===void 0||$===null)return;if(!Array.isArray($)){X.push({message:"groups must be an array",path:Q});return}let Z=[];for(let G=0;G<$.length;G++){let F=$[G],H=[...Q,G];if(typeof F!=="object"||F===null){X.push({message:"group must be an object",path:H});continue}let M=F,Y=J(M.value,"value",!0,X,[...H,"value"]);if(Y)Z.push({value:Y,$ref:J(M.$ref,"$ref",!1,X,[...H,"$ref"]),display:J(M.display,"display",!1,X,[...H,"display"]),type:J(M.type,"type",!1,X,[...H,"type"])})}return Z.length>0?Z:void 0}function s($,X,Q){if($===void 0||$===null)return;if(!Array.isArray($)){X.push({message:"roles must be an array",path:Q});return}let Z=[];for(let G=0;G<$.length;G++){let F=$[G],H=[...Q,G];if(typeof F!=="object"||F===null){X.push({message:"role must be an object",path:H});continue}let M=F,Y=J(M.value,"value",!0,X,[...H,"value"]);if(Y)Z.push({value:Y,display:J(M.display,"display",!1,X,[...H,"display"]),type:J(M.type,"type",!1,X,[...H,"type"]),primary:T(M.primary,"primary",X,[...H,"primary"])})}return Z.length>0?Z:void 0}function e($,X,Q){if($===void 0||$===null)return;if(typeof $!=="object"||$===null){X.push({message:"Enterprise User extension must be an object",path:Q});return}let Z=$,G={};if(G.employeeNumber=J(Z.employeeNumber,"employeeNumber",!1,X,[...Q,"employeeNumber"]),G.costCenter=J(Z.costCenter,"costCenter",!1,X,[...Q,"costCenter"]),G.organization=J(Z.organization,"organization",!1,X,[...Q,"organization"]),G.division=J(Z.division,"division",!1,X,[...Q,"division"]),G.department=J(Z.department,"department",!1,X,[...Q,"department"]),Z.manager!==void 0&&Z.manager!==null)if(typeof Z.manager!=="object"||Z.manager===null)X.push({message:"manager must be an object",path:[...Q,"manager"]});else{let F=Z.manager;G.manager={value:J(F.value,"value",!1,X,[...Q,"manager","value"]),$ref:J(F.$ref,"$ref",!1,X,[...Q,"manager","$ref"]),displayName:J(F.displayName,"displayName",!1,X,[...Q,"manager","displayName"])}}return G}function O($){return{"~standard":{version:1,vendor:$,validate:(X)=>{if(typeof X!=="object"||X===null)return{issues:[{message:"Expected an object"}]};let Q=X,Z=[],G={},F=J(Q.userName,"userName",!0,Z,["userName"]);if(!F)return{issues:Z};G.userName=F,G.id=J(Q.id,"id",!1,Z,["id"]),G.externalId=J(Q.externalId,"externalId",!1,Z,["externalId"]),G.displayName=J(Q.displayName,"displayName",!1,Z,["displayName"]),G.nickName=J(Q.nickName,"nickName",!1,Z,["nickName"]),G.profileUrl=J(Q.profileUrl,"profileUrl",!1,Z,["profileUrl"]),G.title=J(Q.title,"title",!1,Z,["title"]),G.userType=J(Q.userType,"userType",!1,Z,["userType"]),G.preferredLanguage=J(Q.preferredLanguage,"preferredLanguage",!1,Z,["preferredLanguage"]),G.locale=J(Q.locale,"locale",!1,Z,["locale"]),G.timezone=J(Q.timezone,"timezone",!1,Z,["timezone"]),G.password=J(Q.password,"password",!1,Z,["password"]),G.active=T(Q.active,"active",Z,["active"]),G.name=l(Q.name,Z,["name"]),G.emails=u(Q.emails,Z,["emails"]),G.phoneNumbers=i(Q.phoneNumbers,Z,["phoneNumbers"]),G.addresses=t(Q.addresses,Z,["addresses"]),G.groups=a(Q.groups,Z,["groups"]),G.roles=s(Q.roles,Z,["roles"]);let H="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User";if(Q[H]!==void 0)G[H]=e(Q[H],Z,[H]);if(Q.schemas!==void 0)if(Array.isArray(Q.schemas))G.schemas=Q.schemas.filter((M)=>typeof M==="string");else Z.push({message:"schemas must be an array",path:["schemas"]});if(Q.meta!==void 0)if(typeof Q.meta==="object"&&Q.meta!==null){let M=Q.meta;G.meta={resourceType:typeof M.resourceType==="string"?M.resourceType:void 0,created:typeof M.created==="string"?M.created:void 0,lastModified:typeof M.lastModified==="string"?M.lastModified:void 0,location:typeof M.location==="string"?M.location:void 0,version:typeof M.version==="string"?M.version:void 0}}else Z.push({message:"meta must be an object",path:["meta"]});if(Z.length>0)return{issues:Z};return{value:G}}}}}function Q0($,X,Q){if($===void 0||$===null)return;if(!Array.isArray($)){X.push({message:"members must be an array",path:Q});return}let Z=[];for(let G=0;G<$.length;G++){let F=$[G],H=[...Q,G];if(typeof F!=="object"||F===null){X.push({message:"member must be an object",path:H});continue}let M=F,Y=J(M.value,"value",!0,X,[...H,"value"]);if(Y){let _=J(M.type,"type",!1,X,[...H,"type"]);Z.push({value:Y,$ref:J(M.$ref,"$ref",!1,X,[...H,"$ref"]),display:J(M.display,"display",!1,X,[...H,"display"]),type:_==="User"||_==="Group"?_:void 0})}}return Z.length>0?Z:void 0}function V($){return{"~standard":{version:1,vendor:$,validate:(X)=>{if(typeof X!=="object"||X===null)return{issues:[{message:"Expected an object"}]};let Q=X,Z=[],G={},F=J(Q.displayName,"displayName",!0,Z,["displayName"]);if(!F)return{issues:Z};if(G.displayName=F,G.id=J(Q.id,"id",!1,Z,["id"]),G.externalId=J(Q.externalId,"externalId",!1,Z,["externalId"]),G.members=Q0(Q.members,Z,["members"]),Q.schemas!==void 0)if(Array.isArray(Q.schemas))G.schemas=Q.schemas.filter((H)=>typeof H==="string");else Z.push({message:"schemas must be an array",path:["schemas"]});if(Q.meta!==void 0)if(typeof Q.meta==="object"&&Q.meta!==null){let H=Q.meta;G.meta={resourceType:typeof H.resourceType==="string"?H.resourceType:void 0,created:typeof H.created==="string"?H.created:void 0,lastModified:typeof H.lastModified==="string"?H.lastModified:void 0,location:typeof H.location==="string"?H.location:void 0,version:typeof H.version==="string"?H.version:void 0}}else Z.push({message:"meta must be an object",path:["meta"]});if(Z.length>0)return{issues:Z};return{value:G}}}}}function f($){return{"~standard":{version:1,vendor:$,validate:(X)=>{if(typeof X!=="object"||X===null)return{issues:[{message:"Expected an object"}]};let Q=X,Z=[],G={...Q},F=["iss","sub"];for(let Y of F)if(Y in Q){if(typeof Q[Y]!=="string")Z.push({message:`${Y} must be a string`,path:[Y]})}else Z.push({message:`${Y} is required`,path:[Y]});if("aud"in Q&&Q.aud!==void 0){let Y=Q.aud;if(typeof Y!=="string"&&!Array.isArray(Y))Z.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(Y)&&!Y.every((_)=>typeof _==="string"))Z.push({message:"aud array must contain only strings",path:["aud"]})}let H=["jti","scope"];for(let Y of H)if(Y in Q&&Q[Y]!==void 0){if(typeof Q[Y]!=="string")Z.push({message:`${Y} must be a string`,path:[Y]})}let M=["exp","iat"];for(let Y of M)if(Y in Q){if(typeof Q[Y]!=="number")Z.push({message:`${Y} must be a number`,path:[Y]})}else Z.push({message:`${Y} is required`,path:[Y]});if(Z.length>0)return{issues:Z};return{value:G}}}}}function y($){return{"~standard":{version:1,vendor:$,validate:(X)=>{if(typeof X!=="object"||X===null)return{issues:[{message:"Expected an object"}]};let Q=X,Z=[],G={};if("access_token"in Q)if(typeof Q.access_token==="string")G.access_token=Q.access_token;else Z.push({message:"access_token must be a string",path:["access_token"]});else Z.push({message:"access_token is required",path:["access_token"]});if("token_type"in Q)if(typeof Q.token_type==="string")G.token_type=Q.token_type;else Z.push({message:"token_type must be a string",path:["token_type"]});else Z.push({message:"token_type is required",path:["token_type"]});if("scope"in Q)if(typeof Q.scope==="string"||Q.scope===void 0)G.scope=Q.scope;else Z.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in Q)if(typeof Q.refresh_token==="string"||Q.refresh_token===void 0)G.refresh_token=Q.refresh_token;else Z.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in Q)if(typeof Q.expires==="string"||Q.expires===void 0)G.expires=Q.expires;else Z.push({message:"expires must be a string",path:["expires"]});if("expires_in"in Q)if(typeof Q.expires_in==="number"||Q.expires_in===void 0)G.expires_in=Q.expires_in;else Z.push({message:"expires_in must be a number",path:["expires_in"]});if(Z.length>0)return{issues:Z};return{value:G}}}}}var K="@enterprisestandard/core",g=["POC","DEV","QA","PROD"],h=["pending","processing","completed","failed","action_required"];function X0(){return{"~standard":{version:1,vendor:K,validate($){if(typeof $!=="object"||$===null)return{issues:[{message:"Expected object"}]};let X=$,Q=[],Z=(D,E)=>{if(typeof X[D]!=="string"){Q.push({message:`${D} must be a string`,path:E});return}return X[D]},G=Z("tenantId",["tenantId"]),F=Z("companyId",["companyId"]),H=Z("companyName",["companyName"]),M=Z("email",["email"]),Y=Z("webhookUrl",["webhookUrl"]),_=Z("callbackUrl",["callbackUrl"]),z=X.tenantUrl,C=X.environmentType;if(typeof C!=="string"||!g.includes(C))Q.push({message:`environmentType must be one of ${g.join(", ")}`,path:["environmentType"]});if(z!==void 0&&typeof z!=="string")Q.push({message:"tenantUrl must be a string",path:["tenantUrl"]});if(Q.length>0)return{issues:Q};if(G===void 0||F===void 0||H===void 0||M===void 0||Y===void 0||_===void 0)return{issues:[{message:"Missing required string fields"}]};return{value:{tenantId:G,companyId:F,companyName:H,environmentType:C,email:M,webhookUrl:Y,callbackUrl:_,tenantUrl:z}}}}}}function Z0(){return{"~standard":{version:1,vendor:K,validate($){if(typeof $!=="object"||$===null)return{issues:[{message:"Expected object"}]};let X=$,Q=[],Z=(Y,_)=>{if(typeof X[Y]!=="string"){Q.push({message:`${Y} must be a string`,path:_});return}return X[Y]},G=Z("userName",["userName"]),F=Z("name",["name"]),H=Z("email",["email"]);if(X.id!==void 0&&typeof X.id!=="string")Q.push({message:"id must be a string",path:["id"]});if(X.avatar!==void 0&&typeof X.avatar!=="string")Q.push({message:"avatar must be a string",path:["avatar"]});if(X.userType!==void 0&&typeof X.userType!=="string")Q.push({message:"userType must be a string",path:["userType"]});if(Q.length>0)return{issues:Q};if(G===void 0||F===void 0||H===void 0)return{issues:[{message:"Missing required fields: userName, name, email"}]};let M={userName:G,name:F,email:H};if(typeof X.id==="string")M.id=X.id;if(typeof X.avatar==="string")M.avatar=X.avatar;if(typeof X.userType==="string")M.userType=X.userType;return{value:M}}}}}function $0(){return{"~standard":{validate($){if(typeof $!=="object"||$===null)return{issues:[{message:"Expected object"}]};let X=$,Q=[],Z=X.status;if(typeof Z!=="string"||!h.includes(Z))Q.push({message:`status must be one of ${h.join(", ")}`,path:["status"]});if(Z==="action_required"){if(typeof X.actionUrl!=="string")Q.push({message:"actionUrl must be a string",path:["actionUrl"]});if(typeof X.requestToken!=="string")Q.push({message:"requestToken must be a string",path:["requestToken"]});if(typeof X.expiresAt!=="string")Q.push({message:"expiresAt must be a string",path:["expiresAt"]});if(Q.length>0)return{issues:Q};return{value:{status:"action_required",actionUrl:X.actionUrl,requestToken:X.requestToken,expiresAt:X.expiresAt}}}if(typeof X.tenantUrl!=="string")Q.push({message:"tenantUrl must be a string",path:["tenantUrl"]});if(Q.length>0)return{issues:Q};return{value:{tenantUrl:X.tenantUrl,status:Z}}}}}}function P(){return{sso:{callbackParams:B(j(K)),idTokenClaims:B(c(K)),tokenResponse:B(S(K))},iam:{user:B(O(K)),group:B(V(K))},workload:{jwtAssertionClaims:B(f(K)),tokenResponse:B(y(K))},tenant:{createTenantRequest:B(X0())},ciam:{baseUser:B(Z0())}}}var G0=["sessionStore","userStore","groupStore","tokenStore","magicLinkStore"];function p($){if($===null||typeof $!=="object")return $;let X={};for(let[Q,Z]of Object.entries($)){if(G0.includes(Q)||Q==="validators")continue;X[Q]=Z!==null&&typeof Z==="object"&&!Array.isArray(Z)&&Object.getPrototypeOf(Z)===Object.prototype?p(Z):Z}return X}function H0($){return p($)}function N($,X,Q,Z){let G=X.length,F=Z??$,H=F>0?Math.floor(Q/F)+1:1,M=F>0?Math.ceil($/F):0;return{total:$,count:G,items:X,size:F,page:H,pages:M}}class q extends Error{constructor($,X){super($,X);this.name="TenantRequestError",Object.setPrototypeOf(this,q.prototype)}}function M0($,X,Q,Z){if(!Q&&!Z)return;let G={...Q,...Z},F={...G,signingKey:Q?.signingKey,requestTokenTtl:Q?.requestTokenTtl??G.requestTokenTtl??3600};function H(){if(!F.signingKey)throw Error("Missing tenant configuration field: signingKey. Tenant request tokens require a signingKey provided via Vault (tenant.signingKey).")}function M(L){let x=typeof L==="string"?new TextEncoder().encode(L):L,A="";return x.forEach((W)=>{A+=String.fromCharCode(W)}),btoa(A).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function Y(L){let x=L.replace(/-/g,"+").replace(/_/g,"/"),A=x.padEnd(x.length+(4-x.length%4)%4,"=");return atob(A)}async function _(){H();let L=new TextEncoder().encode(F.signingKey??"");return crypto.subtle.importKey("raw",L,{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}async function z(L){let A=M(JSON.stringify({alg:"HS256",typ:"JWT"})),W=M(JSON.stringify(L)),R=`${A}.${W}`,w=await _(),U=await crypto.subtle.sign("HMAC",w,new TextEncoder().encode(R)),k=M(new Uint8Array(U));return`${R}.${k}`}async function C(L){let x=L.split(".");if(x.length!==3)throw Error("Invalid JWT");let[A,W,R]=x,w=`${A}.${W}`,U=await _(),k=new Uint8Array(Y(R).split("").map((o)=>o.charCodeAt(0)));if(!await crypto.subtle.verify("HMAC",U,k,new TextEncoder().encode(w)))throw Error("Invalid JWT signature");let d=Y(W),I=JSON.parse(d);if(typeof I.exp==="number"&&I.exp<Math.floor(Date.now()/1000))throw Error("Token expired");return I}async function D(L){if(L.method!=="POST")throw Error("Only POST method is supported");let x;try{x=await L.json()}catch(W){throw Error("Invalid JSON in request body")}if(typeof x!=="object"||x===null)throw Error("Request body must be an object");let A=await $.createTenantRequest["~standard"].validate(x);if(A.issues)return A;return A}async function E(L,x){return b(L,x,X)}return{...F,parseTenantRequest:D,sendTenantWebhook:E,async createRequestToken(L,x,A){let W=Math.floor(Date.now()/1000),R=A??F.requestTokenTtl??3600,w=W+R,U={tenantId:L,callbackUrl:x,iat:W,exp:w};return{token:await z(U),expiresAt:new Date(w*1000),payload:U}},async verifyRequestToken(L){return await C(L)}}}async function F0($){let X=P().tenant;if($.method!=="POST")throw new q("Only POST method is supported");let Q;try{Q=await $.json()}catch(Z){throw new q("Invalid JSON in request body")}if(typeof Q!=="object"||Q===null)throw new q("Request body must be an object");return X.createTenantRequest["~standard"].validate(Q)}function b($,X,Q){return(async()=>{try{let Z=await fetch($,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(X)});if(!Z.ok)Q.error(`Failed to send webhook update: ${Z.status} ${Z.statusText}`)}catch(Z){Q.error("Failed to send webhook update:",Z)}})()}async function J0($,X,Q){return b($,X,Q)}class v{tenants=new Map;companyIdIndex=new Map;async get($){return this.tenants.get($)??null}async getByCompanyId($,X){let Q=this.companyIdIndex.get($);if(!Q||Q.size===0)return N(0,[],Math.max(0,X?.start??0),X?.limit);let Z=[];for(let G of Q){let F=this.tenants.get(G);if(F)Z.push(F)}return m(Z,X)}async list($){let X=Array.from(this.tenants.values());return m(X,$)}async upsert($){let X=this.tenants.get($.tenantId);if(X&&X.companyId!==$.companyId){let Z=this.companyIdIndex.get(X.companyId);if(Z){if(Z.delete($.tenantId),Z.size===0)this.companyIdIndex.delete(X.companyId)}}this.tenants.set($.tenantId,$);let Q=this.companyIdIndex.get($.companyId);if(!Q)Q=new Set,this.companyIdIndex.set($.companyId,Q);return Q.add($.tenantId),$}async delete($){let X=this.tenants.get($);if(X){let Q=this.companyIdIndex.get(X.companyId);if(Q){if(Q.delete($),Q.size===0)this.companyIdIndex.delete(X.companyId)}}this.tenants.delete($)}}function m($,X){let Q=Math.max(0,X?.start??0),Z=X?.limit,G=$;if(X?.sort?.length)G=[...$].sort((Y,_)=>{for(let{field:z,direction:C}of X.sort){let D=Y[z],E=_[z],L=Y0(D,E);if(L!==0)return C==="desc"?-L:L}return 0});let F=G.length,H=Z!=null?Q+Z:void 0,M=G.slice(Q,H);return N(F,M,Q,Z)}function Y0($,X){let Q=$===void 0||$===null,Z=X===void 0||X===null;if(Q&&Z)return 0;if(Q)return 1;if(Z)return-1;if($ instanceof Date&&X instanceof Date)return $.getTime()-X.getTime();return String($).localeCompare(String(X))}export{y as workloadTokenResponseSchema,B as withValidate,W0 as waitOn,r as version,x0 as validationFailureResponse,O as userSchema,S as tokenResponseSchema,M0 as tenant,A0 as stripJsonComments,D0 as silentLogger,E0 as setActiveSession,H0 as serializeESConfig,J0 as sendTenantWebhook,F0 as parseTenantRequest,B0 as parseJsonc,j as oidcCallbackSchema,L0 as must,_0 as mergeConfig,N as list,f as jwtAssertionClaimsSchema,R0 as infoLogger,c as idTokenClaimsSchema,V as groupResourceSchema,q0 as getActiveSession,T0 as findTenantFromStateParam,C0 as defaultLogger,z0 as decodeUser,w0 as debugLogger,P as createValidators,$0 as createTenantResponseValidator,U0 as consoleLogger,K0 as claimsToUser,q as TenantRequestError,v 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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StandardSchemaV1 as
|
|
1
|
+
import { StandardSchemaV1 as StandardSchemaV17 } from "@standard-schema/spec";
|
|
2
2
|
import { StandardSchemaV1 as StandardSchemaV15 } from "@standard-schema/spec";
|
|
3
3
|
/**
|
|
4
4
|
* Minimal logger interface compatible with common patterns (console, pino, winston, etc.)
|
|
@@ -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
|
*
|
|
@@ -1735,161 +1750,6 @@ declare function initiateLogin(config: LoginConfig, es: EnterpriseStandard): Pro
|
|
|
1735
1750
|
declare function callback(request: Request, es: EnterpriseStandard): Promise<Response>;
|
|
1736
1751
|
declare function logout(request: Request, es: EnterpriseStandard): Promise<Response>;
|
|
1737
1752
|
declare function logoutBackChannel2(request: Request, es: EnterpriseStandard): Promise<Response>;
|
|
1738
|
-
import { StandardSchemaV1 as StandardSchemaV17 } from "@standard-schema/spec";
|
|
1739
|
-
/**
|
|
1740
|
-
* Environment type for tenant creation
|
|
1741
|
-
*/
|
|
1742
|
-
type EnvironmentType = "POC" | "DEV" | "QA" | "PROD";
|
|
1743
|
-
/**
|
|
1744
|
-
* Status of tenant creation process
|
|
1745
|
-
*/
|
|
1746
|
-
type TenantStatus = "pending" | "processing" | "completed" | "failed" | "action_required";
|
|
1747
|
-
/**
|
|
1748
|
-
* Request payload sent by a TMR (e.g. ESV or control plane) for creating a tenant
|
|
1749
|
-
*/
|
|
1750
|
-
interface CreateTenantRequest {
|
|
1751
|
-
/**
|
|
1752
|
-
* Required app identifier to use when initializing EnterpriseStandard for this tenant.
|
|
1753
|
-
* This is the primary identifier for tenant management. A company can have multiple
|
|
1754
|
-
* applications (e.g., one instance on the east coast, one on the west coast).
|
|
1755
|
-
*/
|
|
1756
|
-
tenantId: string;
|
|
1757
|
-
/**
|
|
1758
|
-
* Company ID (used for reporting purposes only, not for tenant identification)
|
|
1759
|
-
*/
|
|
1760
|
-
companyId: string;
|
|
1761
|
-
/**
|
|
1762
|
-
* Company Name
|
|
1763
|
-
*/
|
|
1764
|
-
companyName: string;
|
|
1765
|
-
/**
|
|
1766
|
-
* Environment Type (POC, DEV, QA, PROD)
|
|
1767
|
-
*/
|
|
1768
|
-
environmentType: EnvironmentType;
|
|
1769
|
-
/**
|
|
1770
|
-
* Email (The email or distribution list used to communicate to the team)
|
|
1771
|
-
*/
|
|
1772
|
-
email: string;
|
|
1773
|
-
/**
|
|
1774
|
-
* Webhook URL where the application can send updates concerning the creation of the tenant
|
|
1775
|
-
*/
|
|
1776
|
-
webhookUrl: string;
|
|
1777
|
-
/**
|
|
1778
|
-
* Callback URL where the customer should be redirected after completing TMS steps
|
|
1779
|
-
*/
|
|
1780
|
-
callbackUrl: string;
|
|
1781
|
-
/**
|
|
1782
|
-
* URL that the tenant will be available at (optional; deployer may allocate)
|
|
1783
|
-
*/
|
|
1784
|
-
tenantUrl?: string;
|
|
1785
|
-
}
|
|
1786
|
-
/**
|
|
1787
|
-
* Payload sent to webhook URL for status updates
|
|
1788
|
-
*/
|
|
1789
|
-
interface TenantWebhookPayload {
|
|
1790
|
-
/**
|
|
1791
|
-
* Tenant ID (primary identifier)
|
|
1792
|
-
*/
|
|
1793
|
-
tenantId: string;
|
|
1794
|
-
/**
|
|
1795
|
-
* Company ID
|
|
1796
|
-
*/
|
|
1797
|
-
companyId: string;
|
|
1798
|
-
/**
|
|
1799
|
-
* Current status of tenant creation
|
|
1800
|
-
*/
|
|
1801
|
-
status: TenantStatus;
|
|
1802
|
-
/**
|
|
1803
|
-
* URL that the tenant will be available at (provided once creation completes)
|
|
1804
|
-
*/
|
|
1805
|
-
tenantUrl?: string;
|
|
1806
|
-
/**
|
|
1807
|
-
* URL where the customer should provide additional information
|
|
1808
|
-
*/
|
|
1809
|
-
actionUrl?: string;
|
|
1810
|
-
/**
|
|
1811
|
-
* Signed request token for the action flow
|
|
1812
|
-
*/
|
|
1813
|
-
requestToken?: string;
|
|
1814
|
-
/**
|
|
1815
|
-
* ISO timestamp when the request token expires
|
|
1816
|
-
*/
|
|
1817
|
-
expiresAt?: string;
|
|
1818
|
-
/**
|
|
1819
|
-
* Error message (only present if status is "failed")
|
|
1820
|
-
*/
|
|
1821
|
-
error?: string;
|
|
1822
|
-
}
|
|
1823
|
-
/**
|
|
1824
|
-
* Validators for tenant management
|
|
1825
|
-
*/
|
|
1826
|
-
type TenantValidators = {
|
|
1827
|
-
createTenantRequest: StandardSchemaV17<unknown, CreateTenantRequest>;
|
|
1828
|
-
};
|
|
1829
|
-
/**
|
|
1830
|
-
* Configuration for tenant management
|
|
1831
|
-
*/
|
|
1832
|
-
type TenantConfig = {
|
|
1833
|
-
/**
|
|
1834
|
-
* Vault-only signing key used for request token signing
|
|
1835
|
-
*/
|
|
1836
|
-
signingKey?: string;
|
|
1837
|
-
/**
|
|
1838
|
-
* Default TTL (seconds) for request tokens
|
|
1839
|
-
*/
|
|
1840
|
-
requestTokenTtl?: number;
|
|
1841
|
-
};
|
|
1842
|
-
/** Tenant config that code may provide; excludes signingKey (vault-only). */
|
|
1843
|
-
type TenantConfigFromCode = Omit<TenantConfig, "signingKey">;
|
|
1844
|
-
type TenantRequestTokenPayload = {
|
|
1845
|
-
tenantId: string;
|
|
1846
|
-
callbackUrl: string;
|
|
1847
|
-
exp: number;
|
|
1848
|
-
iat: number;
|
|
1849
|
-
};
|
|
1850
|
-
/**
|
|
1851
|
-
* Tenant service interface
|
|
1852
|
-
*/
|
|
1853
|
-
type Tenant = TenantConfig & {
|
|
1854
|
-
/**
|
|
1855
|
-
* Parse and validate a tenant creation request from an HTTP request.
|
|
1856
|
-
* Returns a validation result object with either `issues` (if validation fails) or `value` (if validation succeeds).
|
|
1857
|
-
*
|
|
1858
|
-
* @param request - The HTTP request containing the tenant creation data
|
|
1859
|
-
* @returns Validation result with either `issues` array or `value` containing the validated request
|
|
1860
|
-
*
|
|
1861
|
-
* @example
|
|
1862
|
-
* ```typescript
|
|
1863
|
-
* app.post('/api/tenant', async (c) => {
|
|
1864
|
-
* const result = await tenantService.parseTenantRequest(c.req.raw);
|
|
1865
|
-
* if (result.issues) {
|
|
1866
|
-
* return validationFailureResponse(result.issues, 'Tenant request validation failed');
|
|
1867
|
-
* }
|
|
1868
|
-
* // Use result.value as CreateTenantRequest
|
|
1869
|
-
* });
|
|
1870
|
-
* ```
|
|
1871
|
-
*/
|
|
1872
|
-
parseTenantRequest: (request: Request) => Promise<StandardSchemaV17.Result<CreateTenantRequest>>;
|
|
1873
|
-
/**
|
|
1874
|
-
* Send a webhook update to ESVS with tenant creation status.
|
|
1875
|
-
*
|
|
1876
|
-
* @param webhookUrl - The webhook URL provided in the tenant creation request
|
|
1877
|
-
* @param payload - The webhook payload with status and tenant information
|
|
1878
|
-
*/
|
|
1879
|
-
sendTenantWebhook: (webhookUrl: string, payload: TenantWebhookPayload) => Promise<void>;
|
|
1880
|
-
/**
|
|
1881
|
-
* Create a signed request token for the action_required flow
|
|
1882
|
-
*/
|
|
1883
|
-
createRequestToken: (tenantId: string, callbackUrl: string, ttlSeconds?: number) => Promise<{
|
|
1884
|
-
token: string;
|
|
1885
|
-
expiresAt: Date;
|
|
1886
|
-
payload: TenantRequestTokenPayload;
|
|
1887
|
-
}>;
|
|
1888
|
-
/**
|
|
1889
|
-
* Verify a signed request token and return its payload
|
|
1890
|
-
*/
|
|
1891
|
-
verifyRequestToken: (token: string) => Promise<TenantRequestTokenPayload>;
|
|
1892
|
-
};
|
|
1893
1753
|
type Secret<T> = {
|
|
1894
1754
|
data: T;
|
|
1895
1755
|
metadata: MetaData;
|
|
@@ -1995,6 +1855,16 @@ type Secrets = {
|
|
|
1995
1855
|
handleLfvEvents?(request: Request): Promise<Response>;
|
|
1996
1856
|
};
|
|
1997
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
|
+
/**
|
|
1998
1868
|
* TODO: Let's see if we can do some clean inference and remove this!!!
|
|
1999
1869
|
*/
|
|
2000
1870
|
type SecretsSourceMap = Record<string, SecretsSource>;
|
|
@@ -2145,7 +2015,6 @@ type ESValidators = {
|
|
|
2145
2015
|
sso: SSOValidators;
|
|
2146
2016
|
iam: IAMValidators;
|
|
2147
2017
|
workload: WorkloadValidators;
|
|
2148
|
-
tenant: TenantValidators;
|
|
2149
2018
|
ciam: CIAMValidators;
|
|
2150
2019
|
secrets?: SecretsValidators;
|
|
2151
2020
|
};
|
|
@@ -2153,16 +2022,18 @@ type ESValidators = {
|
|
|
2153
2022
|
* Configuration supplied by the framework/application when creating an Enterprise Standard instance.
|
|
2154
2023
|
* Merged with RemoteConfig from the ConfigSource (framework config wins). Pass as the second
|
|
2155
2024
|
* argument to enterpriseStandard(source, config).
|
|
2025
|
+
* Set a module to `null` to explicitly disable it; then the corresponding property on the
|
|
2026
|
+
* EnterpriseStandard instance is typed as `never`. Omit a module to allow it to be supplied
|
|
2027
|
+
* from ConfigSource / adaptive (typed as the module type, non-optional).
|
|
2156
2028
|
*/
|
|
2157
2029
|
type FrameworkConfig = {
|
|
2158
2030
|
logger?: Logger;
|
|
2159
|
-
sso?: SSOConfig;
|
|
2160
|
-
iam?: IAMConfig;
|
|
2161
|
-
workload?:
|
|
2162
|
-
secrets?:
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
validators?: ESValidators;
|
|
2031
|
+
sso?: SSOConfig | null;
|
|
2032
|
+
iam?: IAMConfig | null;
|
|
2033
|
+
workload?: FrameworkWorkloadConfig | null;
|
|
2034
|
+
secrets?: FrameworkSecretsModuleConfig | null;
|
|
2035
|
+
ciam?: CIAMConfig | null;
|
|
2036
|
+
validators: ESValidators;
|
|
2166
2037
|
};
|
|
2167
2038
|
/**
|
|
2168
2039
|
* Remote config read from a config source (vault, lfv, etc.).
|
|
@@ -2181,10 +2052,14 @@ type RemoteConfig = {
|
|
|
2181
2052
|
workload?: WorkloadConfig | WorkloadConfigMap | WorkloadIncomingOutgoing;
|
|
2182
2053
|
/** Optional named secrets-source configs available to this ESA instance. */
|
|
2183
2054
|
secrets?: SecretsModuleConfig;
|
|
2184
|
-
tenant?: TenantConfig;
|
|
2185
2055
|
ciam?: CIAMConfig;
|
|
2186
2056
|
};
|
|
2187
|
-
type
|
|
2057
|
+
type AggregateWorkload = Omit<Workload, "getToken"> & {
|
|
2058
|
+
getToken: (client: string, scope?: string) => Promise<string>;
|
|
2059
|
+
getServerToken: (scope?: string) => Promise<string>;
|
|
2060
|
+
};
|
|
2061
|
+
/** Base shape shared by all EnterpriseStandard variants (modules optional for backward compatibility). */
|
|
2062
|
+
type EnterpriseStandardBase = {
|
|
2188
2063
|
logger?: Logger;
|
|
2189
2064
|
/** App/tenant identifier when provided by ConfigSource (e.g. vault). */
|
|
2190
2065
|
tenantId?: string;
|
|
@@ -2193,25 +2068,29 @@ type EnterpriseStandard = {
|
|
|
2193
2068
|
secrets?: Secrets;
|
|
2194
2069
|
sso?: SSO;
|
|
2195
2070
|
iam?: IAM;
|
|
2196
|
-
workload?: Workload;
|
|
2197
|
-
tenants?: Tenant;
|
|
2071
|
+
workload?: Workload | AggregateWorkload;
|
|
2198
2072
|
ciam?: CIAM;
|
|
2199
2073
|
/**
|
|
2200
2074
|
* Framework-agnostic request handler that routes requests to the appropriate
|
|
2201
2075
|
* module (SSO, IAM, Workload, or CIAM) based on the configured URLs.
|
|
2202
2076
|
*/
|
|
2203
2077
|
handler: (request: Request) => Promise<Response>;
|
|
2078
|
+
/** Returns a promise that resolves when configured at least once. If timeout is > 0, rejects after timeout ms. */
|
|
2079
|
+
ready(timeout?: number): Promise<void>;
|
|
2080
|
+
/** Returns true once config has been applied at least once, false otherwise. */
|
|
2081
|
+
isReady(): boolean;
|
|
2204
2082
|
/** When present (e.g. from server enterpriseStandard), reload config from the config source and reapply. */
|
|
2205
2083
|
reload?(): Promise<void>;
|
|
2206
2084
|
/** When present (e.g. from server enterpriseStandard), merge config then reload from the config source and reapply. */
|
|
2207
2085
|
reconfigure?(config?: FrameworkConfig): Promise<void>;
|
|
2208
2086
|
};
|
|
2087
|
+
type EnterpriseStandard = EnterpriseStandardBase;
|
|
2209
2088
|
/**
|
|
2210
2089
|
* Magic link data stored in the store.
|
|
2211
2090
|
*
|
|
2212
2091
|
* @template TExtended - Type-safe custom data that consumers can add to magic links
|
|
2213
2092
|
*/
|
|
2214
|
-
type MagicLink<TExtended =
|
|
2093
|
+
type MagicLink<TExtended = object> = {
|
|
2215
2094
|
/**
|
|
2216
2095
|
* The magic link token (unique identifier)
|
|
2217
2096
|
*/
|
|
@@ -2269,7 +2148,7 @@ type MagicLink<TExtended = {}> = {
|
|
|
2269
2148
|
* }
|
|
2270
2149
|
* ```
|
|
2271
2150
|
*/
|
|
2272
|
-
interface MagicLinkStore<TExtended =
|
|
2151
|
+
interface MagicLinkStore<TExtended = object> {
|
|
2273
2152
|
/**
|
|
2274
2153
|
* Create a new magic link in the store.
|
|
2275
2154
|
*
|
|
@@ -2301,8 +2180,8 @@ interface MagicLinkStore<TExtended = {}> {
|
|
|
2301
2180
|
* baseUser includes a top-level .validate() for a cleaner API (see withValidate).
|
|
2302
2181
|
*/
|
|
2303
2182
|
type CIAMValidators = {
|
|
2304
|
-
baseUser:
|
|
2305
|
-
validate(value: unknown): Promise<
|
|
2183
|
+
baseUser: StandardSchemaV17<unknown, BaseUser> & {
|
|
2184
|
+
validate(value: unknown): Promise<StandardSchemaV17.Result<BaseUser>>;
|
|
2306
2185
|
};
|
|
2307
2186
|
};
|
|
2308
2187
|
type CIAMConfig<
|
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-5zzt9q6h.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};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
function JX(Y){return{"~standard":{version:1,vendor:Y,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,A=[],N={};if("code"in X)if(typeof X.code==="string")N.code=X.code;else A.push({message:"code must be a string",path:["code"]});else if(!("error"in X))A.push({message:"code is required",path:["code"]});if("state"in X)if(typeof X.state==="string"||X.state===void 0)N.state=X.state;else A.push({message:"state must be a string",path:["state"]});if("session_state"in X)if(typeof X.session_state==="string"||X.session_state===void 0)N.session_state=X.session_state;else A.push({message:"session_state must be a string",path:["session_state"]});if("error"in X){if(typeof X.error==="string")N.error=X.error;else A.push({message:"error must be a string",path:["error"]});if("error_description"in X)if(typeof X.error_description==="string"||X.error_description===void 0)N.error_description=X.error_description;else A.push({message:"error_description must be a string",path:["error_description"]});if("error_uri"in X)if(typeof X.error_uri==="string"||X.error_uri===void 0)N.error_uri=X.error_uri;else A.push({message:"error_uri must be a string",path:["error_uri"]})}if("iss"in X)if(typeof X.iss==="string"||X.iss===void 0)N.iss=X.iss;else A.push({message:"iss must be a string",path:["iss"]});if(A.length>0)return{issues:A};return{value:N}}}}}function FX(Y){return{"~standard":{version:1,vendor:Y,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,A=[],N={};if("access_token"in X)if(typeof X.access_token==="string")N.access_token=X.access_token;else A.push({message:"access_token must be a string",path:["access_token"]});else A.push({message:"access_token is required",path:["access_token"]});if("id_token"in X)if(typeof X.id_token==="string")N.id_token=X.id_token;else A.push({message:"id_token must be a string",path:["id_token"]});else A.push({message:"id_token is required",path:["id_token"]});if("token_type"in X)if(typeof X.token_type==="string")N.token_type=X.token_type;else A.push({message:"token_type must be a string",path:["token_type"]});else A.push({message:"token_type is required",path:["token_type"]});if("refresh_token"in X)if(typeof X.refresh_token==="string"||X.refresh_token===void 0)N.refresh_token=X.refresh_token;else A.push({message:"refresh_token must be a string",path:["refresh_token"]});if("scope"in X)if(typeof X.scope==="string"||X.scope===void 0)N.scope=X.scope;else A.push({message:"scope must be a string",path:["scope"]});if("session_state"in X)if(typeof X.session_state==="string"||X.session_state===void 0)N.session_state=X.session_state;else A.push({message:"session_state must be a string",path:["session_state"]});if("expires"in X)if(typeof X.expires==="string"||X.expires===void 0)N.expires=X.expires;else A.push({message:"expires must be a string",path:["expires"]});if("expires_in"in X)if(typeof X.expires_in==="number"||X.expires_in===void 0)N.expires_in=X.expires_in;else A.push({message:"expires_in must be a number",path:["expires_in"]});if("refresh_expires_in"in X)if(typeof X.refresh_expires_in==="number"||X.refresh_expires_in===void 0)N.refresh_expires_in=X.refresh_expires_in;else A.push({message:"refresh_expires_in must be a number",path:["refresh_expires_in"]});if(A.length>0)return{issues:A};return{value:N}}}}}function n(Y){return{"~standard":{version:1,vendor:Y,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,A=[],N={...X},M=["iss","aud","sub","sid","name","email","preferred_username","picture"];for(let H of M)if(H in X&&X[H]!==void 0){if(typeof X[H]!=="string")A.push({message:`${H} must be a string`,path:[H]})}let $=["exp","iat"];for(let H of $)if(H in X&&X[H]!==void 0){if(typeof X[H]!=="number")A.push({message:`${H} must be a number`,path:[H]})}if(A.length>0)return{issues:A};return{value:N}}}}}function t(Y){let Z=Y["~standard"];return Object.assign({},Y,{validate(X){return Promise.resolve(Z.validate(X))}})}function D(Y,Z="Assertion failed. Required value is null or undefined."){if(Y===void 0||Y===null)throw Error(Z);return Y}function i(Y,Z){return Response.json({error:"validation_failed",message:Z,issues:Y},{status:400,headers:{"Content-Type":"application/json"}})}function jX(Y,Z,X=[]){let A={...Y,...Z};for(let N of X)A[N]=Y?.[N]??Z?.[N];return A}function QX(Y){let Z="",X=0,A=Y.length;while(X<A){let N=Y[X];if(N==='"'||N==="'"){let M=N;Z+=N,X++;while(X<A){let $=Y[X];if($==="\\"){if(Z+=$,X+1<A)Z+=Y[X+1],X+=2;else X++;continue}if($===M){Z+=$,X++;break}Z+=$,X++}continue}if(N==="/"&&X+1<A){let M=Y[X+1];if(M==="/"){X+=2;while(X<A&&Y[X]!==`
|
|
2
2
|
`)X++;if(X<A)Z+=`
|
|
3
|
-
`;X++;continue}if(M==="*"){X+=2;while(X+1<A&&!(Y[X]==="*"&&Y[X+1]==="/"))X++;X+=2;continue}}Z+=N,X++}return Z}function DX(Y){let Z=QX(Y);return JSON.parse(Z)}async function EX(Y,Z=1000,X=1e4,A){let N=Date.now(),M="Awaiting Ping";return new Promise(($,H)=>{let P=null,w=null,C=async()=>{try{let I=await fetch(Y);if(I.ok){if(P)clearInterval(P);if(w)clearInterval(w);$()}else M=`Response error: ${I.status}: ${I.statusText}`}catch(I){M
|
|
3
|
+
`;X++;continue}if(M==="*"){X+=2;while(X+1<A&&!(Y[X]==="*"&&Y[X+1]==="/"))X++;X+=2;continue}}Z+=N,X++}return Z}function DX(Y){let Z=QX(Y);return JSON.parse(Z)}async function EX(Y,Z=1000,X=1e4,A){let N=Date.now(),M="Awaiting Ping";return new Promise(($,H)=>{let P=null,w=null,C=async()=>{try{let I=await fetch(Y);if(I.ok){if(P)clearInterval(P);if(w)clearInterval(w);$()}else M=`Response error: ${I.status}: ${I.statusText} - ${Y}`}catch(I){M=`${I instanceof Error?I.message:String(I)} - ${Y}`}};if(C(),P=setInterval(C,Z),X>0)w=setInterval(()=>{console.warn(`${M}: ${Date.now()-N}ms`)},X);if(A)setTimeout(()=>{if(P)clearInterval(P);if(w)clearInterval(w);H(Error(`Timeout: ${A}ms: ${M}`))},A)})}var BX="@enterprisestandard/core",WX=t(n(BX));function MX(Y){let Z=Y.exp!=null?new Date(Y.exp*1000):new Date,X=Y.iss??"";return{id:Y.sub??"",userName:Y.preferred_username??"",name:Y.name??"",email:Y.email??"",avatar:Y.picture,sso:{profile:{...Y,iss:Y.iss??X,aud:Y.aud},tenant:{id:Y.idp??X,name:X},tokenType:"Bearer",expires:Z}}}function LX(Y){let Z=Y.replace(/-/g,"+").replace(/_/g,"/");return atob(Z)}async function _X(Y){let Z=Y.split(".");if(Z.length!==3)throw Error("Invalid JWT");let X=LX(Z[1]),A=JSON.parse(X),N=await WX.validate(A);if(N.issues)throw Error(`ID token claims validation failed: ${N.issues.map((M)=>M.message).join("; ")}`);if(N.value)return MX(N.value);throw Error("ID token claims validation failed")}var x=(Y,Z,...X)=>{if(X.length>0)console[Y](`[${Y.toUpperCase()}]`,Z,...X);else console[Y](`[${Y.toUpperCase()}]`,Z)},a={debug:()=>{},info:()=>{},warn(Y,...Z){x("warn",Y,...Z)},error(Y,...Z){x("error",Y,...Z)}},IX={debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}},TX={debug:()=>{},info:x.bind(console,"info"),warn:x.bind(console,"warn"),error:x.bind(console,"error")},o=(Y,...Z)=>{if(Z.length>0)console.log("[DEBUG]",Y,...Z);else console.log("[DEBUG]",Y)},wX={debug:o,info:x.bind(console,"info"),warn:x.bind(console,"warn"),error:x.bind(console,"error")},yX={debug:o,info:x.bind(console,"info"),warn:x.bind(console,"warn"),error:x.bind(console,"error")};var r=new Map;async function p(Y,Z=3,X=1000,A=30000){let N=Error("Placeholder Error");for(let M=0;M<=Z;M++)try{return await Y()}catch($){if(N=$ instanceof Error?$:Error(String($)),$ instanceof Error&&$.message.includes("400"))throw $;if(M===Z)throw N;let H=Math.min(X*2**M,A),P=Math.random()*0.1*H;await new Promise((w)=>setTimeout(w,H+P)),console.warn(`Retry attempt ${M+1} after ${H+P}ms delay`)}throw N}async function s(Y){let Z=r.get(Y);if(Z)return Z;return p(async()=>{let X=await fetch(Y);if(!X.ok)throw Error("Failed to fetch JWKS");let A=await X.json();return r.set(Y,A),A})}async function e(Y,Z){let X=Y.keys.find((A)=>A.kid===Z);if(!X)throw Error("Public key not found");return crypto.subtle.importKey("jwk",{kty:X.kty,n:X.n,e:X.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}function UX(Y,Z={}){let X=Z.cookieName??"es.active_session",A=Y.headers.get("cookie");if(!A)return;return YX(A)[X]}function hX(Y,Z={}){let X=Z.cookieName??"es.active_session",A=Z.path??"/",N=Z.secure??!1,M=Z.sameSite??"Lax",$=Z.maxAge,H=[`${X}=${Y}`,`Path=${A}`,"HttpOnly",`SameSite=${M}`];if(N)H.push("Secure");if(typeof $==="number")H.push(`Max-Age=${$}`);return H.join("; ")}function fX(Y,Z){if(!Y)return;let X=YX(Y);for(let[A,N]of Object.entries(X)){if(!A.startsWith("es.sso.")||!A.endsWith(".state"))continue;try{let M=JSON.parse(atob(N));if(M?.state===Z)return{clientId:A.slice(7,-6),stateCookie:M}}catch{}}return}function kX(Y,Z,X,A){if(!X&&!A)return;let N={...X,...A},M=!!(N.authority&&N.tokenUrl&&N.authorizationUrl&&N.clientId&&N.redirectUri&&N.scope),$={...N,authority:M?D(N.authority,"Missing 'authority' from SSO Config"):N.authority,tokenUrl:M?D(N.tokenUrl,"Missing 'tokenUrl' from SSO Config"):N.tokenUrl,authorizationUrl:M?D(N.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):N.authorizationUrl,clientId:M?D(N.clientId,"Missing 'clientId' from SSO Config"):N.clientId,redirectUri:M?D(N.redirectUri,"Missing 'redirectUri' from SSO Config"):N.redirectUri,scope:M?D(N.scope,"Missing 'scope' from SSO Config"):N.scope,responseType:N.responseType??"code",cookiesSecure:N.cookiesSecure!==void 0?N.cookiesSecure:!0,cookiesSameSite:N.cookiesSameSite!==void 0?N.cookiesSameSite:"Strict",cookiesPrefix:N.cookiesPrefix??(N.clientId?`es.sso.${N.clientId}`:"es.sso"),cookiesPath:N.cookiesPath??"/"};function H(){let K=[];if(!$.authority)K.push("authority");if(!$.tokenUrl)K.push("tokenUrl");if(!$.authorizationUrl)K.push("authorizationUrl");if(!$.clientId)K.push("clientId");if(!$.redirectUri)K.push("redirectUri");if(!$.scope)K.push("scope");if(K.length>0)throw Error(`Missing OIDC configuration fields: ${K.join(", ")}. OIDC configuration is required for SSO operations. Please provide these fields either in your vault configuration or in the SSO config when initializing enterpriseStandard.`)}async function P(K){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");try{let{tokens:G}=await h(K);if(!G)return;return await v(G)}catch(G){console.error("Error parsing user from cookies:",G);return}}async function w(K){let G=await P(K);if(G)return G;throw new Response("Unauthorized",{status:401,statusText:"Unauthorized"})}async function C({landingUrl:K,errorUrl:G},B){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");H();let L=l(),W=l(64),Q=$.redirectUri;try{new URL(Q)}catch{if(B)try{let V=new URL(B),T=Q.startsWith("//")?Q.slice(1):Q.startsWith("/")?Q:`/${Q}`;Q=new URL(T,V.origin).toString()}catch{try{let V=new URL($.authorizationUrl),T=Q.startsWith("//")?Q.slice(1):Q.startsWith("/")?Q:`/${Q}`;Q=new URL(T,V.origin).toString()}catch{throw Error(`Invalid redirectUri: "${$.redirectUri}". It must be a valid absolute URL.`)}}}let O=new URL($.authorizationUrl);O.searchParams.append("client_id",$.clientId),O.searchParams.append("redirect_uri",Q),O.searchParams.append("response_type","code"),O.searchParams.append("scope",$.scope),O.searchParams.append("state",L);let J=await NX(W);O.searchParams.append("code_challenge",J),O.searchParams.append("code_challenge_method","S256");let j={state:L,codeVerifier:W,landingUrl:K,errorUrl:G};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:O.toString(),"Set-Cookie":U("state",j,86400)}})}async function I(K,G){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");try{let J=y("refresh",K);if(J)await $X(J)}catch(J){console.warn("Failed to revoke token:",J)}if($.sessionStore)try{let J=await P(K);if(J?.sso?.profile.sid){let j=J.sso.profile.sid;await $.sessionStore.delete(j)}}catch(J){console.warn("Failed to delete session:",J)}let B=[["Set-Cookie",R("access")],["Set-Cookie",R("id")],["Set-Cookie",R("refresh")],["Set-Cookie",R("control")],["Set-Cookie",R("state")]],W=new URL(K.url).searchParams.get("redirect");if(W)return new Response("Logged out",{status:302,headers:[["Location",W],...B]});let Q=K.headers.get("accept");if(Q?.includes("application/json")||Q?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out"}),{status:200,headers:[["Content-Type","application/json"],...B]});else return new Response(`
|
|
4
4
|
<!DOCTYPE html><html lang="en"><body>
|
|
5
5
|
<h1>Logout Complete</h1>
|
|
6
6
|
<div style="display: none">
|