{"version":3,"file":"authorization-Un7v7f6J.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>;\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\ntype CheckOrgAuthorization = (\n params: { role?: OrganizationCustomRoleKey; permission?: OrganizationCustomPermissionKey },\n options: Pick,\n) => boolean | null;\n\ntype CheckBillingAuthorization = (\n params: { feature?: string; plan?: string },\n options: Pick,\n) => boolean | null;\n\ntype CheckReverificationAuthorization = (\n params: {\n reverification?: ReverificationConfig;\n },\n { factorVerificationAge }: AuthorizationOptions,\n) => boolean | null;\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(['first_factor', 'second_factor', 'multi_factor']);\n\nconst ALLOWED_TYPES = new Set(['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);\n\nconst prefixWithOrg = (value: string) => value.replace(/^(org:)*/, 'org:');\n\n/**\n * Checks if a user has the required organization-level authorization.\n * Verifies if the user has the specified role or permission within their organization.\n *\n * @returns null, if unable to determine due to missing data or unspecified role/permission.\n */\nconst checkOrgAuthorization: CheckOrgAuthorization = (params, options) => {\n const { orgId, orgRole, orgPermissions } = options;\n if (!params.role && !params.permission) {\n return null;\n }\n\n if (!orgId || !orgRole || !orgPermissions) {\n return null;\n }\n\n if (params.permission) {\n return orgPermissions.includes(prefixWithOrg(params.permission));\n }\n\n if (params.role) {\n return prefixWithOrg(orgRole) === prefixWithOrg(params.role);\n }\n return null;\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\nconst checkBillingAuthorization: CheckBillingAuthorization = (params, options) => {\n const { features, plans } = options;\n\n if (params.feature && features) {\n return checkForFeatureOrPlan(features, params.feature);\n }\n\n if (params.plan && plans) {\n return checkForFeatureOrPlan(plans, params.plan);\n }\n return null;\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 * Compares the user's factor verification ages against the specified maxAge.\n * Handles different verification levels (first factor, second factor, multi-factor).\n *\n * @returns null, if requirements or verification data are missing.\n */\nconst checkReverificationAuthorization: CheckReverificationAuthorization = (params, { factorVerificationAge }) => {\n if (!params.reverification || !factorVerificationAge) {\n return null;\n }\n\n const isValidReverification = validateReverificationConfig(params.reverification);\n if (!isValidReverification) {\n return null;\n }\n\n const { level, afterMinutes } = isValidReverification();\n const [factor1Age, factor2Age] = factorVerificationAge;\n\n // -1 indicates the factor group (1fa,2fa) is not enabled\n // -1 for 1fa is not a valid scenario, but we need to make sure we handle it properly\n const isValidFactor1 = factor1Age !== -1 ? afterMinutes > factor1Age : null;\n const isValidFactor2 = factor2Age !== -1 ? afterMinutes > factor2Age : null;\n\n switch (level) {\n case 'first_factor':\n return isValidFactor1;\n case 'second_factor':\n return factor2Age !== -1 ? isValidFactor2 : isValidFactor1;\n case 'multi_factor':\n return factor2Age === -1 ? isValidFactor1 : isValidFactor1 && isValidFactor2;\n }\n};\n\n/**\n * Creates a function for comprehensive user authorization checks.\n * Combines organization-level and reverification authentication checks.\n * The returned function authorizes if both checks pass, or if at least one passes\n * when the other is indeterminate. 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 const billingAuthorization = checkBillingAuthorization(params, options);\n const orgAuthorization = checkOrgAuthorization(params, options);\n const reverificationAuthorization = checkReverificationAuthorization(params, options);\n\n if ([billingAuthorization || orgAuthorization, reverificationAuthorization].some(a => a === null)) {\n return [billingAuthorization || orgAuthorization, reverificationAuthorization].some(a => a === true);\n }\n\n return [billingAuthorization || orgAuthorization, reverificationAuthorization].every(a => a === true);\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[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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"}