@clerk/shared 4.8.3-snapshot.v20260421194054 → 4.8.3
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/runtime/apiUrlFromPublishableKey.d.mts +1 -1
- package/dist/runtime/apiUrlFromPublishableKey.d.ts +1 -1
- package/dist/runtime/{authorization-Un7v7f6J.mjs → authorization-Bayl2soX.mjs} +72 -32
- package/dist/runtime/authorization-Bayl2soX.mjs.map +1 -0
- package/dist/runtime/{authorization-Du_JQmnH.js → authorization-Dj1hHJtO.js} +72 -32
- package/dist/runtime/authorization-Dj1hHJtO.js.map +1 -0
- package/dist/runtime/authorization.d.mts +4 -3
- package/dist/runtime/authorization.d.mts.map +1 -1
- package/dist/runtime/authorization.d.ts +4 -3
- package/dist/runtime/authorization.d.ts.map +1 -1
- package/dist/runtime/authorization.js +1 -1
- package/dist/runtime/authorization.mjs +1 -1
- package/dist/runtime/color.d.mts.map +1 -1
- package/dist/runtime/globs.d.ts.map +1 -1
- package/dist/runtime/index-B4_BYgBX.d.mts.map +1 -1
- package/dist/runtime/jwtPayloadParser.js +1 -1
- package/dist/runtime/jwtPayloadParser.mjs +1 -1
- package/dist/runtime/loadClerkJsScript.d.mts.map +1 -1
- package/dist/runtime/loadClerkJsScript.d.ts.map +1 -1
- package/dist/runtime/loadClerkJsScript.js +6 -20
- package/dist/runtime/loadClerkJsScript.js.map +1 -1
- package/dist/runtime/loadClerkJsScript.mjs +6 -20
- package/dist/runtime/loadClerkJsScript.mjs.map +1 -1
- package/dist/runtime/poller.d.ts.map +1 -1
- package/dist/runtime/proxy-BcfViKjn.mjs +31 -0
- package/dist/runtime/proxy-BcfViKjn.mjs.map +1 -0
- package/dist/runtime/proxy-DahrnOq8.js +55 -0
- package/dist/runtime/proxy-DahrnOq8.js.map +1 -0
- package/dist/runtime/proxy.d.mts +1 -15
- package/dist/runtime/proxy.d.mts.map +1 -1
- package/dist/runtime/proxy.d.ts +1 -15
- package/dist/runtime/proxy.d.ts.map +1 -1
- package/dist/runtime/proxy.js +2 -9
- package/dist/runtime/proxy.mjs +2 -6
- package/dist/runtime/react/index.js +1 -1
- package/dist/runtime/react/index.mjs +1 -1
- package/dist/runtime/router.d.mts.map +1 -1
- package/dist/runtime/router.d.ts.map +1 -1
- package/dist/runtime/{versionSelector-BwfzCTEB.js → versionSelector-cJbE4ZNU.js} +2 -2
- package/dist/runtime/{versionSelector-BwfzCTEB.js.map → versionSelector-cJbE4ZNU.js.map} +1 -1
- package/dist/runtime/{versionSelector-DK06JbJn.mjs → versionSelector-mE4tPkHj.mjs} +2 -2
- package/dist/runtime/{versionSelector-DK06JbJn.mjs.map → versionSelector-mE4tPkHj.mjs.map} +1 -1
- package/dist/runtime/versionSelector.js +1 -1
- package/dist/runtime/versionSelector.mjs +1 -1
- package/dist/types/index.d.mts.map +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/runtime/authorization-Du_JQmnH.js.map +0 -1
- package/dist/runtime/authorization-Un7v7f6J.mjs.map +0 -1
- package/dist/runtime/proxy-3SYEg0mL.mjs +0 -55
- package/dist/runtime/proxy-3SYEg0mL.mjs.map +0 -1
- package/dist/runtime/proxy-BcBJmkTc.js +0 -96
- package/dist/runtime/proxy-BcBJmkTc.js.map +0 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @param publishableKey - The publishable key to parse.
|
|
6
6
|
* @returns One of Clerk's API URLs.
|
|
7
7
|
*/
|
|
8
|
-
declare const apiUrlFromPublishableKey: (publishableKey: string) => "https://api.
|
|
8
|
+
declare const apiUrlFromPublishableKey: (publishableKey: string) => "https://api.clerk.com" | "https://api.lclclerk.com" | "https://api.clerkstage.dev";
|
|
9
9
|
//#endregion
|
|
10
10
|
export { apiUrlFromPublishableKey };
|
|
11
11
|
//# sourceMappingURL=apiUrlFromPublishableKey.d.mts.map
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @param publishableKey - The publishable key to parse.
|
|
6
6
|
* @returns One of Clerk's API URLs.
|
|
7
7
|
*/
|
|
8
|
-
declare const apiUrlFromPublishableKey: (publishableKey: string) => "https://api.
|
|
8
|
+
declare const apiUrlFromPublishableKey: (publishableKey: string) => "https://api.clerk.com" | "https://api.lclclerk.com" | "https://api.clerkstage.dev";
|
|
9
9
|
//#endregion
|
|
10
10
|
export { apiUrlFromPublishableKey };
|
|
11
11
|
//# sourceMappingURL=apiUrlFromPublishableKey.d.ts.map
|
|
@@ -37,20 +37,29 @@ const USER_SCOPES = new Set(["u", "user"]);
|
|
|
37
37
|
const isValidMaxAge = (maxAge) => typeof maxAge === "number" && maxAge > 0;
|
|
38
38
|
const isValidLevel = (level) => ALLOWED_LEVELS.has(level);
|
|
39
39
|
const isValidVerificationType = (type) => ALLOWED_TYPES.has(type);
|
|
40
|
+
const isValidFactorAge = (x) => typeof x === "number" && Number.isFinite(x) && (x === -1 || x >= 0);
|
|
40
41
|
const prefixWithOrg = (value) => value.replace(/^(org:)*/, "org:");
|
|
41
42
|
/**
|
|
42
43
|
* Checks if a user has the required organization-level authorization.
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* @returns null, if unable to determine due to missing data or unspecified role/permission.
|
|
44
|
+
* If both role and permission are provided, both must match (AND).
|
|
46
45
|
*/
|
|
47
46
|
const checkOrgAuthorization = (params, options) => {
|
|
48
47
|
const { orgId, orgRole, orgPermissions } = options;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
if (params.role
|
|
53
|
-
return
|
|
48
|
+
const roleAsked = params.role !== void 0;
|
|
49
|
+
const permissionAsked = params.permission !== void 0;
|
|
50
|
+
if (!roleAsked && !permissionAsked) return "skip";
|
|
51
|
+
if (roleAsked && typeof params.role !== "string") return "fail";
|
|
52
|
+
if (permissionAsked && typeof params.permission !== "string") return "fail";
|
|
53
|
+
if (!orgId) return "fail";
|
|
54
|
+
if (roleAsked) {
|
|
55
|
+
if (typeof orgRole !== "string" || !orgRole) return "fail";
|
|
56
|
+
if (prefixWithOrg(orgRole) !== prefixWithOrg(params.role)) return "fail";
|
|
57
|
+
}
|
|
58
|
+
if (permissionAsked) {
|
|
59
|
+
if (!Array.isArray(orgPermissions)) return "fail";
|
|
60
|
+
if (!orgPermissions.includes(prefixWithOrg(params.permission))) return "fail";
|
|
61
|
+
}
|
|
62
|
+
return "pass";
|
|
54
63
|
};
|
|
55
64
|
const checkForFeatureOrPlan = (claim, featureOrPlan) => {
|
|
56
65
|
const { org: orgFeatures, user: userFeatures } = splitByScope(claim);
|
|
@@ -65,11 +74,34 @@ const checkForFeatureOrPlan = (claim, featureOrPlan) => {
|
|
|
65
74
|
}
|
|
66
75
|
return [...orgFeatures, ...userFeatures].includes(id);
|
|
67
76
|
};
|
|
77
|
+
/**
|
|
78
|
+
* Checks if a user is entitled to the requested feature or plan.
|
|
79
|
+
* If both feature and plan are provided, both must match (AND).
|
|
80
|
+
*/
|
|
68
81
|
const checkBillingAuthorization = (params, options) => {
|
|
69
82
|
const { features, plans } = options;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return
|
|
83
|
+
const featureAsked = params.feature !== void 0;
|
|
84
|
+
const planAsked = params.plan !== void 0;
|
|
85
|
+
if (!featureAsked && !planAsked) return "skip";
|
|
86
|
+
if (featureAsked && typeof params.feature !== "string") return "fail";
|
|
87
|
+
if (planAsked && typeof params.plan !== "string") return "fail";
|
|
88
|
+
if (featureAsked) {
|
|
89
|
+
if (typeof features !== "string" || !features) return "fail";
|
|
90
|
+
try {
|
|
91
|
+
if (!checkForFeatureOrPlan(features, params.feature)) return "fail";
|
|
92
|
+
} catch {
|
|
93
|
+
return "fail";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (planAsked) {
|
|
97
|
+
if (typeof plans !== "string" || !plans) return "fail";
|
|
98
|
+
try {
|
|
99
|
+
if (!checkForFeatureOrPlan(plans, params.plan)) return "fail";
|
|
100
|
+
} catch {
|
|
101
|
+
return "fail";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return "pass";
|
|
73
105
|
};
|
|
74
106
|
const splitByScope = (fea) => {
|
|
75
107
|
const org = [];
|
|
@@ -110,39 +142,47 @@ const validateReverificationConfig = (config) => {
|
|
|
110
142
|
};
|
|
111
143
|
/**
|
|
112
144
|
* Evaluates if the user meets re-verification authentication requirements.
|
|
113
|
-
* Compares the user's factor verification ages against the specified maxAge.
|
|
114
145
|
* Handles different verification levels (first factor, second factor, multi-factor).
|
|
115
|
-
*
|
|
116
|
-
* @returns null, if requirements or verification data are missing.
|
|
117
146
|
*/
|
|
118
147
|
const checkReverificationAuthorization = (params, { factorVerificationAge }) => {
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
if (!
|
|
122
|
-
const
|
|
148
|
+
if (params.reverification === void 0) return "skip";
|
|
149
|
+
if (!factorVerificationAge) return "fail";
|
|
150
|
+
if (!Array.isArray(factorVerificationAge) || factorVerificationAge.length !== 2 || !isValidFactorAge(factorVerificationAge[0]) || !isValidFactorAge(factorVerificationAge[1])) return "fail";
|
|
151
|
+
const getConfig = validateReverificationConfig(params.reverification);
|
|
152
|
+
if (!getConfig) return "fail";
|
|
153
|
+
const { level, afterMinutes } = getConfig();
|
|
123
154
|
const [factor1Age, factor2Age] = factorVerificationAge;
|
|
124
|
-
|
|
125
|
-
const
|
|
155
|
+
if (factor1Age === -1 && factor2Age === -1) return "fail";
|
|
156
|
+
const factor1FreshEnough = factor1Age !== -1 && afterMinutes > factor1Age;
|
|
157
|
+
const factor2FreshEnough = factor2Age !== -1 && afterMinutes > factor2Age;
|
|
126
158
|
switch (level) {
|
|
127
|
-
case "first_factor": return
|
|
128
|
-
case "second_factor":
|
|
129
|
-
|
|
159
|
+
case "first_factor": return factor1FreshEnough ? "pass" : "fail";
|
|
160
|
+
case "second_factor":
|
|
161
|
+
if (factor2Age === -1) return factor1FreshEnough ? "pass" : "fail";
|
|
162
|
+
if (factor1Age === -1) return factor2FreshEnough ? "pass" : "fail";
|
|
163
|
+
return factor2FreshEnough ? "pass" : "fail";
|
|
164
|
+
case "multi_factor":
|
|
165
|
+
if (factor2Age === -1) return factor1FreshEnough ? "pass" : "fail";
|
|
166
|
+
if (factor1Age === -1) return "fail";
|
|
167
|
+
return factor1FreshEnough && factor2FreshEnough ? "pass" : "fail";
|
|
130
168
|
}
|
|
131
169
|
};
|
|
170
|
+
const combine = (results) => results.some((r) => r === "pass") && results.every((r) => r === "pass" || r === "skip");
|
|
132
171
|
/**
|
|
133
172
|
* Creates a function for comprehensive user authorization checks.
|
|
134
|
-
* Combines organization
|
|
135
|
-
*
|
|
136
|
-
*
|
|
173
|
+
* Combines organization, billing, and reverification checks. The returned function
|
|
174
|
+
* authorizes only when every requested dimension passes; any requested dimension
|
|
175
|
+
* that cannot be satisfied (including missing or malformed session data) denies
|
|
176
|
+
* the request. Fails if `userId` is missing.
|
|
137
177
|
*/
|
|
138
178
|
const createCheckAuthorization = (options) => {
|
|
139
179
|
return (params) => {
|
|
140
180
|
if (!options.userId) return false;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
181
|
+
return combine([
|
|
182
|
+
checkOrgAuthorization(params, options),
|
|
183
|
+
checkBillingAuthorization(params, options),
|
|
184
|
+
checkReverificationAuthorization(params, options)
|
|
185
|
+
]);
|
|
146
186
|
};
|
|
147
187
|
};
|
|
148
188
|
/**
|
|
@@ -226,4 +266,4 @@ const resolveAuthState = ({ authObject: { sessionId, sessionStatus, userId, acto
|
|
|
226
266
|
|
|
227
267
|
//#endregion
|
|
228
268
|
export { validateReverificationConfig as i, resolveAuthState as n, splitByScope as r, createCheckAuthorization as t };
|
|
229
|
-
//# sourceMappingURL=authorization-
|
|
269
|
+
//# sourceMappingURL=authorization-Bayl2soX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-Bayl2soX.mjs","names":["TYPES_TO_OBJECTS: TypesToConfig","checkOrgAuthorization: CheckOrgAuthorization","checkBillingAuthorization: CheckBillingAuthorization","org: string[]","user: string[]","config","checkReverificationAuthorization: CheckReverificationAuthorization"],"sources":["../../src/authorization.ts"],"sourcesContent":["import type {\n ActClaim,\n CheckAuthorizationWithCustomPermissions,\n GetToken,\n JwtPayload,\n OrganizationCustomPermissionKey,\n OrganizationCustomRoleKey,\n PendingSessionOptions,\n ReverificationConfig,\n SessionStatusClaim,\n SessionVerificationLevel,\n SessionVerificationTypes,\n SignOut,\n UseAuthReturn,\n} from './types';\n\ntype TypesToConfig = Record<SessionVerificationTypes, Exclude<ReverificationConfig, SessionVerificationTypes>>;\ntype AuthorizationOptions = {\n userId: string | null | undefined;\n orgId: string | null | undefined;\n orgRole: string | null | undefined;\n orgPermissions: string[] | null | undefined;\n factorVerificationAge: [number, number] | null;\n features: string | null | undefined;\n plans: string | null | undefined;\n};\n\n// Internal verdict for each authorization dimension.\n// pass = caller asked, the dimension is satisfied\n// fail = caller asked, the dimension is not satisfied (includes \"data missing\" - fail closed)\n// skip = caller did not ask in this dimension; it does not contribute to the result\ntype CheckResult = 'pass' | 'fail' | 'skip';\n\ntype CheckOrgAuthorization = (\n params: { role?: OrganizationCustomRoleKey; permission?: OrganizationCustomPermissionKey },\n options: Pick<AuthorizationOptions, 'orgId' | 'orgRole' | 'orgPermissions'>,\n) => CheckResult;\n\ntype CheckBillingAuthorization = (\n params: { feature?: string; plan?: string },\n options: Pick<AuthorizationOptions, 'plans' | 'features'>,\n) => CheckResult;\n\ntype CheckReverificationAuthorization = (\n params: {\n reverification?: ReverificationConfig;\n },\n { factorVerificationAge }: AuthorizationOptions,\n) => CheckResult;\n\nconst TYPES_TO_OBJECTS: TypesToConfig = {\n strict_mfa: {\n afterMinutes: 10,\n level: 'multi_factor',\n },\n strict: {\n afterMinutes: 10,\n level: 'second_factor',\n },\n moderate: {\n afterMinutes: 60,\n level: 'second_factor',\n },\n lax: {\n afterMinutes: 1_440,\n level: 'second_factor',\n },\n};\n\nconst ALLOWED_LEVELS = new Set<SessionVerificationLevel>(['first_factor', 'second_factor', 'multi_factor']);\n\nconst ALLOWED_TYPES = new Set<SessionVerificationTypes>(['strict_mfa', 'strict', 'moderate', 'lax']);\n\nconst ORG_SCOPES = new Set(['o', 'org', 'organization']);\nconst USER_SCOPES = new Set(['u', 'user']);\n\n// Helper functions\nconst isValidMaxAge = (maxAge: any) => typeof maxAge === 'number' && maxAge > 0;\nconst isValidLevel = (level: any) => ALLOWED_LEVELS.has(level);\nconst isValidVerificationType = (type: any) => ALLOWED_TYPES.has(type);\nconst isValidFactorAge = (x: unknown): x is number =>\n typeof x === 'number' && Number.isFinite(x) && (x === -1 || x >= 0);\n\nconst prefixWithOrg = (value: string) => value.replace(/^(org:)*/, 'org:');\n\n/**\n * Checks if a user has the required organization-level authorization.\n * If both role and permission are provided, both must match (AND).\n */\nconst checkOrgAuthorization: CheckOrgAuthorization = (params, options) => {\n const { orgId, orgRole, orgPermissions } = options;\n const roleAsked = params.role !== undefined;\n const permissionAsked = params.permission !== undefined;\n\n if (!roleAsked && !permissionAsked) {\n return 'skip';\n }\n\n // Asked with a non-string value (e.g. null cast through `as any`): fail closed\n // rather than letting `prefixWithOrg` throw.\n if (roleAsked && typeof params.role !== 'string') {\n return 'fail';\n }\n if (permissionAsked && typeof params.permission !== 'string') {\n return 'fail';\n }\n\n if (!orgId) {\n return 'fail';\n }\n\n if (roleAsked) {\n if (typeof orgRole !== 'string' || !orgRole) {\n return 'fail';\n }\n if (prefixWithOrg(orgRole) !== prefixWithOrg(params.role as string)) {\n return 'fail';\n }\n }\n\n if (permissionAsked) {\n if (!Array.isArray(orgPermissions)) {\n return 'fail';\n }\n if (!orgPermissions.includes(prefixWithOrg(params.permission as string))) {\n return 'fail';\n }\n }\n\n return 'pass';\n};\n\nconst checkForFeatureOrPlan = (claim: string, featureOrPlan: string) => {\n const { org: orgFeatures, user: userFeatures } = splitByScope(claim);\n const [rawScope, rawId] = featureOrPlan.split(':');\n const hasExplicitScope = rawId !== undefined;\n const scope = rawScope;\n const id = rawId || rawScope;\n\n if (hasExplicitScope && !ORG_SCOPES.has(scope) && !USER_SCOPES.has(scope)) {\n throw new Error(`Invalid scope: ${scope}`);\n }\n\n if (hasExplicitScope) {\n if (ORG_SCOPES.has(scope)) {\n return orgFeatures.includes(id);\n }\n if (USER_SCOPES.has(scope)) {\n return userFeatures.includes(id);\n }\n }\n\n // Since org scoped features will not exist if there is not an active org, merging is safe.\n return [...orgFeatures, ...userFeatures].includes(id);\n};\n\n/**\n * Checks if a user is entitled to the requested feature or plan.\n * If both feature and plan are provided, both must match (AND).\n */\nconst checkBillingAuthorization: CheckBillingAuthorization = (params, options) => {\n const { features, plans } = options;\n const featureAsked = params.feature !== undefined;\n const planAsked = params.plan !== undefined;\n\n if (!featureAsked && !planAsked) {\n return 'skip';\n }\n\n // Asked with a non-string value: fail closed before handing to checkForFeatureOrPlan.\n if (featureAsked && typeof params.feature !== 'string') {\n return 'fail';\n }\n if (planAsked && typeof params.plan !== 'string') {\n return 'fail';\n }\n\n if (featureAsked) {\n if (typeof features !== 'string' || !features) {\n return 'fail';\n }\n try {\n if (!checkForFeatureOrPlan(features, params.feature as string)) {\n return 'fail';\n }\n } catch {\n return 'fail';\n }\n }\n\n if (planAsked) {\n if (typeof plans !== 'string' || !plans) {\n return 'fail';\n }\n try {\n if (!checkForFeatureOrPlan(plans, params.plan as string)) {\n return 'fail';\n }\n } catch {\n return 'fail';\n }\n }\n\n return 'pass';\n};\n\nconst splitByScope = (fea: string | null | undefined) => {\n const org: string[] = [];\n const user: string[] = [];\n\n if (!fea) {\n return { org, user };\n }\n\n const parts = fea.split(',');\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i].trim();\n const colonIndex = part.indexOf(':');\n if (colonIndex === -1) {\n throw new Error(`Invalid claim element (missing colon): ${part}`);\n }\n const scope = part.slice(0, colonIndex);\n const value = part.slice(colonIndex + 1);\n\n if (scope === 'o') {\n org.push(value);\n } else if (scope === 'u') {\n user.push(value);\n } else if (scope === 'ou' || scope === 'uo') {\n org.push(value);\n user.push(value);\n }\n }\n\n return { org, user };\n};\n\nconst validateReverificationConfig = (config: ReverificationConfig | undefined | null) => {\n if (!config) {\n return false;\n }\n\n const convertConfigToObject = (config: ReverificationConfig) => {\n if (typeof config === 'string') {\n return TYPES_TO_OBJECTS[config];\n }\n return config;\n };\n\n const isValidStringValue = typeof config === 'string' && isValidVerificationType(config);\n const isValidObjectValue =\n typeof config === 'object' && isValidLevel(config.level) && isValidMaxAge(config.afterMinutes);\n\n if (isValidStringValue || isValidObjectValue) {\n return convertConfigToObject.bind(null, config);\n }\n\n return false;\n};\n\n/**\n * Evaluates if the user meets re-verification authentication requirements.\n * Handles different verification levels (first factor, second factor, multi-factor).\n */\nconst checkReverificationAuthorization: CheckReverificationAuthorization = (params, { factorVerificationAge }) => {\n if (params.reverification === undefined) {\n return 'skip';\n }\n\n if (!factorVerificationAge) {\n return 'fail';\n }\n\n // Validate the tuple shape before comparing ages to defend against malformed JWT\n // payloads or TS `as any` escapes. `factor1Age` / `factor2Age` must be numbers\n // representing minutes (or -1 when a factor group is not enabled).\n if (\n !Array.isArray(factorVerificationAge) ||\n factorVerificationAge.length !== 2 ||\n !isValidFactorAge(factorVerificationAge[0]) ||\n !isValidFactorAge(factorVerificationAge[1])\n ) {\n return 'fail';\n }\n\n const getConfig = validateReverificationConfig(params.reverification);\n if (!getConfig) {\n return 'fail';\n }\n\n const { level, afterMinutes } = getConfig();\n const [factor1Age, factor2Age] = factorVerificationAge;\n\n // -1 indicates the factor group (1fa, 2fa) is not enabled.\n // If neither factor is enrolled we cannot verify anything; fail closed.\n if (factor1Age === -1 && factor2Age === -1) {\n return 'fail';\n }\n\n const factor1FreshEnough = factor1Age !== -1 && afterMinutes > factor1Age;\n const factor2FreshEnough = factor2Age !== -1 && afterMinutes > factor2Age;\n\n switch (level) {\n case 'first_factor':\n return factor1FreshEnough ? 'pass' : 'fail';\n case 'second_factor':\n // Graceful downgrade: prefer second factor; fall back to whichever factor is\n // enrolled when the other is missing.\n if (factor2Age === -1) {\n return factor1FreshEnough ? 'pass' : 'fail';\n }\n if (factor1Age === -1) {\n return factor2FreshEnough ? 'pass' : 'fail';\n }\n return factor2FreshEnough ? 'pass' : 'fail';\n case 'multi_factor':\n // Graceful downgrade: no second factor enrolled falls back to first factor.\n if (factor2Age === -1) {\n return factor1FreshEnough ? 'pass' : 'fail';\n }\n // Second factor exists but first factor is not enrolled - we cannot satisfy\n // the multi-factor requirement.\n if (factor1Age === -1) {\n return 'fail';\n }\n return factor1FreshEnough && factor2FreshEnough ? 'pass' : 'fail';\n }\n};\n\n// At least one dimension must have passed, and every non-skip result must be a pass.\n// This is an AND across asked dimensions with a fail-closed default: if a helper ever\n// returns anything other than 'pass' or 'skip' (a typo, off-type, or future variant),\n// it is treated as a denial.\nconst combine = (results: CheckResult[]): boolean =>\n results.some(r => r === 'pass') && results.every(r => r === 'pass' || r === 'skip');\n\n/**\n * Creates a function for comprehensive user authorization checks.\n * Combines organization, billing, and reverification checks. The returned function\n * authorizes only when every requested dimension passes; any requested dimension\n * that cannot be satisfied (including missing or malformed session data) denies\n * the request. Fails if `userId` is missing.\n */\nconst createCheckAuthorization = (options: AuthorizationOptions): CheckAuthorizationWithCustomPermissions => {\n return (params): boolean => {\n if (!options.userId) {\n return false;\n }\n\n return combine([\n checkOrgAuthorization(params, options),\n checkBillingAuthorization(params, options),\n checkReverificationAuthorization(params, options),\n ]);\n };\n};\n\ntype AuthStateOptions = {\n authObject: {\n userId?: string | null;\n sessionId?: string | null;\n sessionStatus?: SessionStatusClaim | null;\n sessionClaims?: JwtPayload | null;\n actor?: ActClaim | null;\n orgId?: string | null;\n orgRole?: OrganizationCustomRoleKey | null;\n orgSlug?: string | null;\n orgPermissions?: OrganizationCustomPermissionKey[] | null;\n getToken: GetToken;\n signOut: SignOut;\n has: (params: Parameters<CheckAuthorizationWithCustomPermissions>[0]) => boolean;\n };\n options: PendingSessionOptions;\n};\n\n/**\n * Shared utility function that centralizes auth state resolution logic,\n * preventing duplication across different packages.\n *\n * @internal\n */\nconst resolveAuthState = ({\n authObject: {\n sessionId,\n sessionStatus,\n userId,\n actor,\n orgId,\n orgRole,\n orgSlug,\n signOut,\n getToken,\n has,\n sessionClaims,\n },\n options: { treatPendingAsSignedOut = true },\n}: AuthStateOptions): UseAuthReturn | undefined => {\n if (sessionId === undefined && userId === undefined) {\n return {\n actor: undefined,\n getToken,\n has: () => false,\n isLoaded: false,\n isSignedIn: undefined,\n orgId: undefined,\n orgRole: undefined,\n orgSlug: undefined,\n sessionClaims: undefined,\n sessionId,\n signOut,\n userId,\n } as const;\n }\n\n if (sessionId === null && userId === null) {\n return {\n actor: null,\n getToken,\n has: () => false,\n isLoaded: true,\n isSignedIn: false,\n orgId: null,\n orgRole: null,\n orgSlug: null,\n sessionClaims: null,\n sessionId,\n signOut,\n userId,\n } as const;\n }\n\n if (treatPendingAsSignedOut && sessionStatus === 'pending') {\n return {\n actor: null,\n getToken,\n has: () => false,\n isLoaded: true,\n isSignedIn: false,\n orgId: null,\n orgRole: null,\n orgSlug: null,\n sessionClaims: null,\n sessionId: null,\n signOut,\n userId: null,\n } as const;\n }\n\n if (!!sessionId && !!sessionClaims && !!userId && !!orgId && !!orgRole) {\n return {\n actor: actor || null,\n getToken,\n has,\n isLoaded: true,\n isSignedIn: true,\n orgId,\n orgRole,\n orgSlug: orgSlug || null,\n sessionClaims,\n sessionId,\n signOut,\n userId,\n } as const;\n }\n\n if (!!sessionId && !!sessionClaims && !!userId && !orgId) {\n return {\n actor: actor || null,\n getToken,\n has,\n isLoaded: true,\n isSignedIn: true,\n orgId: null,\n orgRole: null,\n orgSlug: null,\n sessionClaims,\n sessionId,\n signOut,\n userId,\n } as const;\n }\n};\n\nexport { createCheckAuthorization, resolveAuthState, splitByScope, validateReverificationConfig };\n"],"mappings":"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"}
|
|
@@ -38,20 +38,29 @@ const USER_SCOPES = new Set(["u", "user"]);
|
|
|
38
38
|
const isValidMaxAge = (maxAge) => typeof maxAge === "number" && maxAge > 0;
|
|
39
39
|
const isValidLevel = (level) => ALLOWED_LEVELS.has(level);
|
|
40
40
|
const isValidVerificationType = (type) => ALLOWED_TYPES.has(type);
|
|
41
|
+
const isValidFactorAge = (x) => typeof x === "number" && Number.isFinite(x) && (x === -1 || x >= 0);
|
|
41
42
|
const prefixWithOrg = (value) => value.replace(/^(org:)*/, "org:");
|
|
42
43
|
/**
|
|
43
44
|
* Checks if a user has the required organization-level authorization.
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* @returns null, if unable to determine due to missing data or unspecified role/permission.
|
|
45
|
+
* If both role and permission are provided, both must match (AND).
|
|
47
46
|
*/
|
|
48
47
|
const checkOrgAuthorization = (params, options) => {
|
|
49
48
|
const { orgId, orgRole, orgPermissions } = options;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
if (params.role
|
|
54
|
-
return
|
|
49
|
+
const roleAsked = params.role !== void 0;
|
|
50
|
+
const permissionAsked = params.permission !== void 0;
|
|
51
|
+
if (!roleAsked && !permissionAsked) return "skip";
|
|
52
|
+
if (roleAsked && typeof params.role !== "string") return "fail";
|
|
53
|
+
if (permissionAsked && typeof params.permission !== "string") return "fail";
|
|
54
|
+
if (!orgId) return "fail";
|
|
55
|
+
if (roleAsked) {
|
|
56
|
+
if (typeof orgRole !== "string" || !orgRole) return "fail";
|
|
57
|
+
if (prefixWithOrg(orgRole) !== prefixWithOrg(params.role)) return "fail";
|
|
58
|
+
}
|
|
59
|
+
if (permissionAsked) {
|
|
60
|
+
if (!Array.isArray(orgPermissions)) return "fail";
|
|
61
|
+
if (!orgPermissions.includes(prefixWithOrg(params.permission))) return "fail";
|
|
62
|
+
}
|
|
63
|
+
return "pass";
|
|
55
64
|
};
|
|
56
65
|
const checkForFeatureOrPlan = (claim, featureOrPlan) => {
|
|
57
66
|
const { org: orgFeatures, user: userFeatures } = splitByScope(claim);
|
|
@@ -66,11 +75,34 @@ const checkForFeatureOrPlan = (claim, featureOrPlan) => {
|
|
|
66
75
|
}
|
|
67
76
|
return [...orgFeatures, ...userFeatures].includes(id);
|
|
68
77
|
};
|
|
78
|
+
/**
|
|
79
|
+
* Checks if a user is entitled to the requested feature or plan.
|
|
80
|
+
* If both feature and plan are provided, both must match (AND).
|
|
81
|
+
*/
|
|
69
82
|
const checkBillingAuthorization = (params, options) => {
|
|
70
83
|
const { features, plans } = options;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return
|
|
84
|
+
const featureAsked = params.feature !== void 0;
|
|
85
|
+
const planAsked = params.plan !== void 0;
|
|
86
|
+
if (!featureAsked && !planAsked) return "skip";
|
|
87
|
+
if (featureAsked && typeof params.feature !== "string") return "fail";
|
|
88
|
+
if (planAsked && typeof params.plan !== "string") return "fail";
|
|
89
|
+
if (featureAsked) {
|
|
90
|
+
if (typeof features !== "string" || !features) return "fail";
|
|
91
|
+
try {
|
|
92
|
+
if (!checkForFeatureOrPlan(features, params.feature)) return "fail";
|
|
93
|
+
} catch {
|
|
94
|
+
return "fail";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (planAsked) {
|
|
98
|
+
if (typeof plans !== "string" || !plans) return "fail";
|
|
99
|
+
try {
|
|
100
|
+
if (!checkForFeatureOrPlan(plans, params.plan)) return "fail";
|
|
101
|
+
} catch {
|
|
102
|
+
return "fail";
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return "pass";
|
|
74
106
|
};
|
|
75
107
|
const splitByScope = (fea) => {
|
|
76
108
|
const org = [];
|
|
@@ -111,39 +143,47 @@ const validateReverificationConfig = (config) => {
|
|
|
111
143
|
};
|
|
112
144
|
/**
|
|
113
145
|
* Evaluates if the user meets re-verification authentication requirements.
|
|
114
|
-
* Compares the user's factor verification ages against the specified maxAge.
|
|
115
146
|
* Handles different verification levels (first factor, second factor, multi-factor).
|
|
116
|
-
*
|
|
117
|
-
* @returns null, if requirements or verification data are missing.
|
|
118
147
|
*/
|
|
119
148
|
const checkReverificationAuthorization = (params, { factorVerificationAge }) => {
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
if (!
|
|
123
|
-
const
|
|
149
|
+
if (params.reverification === void 0) return "skip";
|
|
150
|
+
if (!factorVerificationAge) return "fail";
|
|
151
|
+
if (!Array.isArray(factorVerificationAge) || factorVerificationAge.length !== 2 || !isValidFactorAge(factorVerificationAge[0]) || !isValidFactorAge(factorVerificationAge[1])) return "fail";
|
|
152
|
+
const getConfig = validateReverificationConfig(params.reverification);
|
|
153
|
+
if (!getConfig) return "fail";
|
|
154
|
+
const { level, afterMinutes } = getConfig();
|
|
124
155
|
const [factor1Age, factor2Age] = factorVerificationAge;
|
|
125
|
-
|
|
126
|
-
const
|
|
156
|
+
if (factor1Age === -1 && factor2Age === -1) return "fail";
|
|
157
|
+
const factor1FreshEnough = factor1Age !== -1 && afterMinutes > factor1Age;
|
|
158
|
+
const factor2FreshEnough = factor2Age !== -1 && afterMinutes > factor2Age;
|
|
127
159
|
switch (level) {
|
|
128
|
-
case "first_factor": return
|
|
129
|
-
case "second_factor":
|
|
130
|
-
|
|
160
|
+
case "first_factor": return factor1FreshEnough ? "pass" : "fail";
|
|
161
|
+
case "second_factor":
|
|
162
|
+
if (factor2Age === -1) return factor1FreshEnough ? "pass" : "fail";
|
|
163
|
+
if (factor1Age === -1) return factor2FreshEnough ? "pass" : "fail";
|
|
164
|
+
return factor2FreshEnough ? "pass" : "fail";
|
|
165
|
+
case "multi_factor":
|
|
166
|
+
if (factor2Age === -1) return factor1FreshEnough ? "pass" : "fail";
|
|
167
|
+
if (factor1Age === -1) return "fail";
|
|
168
|
+
return factor1FreshEnough && factor2FreshEnough ? "pass" : "fail";
|
|
131
169
|
}
|
|
132
170
|
};
|
|
171
|
+
const combine = (results) => results.some((r) => r === "pass") && results.every((r) => r === "pass" || r === "skip");
|
|
133
172
|
/**
|
|
134
173
|
* Creates a function for comprehensive user authorization checks.
|
|
135
|
-
* Combines organization
|
|
136
|
-
*
|
|
137
|
-
*
|
|
174
|
+
* Combines organization, billing, and reverification checks. The returned function
|
|
175
|
+
* authorizes only when every requested dimension passes; any requested dimension
|
|
176
|
+
* that cannot be satisfied (including missing or malformed session data) denies
|
|
177
|
+
* the request. Fails if `userId` is missing.
|
|
138
178
|
*/
|
|
139
179
|
const createCheckAuthorization = (options) => {
|
|
140
180
|
return (params) => {
|
|
141
181
|
if (!options.userId) return false;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
182
|
+
return combine([
|
|
183
|
+
checkOrgAuthorization(params, options),
|
|
184
|
+
checkBillingAuthorization(params, options),
|
|
185
|
+
checkReverificationAuthorization(params, options)
|
|
186
|
+
]);
|
|
147
187
|
};
|
|
148
188
|
};
|
|
149
189
|
/**
|
|
@@ -250,4 +290,4 @@ Object.defineProperty(exports, 'validateReverificationConfig', {
|
|
|
250
290
|
return validateReverificationConfig;
|
|
251
291
|
}
|
|
252
292
|
});
|
|
253
|
-
//# sourceMappingURL=authorization-
|
|
293
|
+
//# sourceMappingURL=authorization-Dj1hHJtO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-Dj1hHJtO.js","names":["TYPES_TO_OBJECTS: TypesToConfig","checkOrgAuthorization: CheckOrgAuthorization","checkBillingAuthorization: CheckBillingAuthorization","org: string[]","user: string[]","config","checkReverificationAuthorization: CheckReverificationAuthorization"],"sources":["../../src/authorization.ts"],"sourcesContent":["import type {\n ActClaim,\n CheckAuthorizationWithCustomPermissions,\n GetToken,\n JwtPayload,\n OrganizationCustomPermissionKey,\n OrganizationCustomRoleKey,\n PendingSessionOptions,\n ReverificationConfig,\n SessionStatusClaim,\n SessionVerificationLevel,\n SessionVerificationTypes,\n SignOut,\n UseAuthReturn,\n} from './types';\n\ntype TypesToConfig = Record<SessionVerificationTypes, Exclude<ReverificationConfig, SessionVerificationTypes>>;\ntype AuthorizationOptions = {\n userId: string | null | undefined;\n orgId: string | null | undefined;\n orgRole: string | null | undefined;\n orgPermissions: string[] | null | undefined;\n factorVerificationAge: [number, number] | null;\n features: string | null | undefined;\n plans: string | null | undefined;\n};\n\n// Internal verdict for each authorization dimension.\n// pass = caller asked, the dimension is satisfied\n// fail = caller asked, the dimension is not satisfied (includes \"data missing\" - fail closed)\n// skip = caller did not ask in this dimension; it does not contribute to the result\ntype CheckResult = 'pass' | 'fail' | 'skip';\n\ntype CheckOrgAuthorization = (\n params: { role?: OrganizationCustomRoleKey; permission?: OrganizationCustomPermissionKey },\n options: Pick<AuthorizationOptions, 'orgId' | 'orgRole' | 'orgPermissions'>,\n) => CheckResult;\n\ntype CheckBillingAuthorization = (\n params: { feature?: string; plan?: string },\n options: Pick<AuthorizationOptions, 'plans' | 'features'>,\n) => CheckResult;\n\ntype CheckReverificationAuthorization = (\n params: {\n reverification?: ReverificationConfig;\n },\n { factorVerificationAge }: AuthorizationOptions,\n) => CheckResult;\n\nconst TYPES_TO_OBJECTS: TypesToConfig = {\n strict_mfa: {\n afterMinutes: 10,\n level: 'multi_factor',\n },\n strict: {\n afterMinutes: 10,\n level: 'second_factor',\n },\n moderate: {\n afterMinutes: 60,\n level: 'second_factor',\n },\n lax: {\n afterMinutes: 1_440,\n level: 'second_factor',\n },\n};\n\nconst ALLOWED_LEVELS = new Set<SessionVerificationLevel>(['first_factor', 'second_factor', 'multi_factor']);\n\nconst ALLOWED_TYPES = new Set<SessionVerificationTypes>(['strict_mfa', 'strict', 'moderate', 'lax']);\n\nconst ORG_SCOPES = new Set(['o', 'org', 'organization']);\nconst USER_SCOPES = new Set(['u', 'user']);\n\n// Helper functions\nconst isValidMaxAge = (maxAge: any) => typeof maxAge === 'number' && maxAge > 0;\nconst isValidLevel = (level: any) => ALLOWED_LEVELS.has(level);\nconst isValidVerificationType = (type: any) => ALLOWED_TYPES.has(type);\nconst isValidFactorAge = (x: unknown): x is number =>\n typeof x === 'number' && Number.isFinite(x) && (x === -1 || x >= 0);\n\nconst prefixWithOrg = (value: string) => value.replace(/^(org:)*/, 'org:');\n\n/**\n * Checks if a user has the required organization-level authorization.\n * If both role and permission are provided, both must match (AND).\n */\nconst checkOrgAuthorization: CheckOrgAuthorization = (params, options) => {\n const { orgId, orgRole, orgPermissions } = options;\n const roleAsked = params.role !== undefined;\n const permissionAsked = params.permission !== undefined;\n\n if (!roleAsked && !permissionAsked) {\n return 'skip';\n }\n\n // Asked with a non-string value (e.g. null cast through `as any`): fail closed\n // rather than letting `prefixWithOrg` throw.\n if (roleAsked && typeof params.role !== 'string') {\n return 'fail';\n }\n if (permissionAsked && typeof params.permission !== 'string') {\n return 'fail';\n }\n\n if (!orgId) {\n return 'fail';\n }\n\n if (roleAsked) {\n if (typeof orgRole !== 'string' || !orgRole) {\n return 'fail';\n }\n if (prefixWithOrg(orgRole) !== prefixWithOrg(params.role as string)) {\n return 'fail';\n }\n }\n\n if (permissionAsked) {\n if (!Array.isArray(orgPermissions)) {\n return 'fail';\n }\n if (!orgPermissions.includes(prefixWithOrg(params.permission as string))) {\n return 'fail';\n }\n }\n\n return 'pass';\n};\n\nconst checkForFeatureOrPlan = (claim: string, featureOrPlan: string) => {\n const { org: orgFeatures, user: userFeatures } = splitByScope(claim);\n const [rawScope, rawId] = featureOrPlan.split(':');\n const hasExplicitScope = rawId !== undefined;\n const scope = rawScope;\n const id = rawId || rawScope;\n\n if (hasExplicitScope && !ORG_SCOPES.has(scope) && !USER_SCOPES.has(scope)) {\n throw new Error(`Invalid scope: ${scope}`);\n }\n\n if (hasExplicitScope) {\n if (ORG_SCOPES.has(scope)) {\n return orgFeatures.includes(id);\n }\n if (USER_SCOPES.has(scope)) {\n return userFeatures.includes(id);\n }\n }\n\n // Since org scoped features will not exist if there is not an active org, merging is safe.\n return [...orgFeatures, ...userFeatures].includes(id);\n};\n\n/**\n * Checks if a user is entitled to the requested feature or plan.\n * If both feature and plan are provided, both must match (AND).\n */\nconst checkBillingAuthorization: CheckBillingAuthorization = (params, options) => {\n const { features, plans } = options;\n const featureAsked = params.feature !== undefined;\n const planAsked = params.plan !== undefined;\n\n if (!featureAsked && !planAsked) {\n return 'skip';\n }\n\n // Asked with a non-string value: fail closed before handing to checkForFeatureOrPlan.\n if (featureAsked && typeof params.feature !== 'string') {\n return 'fail';\n }\n if (planAsked && typeof params.plan !== 'string') {\n return 'fail';\n }\n\n if (featureAsked) {\n if (typeof features !== 'string' || !features) {\n return 'fail';\n }\n try {\n if (!checkForFeatureOrPlan(features, params.feature as string)) {\n return 'fail';\n }\n } catch {\n return 'fail';\n }\n }\n\n if (planAsked) {\n if (typeof plans !== 'string' || !plans) {\n return 'fail';\n }\n try {\n if (!checkForFeatureOrPlan(plans, params.plan as string)) {\n return 'fail';\n }\n } catch {\n return 'fail';\n }\n }\n\n return 'pass';\n};\n\nconst splitByScope = (fea: string | null | undefined) => {\n const org: string[] = [];\n const user: string[] = [];\n\n if (!fea) {\n return { org, user };\n }\n\n const parts = fea.split(',');\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i].trim();\n const colonIndex = part.indexOf(':');\n if (colonIndex === -1) {\n throw new Error(`Invalid claim element (missing colon): ${part}`);\n }\n const scope = part.slice(0, colonIndex);\n const value = part.slice(colonIndex + 1);\n\n if (scope === 'o') {\n org.push(value);\n } else if (scope === 'u') {\n user.push(value);\n } else if (scope === 'ou' || scope === 'uo') {\n org.push(value);\n user.push(value);\n }\n }\n\n return { org, user };\n};\n\nconst validateReverificationConfig = (config: ReverificationConfig | undefined | null) => {\n if (!config) {\n return false;\n }\n\n const convertConfigToObject = (config: ReverificationConfig) => {\n if (typeof config === 'string') {\n return TYPES_TO_OBJECTS[config];\n }\n return config;\n };\n\n const isValidStringValue = typeof config === 'string' && isValidVerificationType(config);\n const isValidObjectValue =\n typeof config === 'object' && isValidLevel(config.level) && isValidMaxAge(config.afterMinutes);\n\n if (isValidStringValue || isValidObjectValue) {\n return convertConfigToObject.bind(null, config);\n }\n\n return false;\n};\n\n/**\n * Evaluates if the user meets re-verification authentication requirements.\n * Handles different verification levels (first factor, second factor, multi-factor).\n */\nconst checkReverificationAuthorization: CheckReverificationAuthorization = (params, { factorVerificationAge }) => {\n if (params.reverification === undefined) {\n return 'skip';\n }\n\n if (!factorVerificationAge) {\n return 'fail';\n }\n\n // Validate the tuple shape before comparing ages to defend against malformed JWT\n // payloads or TS `as any` escapes. `factor1Age` / `factor2Age` must be numbers\n // representing minutes (or -1 when a factor group is not enabled).\n if (\n !Array.isArray(factorVerificationAge) ||\n factorVerificationAge.length !== 2 ||\n !isValidFactorAge(factorVerificationAge[0]) ||\n !isValidFactorAge(factorVerificationAge[1])\n ) {\n return 'fail';\n }\n\n const getConfig = validateReverificationConfig(params.reverification);\n if (!getConfig) {\n return 'fail';\n }\n\n const { level, afterMinutes } = getConfig();\n const [factor1Age, factor2Age] = factorVerificationAge;\n\n // -1 indicates the factor group (1fa, 2fa) is not enabled.\n // If neither factor is enrolled we cannot verify anything; fail closed.\n if (factor1Age === -1 && factor2Age === -1) {\n return 'fail';\n }\n\n const factor1FreshEnough = factor1Age !== -1 && afterMinutes > factor1Age;\n const factor2FreshEnough = factor2Age !== -1 && afterMinutes > factor2Age;\n\n switch (level) {\n case 'first_factor':\n return factor1FreshEnough ? 'pass' : 'fail';\n case 'second_factor':\n // Graceful downgrade: prefer second factor; fall back to whichever factor is\n // enrolled when the other is missing.\n if (factor2Age === -1) {\n return factor1FreshEnough ? 'pass' : 'fail';\n }\n if (factor1Age === -1) {\n return factor2FreshEnough ? 'pass' : 'fail';\n }\n return factor2FreshEnough ? 'pass' : 'fail';\n case 'multi_factor':\n // Graceful downgrade: no second factor enrolled falls back to first factor.\n if (factor2Age === -1) {\n return factor1FreshEnough ? 'pass' : 'fail';\n }\n // Second factor exists but first factor is not enrolled - we cannot satisfy\n // the multi-factor requirement.\n if (factor1Age === -1) {\n return 'fail';\n }\n return factor1FreshEnough && factor2FreshEnough ? 'pass' : 'fail';\n }\n};\n\n// At least one dimension must have passed, and every non-skip result must be a pass.\n// This is an AND across asked dimensions with a fail-closed default: if a helper ever\n// returns anything other than 'pass' or 'skip' (a typo, off-type, or future variant),\n// it is treated as a denial.\nconst combine = (results: CheckResult[]): boolean =>\n results.some(r => r === 'pass') && results.every(r => r === 'pass' || r === 'skip');\n\n/**\n * Creates a function for comprehensive user authorization checks.\n * Combines organization, billing, and reverification checks. The returned function\n * authorizes only when every requested dimension passes; any requested dimension\n * that cannot be satisfied (including missing or malformed session data) denies\n * the request. Fails if `userId` is missing.\n */\nconst createCheckAuthorization = (options: AuthorizationOptions): CheckAuthorizationWithCustomPermissions => {\n return (params): boolean => {\n if (!options.userId) {\n return false;\n }\n\n return combine([\n checkOrgAuthorization(params, options),\n checkBillingAuthorization(params, options),\n checkReverificationAuthorization(params, options),\n ]);\n };\n};\n\ntype AuthStateOptions = {\n authObject: {\n userId?: string | null;\n sessionId?: string | null;\n sessionStatus?: SessionStatusClaim | null;\n sessionClaims?: JwtPayload | null;\n actor?: ActClaim | null;\n orgId?: string | null;\n orgRole?: OrganizationCustomRoleKey | null;\n orgSlug?: string | null;\n orgPermissions?: OrganizationCustomPermissionKey[] | null;\n getToken: GetToken;\n signOut: SignOut;\n has: (params: Parameters<CheckAuthorizationWithCustomPermissions>[0]) => boolean;\n };\n options: PendingSessionOptions;\n};\n\n/**\n * Shared utility function that centralizes auth state resolution logic,\n * preventing duplication across different packages.\n *\n * @internal\n */\nconst resolveAuthState = ({\n authObject: {\n sessionId,\n sessionStatus,\n userId,\n actor,\n orgId,\n orgRole,\n orgSlug,\n signOut,\n getToken,\n has,\n sessionClaims,\n },\n options: { treatPendingAsSignedOut = true },\n}: AuthStateOptions): UseAuthReturn | undefined => {\n if (sessionId === undefined && userId === undefined) {\n return {\n actor: undefined,\n getToken,\n has: () => false,\n isLoaded: false,\n isSignedIn: undefined,\n orgId: undefined,\n orgRole: undefined,\n orgSlug: undefined,\n sessionClaims: undefined,\n sessionId,\n signOut,\n userId,\n } as const;\n }\n\n if (sessionId === null && userId === null) {\n return {\n actor: null,\n getToken,\n has: () => false,\n isLoaded: true,\n isSignedIn: false,\n orgId: null,\n orgRole: null,\n orgSlug: null,\n sessionClaims: null,\n sessionId,\n signOut,\n userId,\n } as const;\n }\n\n if (treatPendingAsSignedOut && sessionStatus === 'pending') {\n return {\n actor: null,\n getToken,\n has: () => false,\n isLoaded: true,\n isSignedIn: false,\n orgId: null,\n orgRole: null,\n orgSlug: null,\n sessionClaims: null,\n sessionId: null,\n signOut,\n userId: null,\n } as const;\n }\n\n if (!!sessionId && !!sessionClaims && !!userId && !!orgId && !!orgRole) {\n return {\n actor: actor || null,\n getToken,\n has,\n isLoaded: true,\n isSignedIn: true,\n orgId,\n orgRole,\n orgSlug: orgSlug || null,\n sessionClaims,\n sessionId,\n signOut,\n userId,\n } as const;\n }\n\n if (!!sessionId && !!sessionClaims && !!userId && !orgId) {\n return {\n actor: actor || null,\n getToken,\n has,\n isLoaded: true,\n isSignedIn: true,\n orgId: null,\n orgRole: null,\n orgSlug: null,\n sessionClaims,\n sessionId,\n signOut,\n userId,\n } as const;\n }\n};\n\nexport { createCheckAuthorization, resolveAuthState, splitByScope, validateReverificationConfig };\n"],"mappings":"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"}
|
|
@@ -21,9 +21,10 @@ declare const validateReverificationConfig: (config: ReverificationConfig | unde
|
|
|
21
21
|
});
|
|
22
22
|
/**
|
|
23
23
|
* Creates a function for comprehensive user authorization checks.
|
|
24
|
-
* Combines organization
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* Combines organization, billing, and reverification checks. The returned function
|
|
25
|
+
* authorizes only when every requested dimension passes; any requested dimension
|
|
26
|
+
* that cannot be satisfied (including missing or malformed session data) denies
|
|
27
|
+
* the request. Fails if `userId` is missing.
|
|
27
28
|
*/
|
|
28
29
|
declare const createCheckAuthorization: (options: AuthorizationOptions) => CheckAuthorizationWithCustomPermissions;
|
|
29
30
|
type AuthStateOptions = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization.d.mts","names":[],"sources":["../../src/authorization.ts"],"sourcesContent":[],"mappings":";;;;KAiBK,oBAAA;;;EAAA,OAAA,EAAA,MAAA,GAAA,IAAA,GAAoB,SAAA;
|
|
1
|
+
{"version":3,"file":"authorization.d.mts","names":[],"sources":["../../src/authorization.ts"],"sourcesContent":[],"mappings":";;;;KAiBK,oBAAA;;;EAAA,OAAA,EAAA,MAAA,GAAA,IAAA,GAAoB,SAAA;EA6LnB,cAAA,EA6BL,MAAA,EAAA,GAAA,IAAA,GAAA,SAAA;EAEK,qBAAA,EAAA,CAAA,MAAA,EAqBL,MAAA,CAAA,GAAA,IAAA;EArB6C,QAAA,EAAA,MAAA,GAAA,IAAA,GAAA,SAAA;;;cA/BxC;EAyIA,GAAA,EAAA,MAAA,EAAA;EAcD,IAAA,EAAA,MAAA,EAAA;CAIe;cA5Hd,4BA6Hc,EAAA,CAAA,MAAA,EA7H0B,oBA6H1B,GAAA,SAAA,GAAA,IAAA,EAAA,GAAA,KAAA,GAAA,CAAA,GAAA,GAAA;EACR,KAAA,0BAAA;EAEE,YAAA,iCAAA;CAEO,CAAA;;;;;;;AAKW;cA7B1B,wBAsCoB,EAAA,CAAA,OAAA,EAtCiB,oBAsCjB,EAAA,GAtCwC,uCAsCxC;KAxBrB,gBAAA,GAwBqB;EAAA,UAAA,EAAA;IAAA,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAAA,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAAA,aAAA,CAAA,EApBN,kBAoBM,GAAA,IAAA;IAAA,aAAA,CAAA,EAnBN,UAmBM,GAAA,IAAA;IAAA,KAAA,CAAA,EAlBd,QAkBc,GAAA,IAAA;IAAA,KAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAAA,OAAA,CAAA,EAhBZ,yBAgBY,GAAA,IAAA;IAAA,OAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAAA,cAAA,CAAA,EAdL,+BAcK,EAAA,GAAA,IAAA;IAevB,QAAA,EA5BW,QA4BX;IAAmB,OAAA,EA3BT,OA2BS;IAAa,GAAA,EAAA,CAAA,MAAA,EA1BjB,UA0BiB,CA1BN,uCA0BM,CAAA,CAAA,CAAA,CAAA,EAAA,GAAA,OAAA;;WAxBxB;;;;;;;;cASL;;;;;;;;;;;;;;;;;GAeH,qBAAmB"}
|
|
@@ -21,9 +21,10 @@ declare const validateReverificationConfig: (config: ReverificationConfig | unde
|
|
|
21
21
|
});
|
|
22
22
|
/**
|
|
23
23
|
* Creates a function for comprehensive user authorization checks.
|
|
24
|
-
* Combines organization
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* Combines organization, billing, and reverification checks. The returned function
|
|
25
|
+
* authorizes only when every requested dimension passes; any requested dimension
|
|
26
|
+
* that cannot be satisfied (including missing or malformed session data) denies
|
|
27
|
+
* the request. Fails if `userId` is missing.
|
|
27
28
|
*/
|
|
28
29
|
declare const createCheckAuthorization: (options: AuthorizationOptions) => CheckAuthorizationWithCustomPermissions;
|
|
29
30
|
type AuthStateOptions = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization.d.ts","names":[],"sources":["../../src/authorization.ts"],"sourcesContent":[],"mappings":";;;;KAiBK,oBAAA;;;EAAA,OAAA,EAAA,MAAA,GAAA,IAAA,GAAoB,SAAA;
|
|
1
|
+
{"version":3,"file":"authorization.d.ts","names":[],"sources":["../../src/authorization.ts"],"sourcesContent":[],"mappings":";;;;KAiBK,oBAAA;;;EAAA,OAAA,EAAA,MAAA,GAAA,IAAA,GAAoB,SAAA;EA6LnB,cAAA,EA6BL,MAAA,EAAA,GAAA,IAAA,GAAA,SAAA;EAEK,qBAAA,EAAA,CAAA,MAAA,EAqBL,MAAA,CAAA,GAAA,IAAA;EArB6C,QAAA,EAAA,MAAA,GAAA,IAAA,GAAA,SAAA;;;cA/BxC;EAyIA,GAAA,EAAA,MAAA,EAAA;EAcD,IAAA,EAAA,MAAA,EAAA;CAIe;cA5Hd,4BA6Hc,EAAA,CAAA,MAAA,EA7H0B,oBA6H1B,GAAA,SAAA,GAAA,IAAA,EAAA,GAAA,KAAA,GAAA,CAAA,GAAA,GAAA;EACR,KAAA,0BAAA;EAEE,YAAA,iCAAA;CAEO,CAAA;;;;;;;AAKW;cA7B1B,wBAsCoB,EAAA,CAAA,OAAA,EAtCiB,oBAsCjB,EAAA,GAtCwC,uCAsCxC;KAxBrB,gBAAA,GAwBqB;EAAA,UAAA,EAAA;IAAA,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAAA,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAAA,aAAA,CAAA,EApBN,kBAoBM,GAAA,IAAA;IAAA,aAAA,CAAA,EAnBN,UAmBM,GAAA,IAAA;IAAA,KAAA,CAAA,EAlBd,QAkBc,GAAA,IAAA;IAAA,KAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAAA,OAAA,CAAA,EAhBZ,yBAgBY,GAAA,IAAA;IAAA,OAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAAA,cAAA,CAAA,EAdL,+BAcK,EAAA,GAAA,IAAA;IAevB,QAAA,EA5BW,QA4BX;IAAmB,OAAA,EA3BT,OA2BS;IAAa,GAAA,EAAA,CAAA,MAAA,EA1BjB,UA0BiB,CA1BN,uCA0BM,CAAA,CAAA,CAAA,CAAA,EAAA,GAAA,OAAA;;WAxBxB;;;;;;;;cASL;;;;;;;;;;;;;;;;;GAeH,qBAAmB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_authorization = require('./authorization-
|
|
1
|
+
const require_authorization = require('./authorization-Dj1hHJtO.js');
|
|
2
2
|
|
|
3
3
|
exports.createCheckAuthorization = require_authorization.createCheckAuthorization;
|
|
4
4
|
exports.resolveAuthState = require_authorization.resolveAuthState;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { i as validateReverificationConfig, n as resolveAuthState, r as splitByScope, t as createCheckAuthorization } from "./authorization-
|
|
1
|
+
import { i as validateReverificationConfig, n as resolveAuthState, r as splitByScope, t as createCheckAuthorization } from "./authorization-Bayl2soX.mjs";
|
|
2
2
|
|
|
3
3
|
export { createCheckAuthorization, resolveAuthState, splitByScope, validateReverificationConfig };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color.d.mts","names":[],"sources":["../../src/color.ts"],"sourcesContent":[],"mappings":";;;;cAUa;cAIA;cAIA;AARA,cAYA,UAVZ,EAAA,CAAA,CAAA,EAU6B,KAV7B,EAAA,GAAA,CAAA,IAU0C,SAV1C;AAEY,cAYA,UAVZ,EAAA,CAAA,CAAA,EAU6B,KAV7B,EAAA,GAAA,CAAA,IAU0C,SAV1C;AAEY,cAYA,aAVZ,EAAA,CAAA,CAAA,EAUgC,KAVhC,EAAA,GAAA,CAAA,IAU6C,gBAV7C;AAEY,cAYA,
|
|
1
|
+
{"version":3,"file":"color.d.mts","names":[],"sources":["../../src/color.ts"],"sourcesContent":[],"mappings":";;;;cAUa;cAIA;cAIA;AARA,cAYA,UAVZ,EAAA,CAAA,CAAA,EAU6B,KAV7B,EAAA,GAAA,CAAA,IAU0C,SAV1C;AAEY,cAYA,UAVZ,EAAA,CAAA,CAAA,EAU6B,KAV7B,EAAA,GAAA,CAAA,IAU0C,SAV1C;AAEY,cAYA,aAVZ,EAAA,CAAA,CAAA,EAUgC,KAVhC,EAAA,GAAA,CAAA,IAU6C,gBAV7C;AAEY,cAYA,QAVZ,EAF6B,CAAA,KAAa,EAYX,KAZW,EAAA,GAE1C,OAAA;AAEY,cAeA,iBAf8B,EAAA,CAAA,KAAA,EAE1C,MAAA,EAAA,GAaiD,SAbjD,GAAA,IAAA;AAEY,cA+BA,qBA/BiC,EAAA,CAAA,KAAA,EAAA,MAE7C,EAAA,GA6BqD,KA7BrD;AAEY,cA+CA,qBA/CwB,EAAA,CAAA,KAAA,EA+CQ,KA/CR,EAAA,GAAA,MAAA,GA+CyB,gBA/CzB;AAOxB,cAwDA,oBAxDqC,EAAA,CAAA,GAAS,EAAA,MAAA,EAAA,GAwDR,SAxDQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"globs.d.ts","names":[],"sources":["../../src/globs.ts"],"sourcesContent":[],"mappings":";cAEa;EAAA,QAUZ,EAAA,CAAA,OAAA,
|
|
1
|
+
{"version":3,"file":"globs.d.ts","names":[],"sources":["../../src/globs.ts"],"sourcesContent":[],"mappings":";cAEa;EAAA,QAUZ,EAAA,CAAA,OAAA,EAT8B,MAAA,EAAM,GAAN,MAAM"}
|