{"version":3,"file":"jwtPayloadParser.mjs","names":[],"sources":["../src/jwtPayloadParser.ts"],"sourcesContent":["import { splitByScope } from './authorization';\nimport type {\n  JwtPayload,\n  OrganizationCustomPermissionKey,\n  OrganizationCustomRoleKey,\n  SharedSignedInAuthObjectProperties,\n} from './types';\n\nconst decimalToBinaryBits = (decimal: string, minimumLength: number): number[] | undefined => {\n  if (!/^\\d+$/.test(decimal)) {\n    return undefined;\n  }\n\n  let remaining = decimal.replace(/^0+/, '') || '0';\n  const bits: number[] = [];\n\n  while (remaining !== '0') {\n    let quotient = '';\n    let remainder = 0;\n\n    for (let i = 0; i < remaining.length; i++) {\n      const value = remainder * 10 + remaining.charCodeAt(i) - 48;\n      const quotientDigit = Math.floor(value / 2);\n\n      if (quotient || quotientDigit !== 0) {\n        quotient += quotientDigit;\n      }\n      remainder = value % 2;\n    }\n\n    bits.push(remainder);\n    remaining = quotient || '0';\n  }\n\n  if (bits.length === 0) {\n    bits.push(0);\n  }\n  while (bits.length < minimumLength) {\n    bits.push(0);\n  }\n\n  return bits;\n};\n\nexport const parsePermissions = ({ per, fpm }: { per?: string; fpm?: string }) => {\n  if (!per || !fpm) {\n    return { permissions: [], featurePermissionMap: [] };\n  }\n\n  const permissions = per.split(',').map(p => p.trim());\n\n  const featurePermissionMap = fpm\n    .split(',')\n    .map(permission => decimalToBinaryBits(permission.trim(), permissions.length) ?? []);\n\n  return { permissions, featurePermissionMap };\n};\n\n/**\n *\n */\nfunction buildOrgPermissions({\n  features,\n  permissions,\n  featurePermissionMap,\n}: {\n  features?: string[];\n  permissions?: string[];\n  featurePermissionMap?: number[][];\n}) {\n  // Early return if any required input is missing\n  if (!features || !permissions || !featurePermissionMap) {\n    return [];\n  }\n\n  const orgPermissions: string[] = [];\n\n  // Process each feature and its permissions in a single loop\n  for (let featureIndex = 0; featureIndex < features.length; featureIndex++) {\n    const feature = features[featureIndex];\n\n    if (featureIndex >= featurePermissionMap.length) {\n      continue;\n    }\n\n    const permissionBits = featurePermissionMap[featureIndex];\n    if (!permissionBits) {\n      continue;\n    }\n\n    for (let permIndex = 0; permIndex < permissionBits.length && permIndex < permissions.length; permIndex++) {\n      if (permissionBits[permIndex] === 1) {\n        orgPermissions.push(`org:${feature}:${permissions[permIndex]}`);\n      }\n    }\n  }\n\n  return orgPermissions;\n}\n\n/**\n * Resolves the signed-in auth state from JWT claims.\n *\n * @experimental\n */\nconst __experimental_JWTPayloadToAuthObjectProperties = (claims: JwtPayload): SharedSignedInAuthObjectProperties => {\n  let orgId: string | undefined;\n  let orgRole: OrganizationCustomRoleKey | undefined;\n  let orgSlug: string | undefined;\n  let orgPermissions: OrganizationCustomPermissionKey[] | undefined;\n\n  // fva can be undefined for instances that have not opt-in\n  const factorVerificationAge = claims.fva ?? null;\n\n  // sts can be undefined for instances that have not opt-in\n  const sessionStatus = claims.sts ?? null;\n\n  switch (claims.v) {\n    case 2: {\n      if (claims.o) {\n        orgId = claims.o?.id;\n        orgSlug = claims.o?.slg;\n\n        if (claims.o?.rol) {\n          orgRole = `org:${claims.o?.rol}`;\n        }\n        const { org } = splitByScope(claims.fea);\n        const { permissions, featurePermissionMap } = parsePermissions({\n          per: claims.o?.per,\n          fpm: claims.o?.fpm,\n        });\n        orgPermissions = buildOrgPermissions({\n          features: org,\n          featurePermissionMap: featurePermissionMap,\n          permissions: permissions,\n        });\n      }\n      break;\n    }\n    default:\n      orgId = claims.org_id;\n      orgRole = claims.org_role;\n      orgSlug = claims.org_slug;\n      orgPermissions = claims.org_permissions;\n      break;\n  }\n\n  return {\n    sessionClaims: claims,\n    sessionId: claims.sid,\n    sessionStatus,\n    actor: claims.act,\n    userId: claims.sub,\n    orgId: orgId,\n    orgRole: orgRole,\n    orgSlug: orgSlug,\n    orgPermissions,\n    factorVerificationAge,\n  };\n};\n\nexport { __experimental_JWTPayloadToAuthObjectProperties };\n"],"mappings":";;;AAQA,MAAM,uBAAuB,SAAiB,kBAAgD;CAC5F,IAAI,CAAC,QAAQ,KAAK,OAAO,GACvB;CAGF,IAAI,YAAY,QAAQ,QAAQ,OAAO,EAAE,KAAK;CAC9C,MAAM,OAAiB,CAAC;CAExB,OAAO,cAAc,KAAK;EACxB,IAAI,WAAW;EACf,IAAI,YAAY;EAEhB,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;GACzC,MAAM,QAAQ,YAAY,KAAK,UAAU,WAAW,CAAC,IAAI;GACzD,MAAM,gBAAgB,KAAK,MAAM,QAAQ,CAAC;GAE1C,IAAI,YAAY,kBAAkB,GAChC,YAAY;GAEd,YAAY,QAAQ;EACtB;EAEA,KAAK,KAAK,SAAS;EACnB,YAAY,YAAY;CAC1B;CAEA,IAAI,KAAK,WAAW,GAClB,KAAK,KAAK,CAAC;CAEb,OAAO,KAAK,SAAS,eACnB,KAAK,KAAK,CAAC;CAGb,OAAO;AACT;AAEA,MAAa,oBAAoB,EAAE,KAAK,UAA0C;CAChF,IAAI,CAAC,OAAO,CAAC,KACX,OAAO;EAAE,aAAa,CAAC;EAAG,sBAAsB,CAAC;CAAE;CAGrD,MAAM,cAAc,IAAI,MAAM,GAAG,CAAC,CAAC,KAAI,MAAK,EAAE,KAAK,CAAC;CAMpD,OAAO;EAAE;EAAa,sBAJO,IAC1B,MAAM,GAAG,CAAC,CACV,KAAI,eAAc,oBAAoB,WAAW,KAAK,GAAG,YAAY,MAAM,KAAK,CAAC,CAE3C;CAAE;AAC7C;;;;AAKA,SAAS,oBAAoB,EAC3B,UACA,aACA,wBAKC;CAED,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,sBAChC,OAAO,CAAC;CAGV,MAAM,iBAA2B,CAAC;CAGlC,KAAK,IAAI,eAAe,GAAG,eAAe,SAAS,QAAQ,gBAAgB;EACzE,MAAM,UAAU,SAAS;EAEzB,IAAI,gBAAgB,qBAAqB,QACvC;EAGF,MAAM,iBAAiB,qBAAqB;EAC5C,IAAI,CAAC,gBACH;EAGF,KAAK,IAAI,YAAY,GAAG,YAAY,eAAe,UAAU,YAAY,YAAY,QAAQ,aAC3F,IAAI,eAAe,eAAe,GAChC,eAAe,KAAK,OAAO,QAAQ,GAAG,YAAY,YAAY;CAGpE;CAEA,OAAO;AACT;;;;;;AAOA,MAAM,mDAAmD,WAA2D;CAClH,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CAGJ,MAAM,wBAAwB,OAAO,OAAO;CAG5C,MAAM,gBAAgB,OAAO,OAAO;CAEpC,QAAQ,OAAO,GAAf;EACE,KAAK;GACH,IAAI,OAAO,GAAG;IACZ,QAAQ,OAAO,GAAG;IAClB,UAAU,OAAO,GAAG;IAEpB,IAAI,OAAO,GAAG,KACZ,UAAU,OAAO,OAAO,GAAG;IAE7B,MAAM,EAAE,QAAQ,aAAa,OAAO,GAAG;IACvC,MAAM,EAAE,aAAa,yBAAyB,iBAAiB;KAC7D,KAAK,OAAO,GAAG;KACf,KAAK,OAAO,GAAG;IACjB,CAAC;IACD,iBAAiB,oBAAoB;KACnC,UAAU;KACY;KACT;IACf,CAAC;GACH;GACA;EAEF;GACE,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,UAAU,OAAO;GACjB,iBAAiB,OAAO;GACxB;CACJ;CAEA,OAAO;EACL,eAAe;EACf,WAAW,OAAO;EAClB;EACA,OAAO,OAAO;EACd,QAAQ,OAAO;EACR;EACE;EACA;EACT;EACA;CACF;AACF"}