{"version":3,"file":"authorization.mjs","names":[],"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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"}