@thunderid/react 0.10.1 → 0.11.1

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.
Files changed (55) hide show
  1. package/dist/cjs/components/adapters/Consent.cjs +96 -9
  2. package/dist/cjs/components/adapters/Consent.cjs.map +1 -1
  3. package/dist/cjs/components/adapters/ConsentCheckboxList.cjs +8 -6
  4. package/dist/cjs/components/adapters/ConsentCheckboxList.cjs.map +1 -1
  5. package/dist/cjs/components/adapters/ConsentCheckboxList.styles.cjs +1 -0
  6. package/dist/cjs/components/adapters/ConsentCheckboxList.styles.cjs.map +1 -1
  7. package/dist/cjs/components/presentation/UserDropdown/BaseUserDropdown.cjs +2 -2
  8. package/dist/cjs/components/presentation/UserProfile/BaseUserProfile.cjs +1 -1
  9. package/dist/cjs/components/presentation/auth/AuthOptionFactory.cjs +23 -4
  10. package/dist/cjs/components/presentation/auth/AuthOptionFactory.cjs.map +1 -1
  11. package/dist/cjs/components/primitives/Dialog/Dialog.cjs +1 -1
  12. package/dist/cjs/components/primitives/KeyValueInput/KeyValueInput.cjs +1 -1
  13. package/dist/cjs/components/primitives/PasswordField/PasswordField.cjs +1 -1
  14. package/dist/cjs/components/primitives/Tooltip/Tooltip.cjs +60 -0
  15. package/dist/cjs/components/primitives/Tooltip/Tooltip.cjs.map +1 -0
  16. package/dist/cjs/components/primitives/Tooltip/Tooltip.styles.cjs +110 -0
  17. package/dist/cjs/components/primitives/Tooltip/Tooltip.styles.cjs.map +1 -0
  18. package/dist/cjs/index.cjs +8 -8
  19. package/dist/cjs/utils/buildThemeConfigFromFlowMeta.cjs +6 -7
  20. package/dist/cjs/utils/buildThemeConfigFromFlowMeta.cjs.map +1 -1
  21. package/dist/cjs/utils/passkey.cjs +2 -2
  22. package/dist/cjs/utils/passkey.cjs.map +1 -1
  23. package/dist/components/adapters/Consent.d.ts +23 -1
  24. package/dist/components/adapters/Consent.d.ts.map +1 -1
  25. package/dist/components/adapters/Consent.js +96 -10
  26. package/dist/components/adapters/Consent.js.map +1 -1
  27. package/dist/components/adapters/ConsentCheckboxList.d.ts.map +1 -1
  28. package/dist/components/adapters/ConsentCheckboxList.js +8 -6
  29. package/dist/components/adapters/ConsentCheckboxList.js.map +1 -1
  30. package/dist/components/adapters/ConsentCheckboxList.styles.d.ts.map +1 -1
  31. package/dist/components/adapters/ConsentCheckboxList.styles.js +1 -0
  32. package/dist/components/adapters/ConsentCheckboxList.styles.js.map +1 -1
  33. package/dist/components/presentation/UserDropdown/BaseUserDropdown.js +2 -2
  34. package/dist/components/presentation/UserProfile/BaseUserProfile.js +1 -1
  35. package/dist/components/presentation/auth/AuthOptionFactory.d.ts.map +1 -1
  36. package/dist/components/presentation/auth/AuthOptionFactory.js +23 -4
  37. package/dist/components/presentation/auth/AuthOptionFactory.js.map +1 -1
  38. package/dist/components/primitives/Dialog/Dialog.js +1 -1
  39. package/dist/components/primitives/KeyValueInput/KeyValueInput.js +1 -1
  40. package/dist/components/primitives/PasswordField/PasswordField.js +1 -1
  41. package/dist/components/primitives/Tooltip/Tooltip.d.ts +40 -0
  42. package/dist/components/primitives/Tooltip/Tooltip.d.ts.map +1 -0
  43. package/dist/components/primitives/Tooltip/Tooltip.js +55 -0
  44. package/dist/components/primitives/Tooltip/Tooltip.js.map +1 -0
  45. package/dist/components/primitives/Tooltip/Tooltip.styles.d.ts +21 -0
  46. package/dist/components/primitives/Tooltip/Tooltip.styles.d.ts.map +1 -0
  47. package/dist/components/primitives/Tooltip/Tooltip.styles.js +107 -0
  48. package/dist/components/primitives/Tooltip/Tooltip.styles.js.map +1 -0
  49. package/dist/index.js +5 -5
  50. package/dist/utils/buildThemeConfigFromFlowMeta.d.ts.map +1 -1
  51. package/dist/utils/buildThemeConfigFromFlowMeta.js +5 -7
  52. package/dist/utils/buildThemeConfigFromFlowMeta.js.map +1 -1
  53. package/dist/utils/passkey.js +2 -2
  54. package/dist/utils/passkey.js.map +1 -1
  55. package/package.json +2 -2
@@ -1,3 +1,5 @@
1
+ import { normalizeBorderRadius } from "@thunderid/browser";
2
+
1
3
  //#region src/utils/buildThemeConfigFromFlowMeta.ts
2
4
  /**
3
5
  * Converts a v2 `FlowMetaTheme` into a `RecursivePartial<ThemeConfig>` that
@@ -14,8 +16,7 @@
14
16
  */
15
17
  const buildThemeConfigFromFlowMeta = (flowMetaTheme, colorScheme) => {
16
18
  const scheme = flowMetaTheme.colorSchemes?.[colorScheme];
17
- const borderRadius = flowMetaTheme.shape?.borderRadius;
18
- const borderRadiusStr = borderRadius !== void 0 ? `${borderRadius}px` : void 0;
19
+ const borderRadiusConfig = normalizeBorderRadius(flowMetaTheme.shape?.borderRadius);
19
20
  let colors;
20
21
  if (scheme?.palette) {
21
22
  colors = {};
@@ -30,12 +31,9 @@ const buildThemeConfigFromFlowMeta = (flowMetaTheme, colorScheme) => {
30
31
  }
31
32
  }
32
33
  return {
34
+ ...flowMetaTheme,
33
35
  ...flowMetaTheme.direction ? { direction: flowMetaTheme.direction } : {},
34
- ...borderRadiusStr ? { borderRadius: {
35
- large: borderRadiusStr,
36
- medium: borderRadiusStr,
37
- small: borderRadiusStr
38
- } } : {},
36
+ ...borderRadiusConfig ? { borderRadius: borderRadiusConfig } : {},
39
37
  ...colors && Object.keys(colors).length > 0 ? { colors } : {},
40
38
  ...flowMetaTheme.typography?.fontFamily ? { typography: { fontFamily: flowMetaTheme.typography.fontFamily } } : {}
41
39
  };
@@ -1 +1 @@
1
- {"version":3,"file":"buildThemeConfigFromFlowMeta.js","names":["scheme: FlowMetaThemeColorScheme | undefined","borderRadius: number | undefined","borderRadiusStr: string | undefined","colors: RecursivePartial<ThemeConfig['colors']> | undefined","bg: RecursivePartial<ThemeConfig['colors']['background']>"],"sources":["../../src/utils/buildThemeConfigFromFlowMeta.ts"],"sourcesContent":["/**\n * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {FlowMetaTheme, FlowMetaThemeColorScheme, RecursivePartial, ThemeConfig} from '@thunderid/browser';\n\n/**\n * Converts a v2 `FlowMetaTheme` into a `RecursivePartial<ThemeConfig>` that\n * `createTheme` can consume.\n *\n * Only fields explicitly present in the FlowMeta response are included so that\n * `createTheme` can deep-merge them onto its base (light/dark) defaults without\n * accidentally dropping sibling keys that were not returned by the server.\n *\n * For example, when FlowMeta returns only `background.default` and\n * `background.paper`, only `body.main` and `surface` are set — the base\n * theme's `background.disabled` and `background.dark` are **not** overridden\n * and therefore keep their default CSS variable values.\n */\nconst buildThemeConfigFromFlowMeta = (\n flowMetaTheme: FlowMetaTheme,\n colorScheme: 'light' | 'dark',\n): RecursivePartial<ThemeConfig> => {\n const scheme: FlowMetaThemeColorScheme | undefined = flowMetaTheme.colorSchemes?.[colorScheme];\n const borderRadius: number | undefined = flowMetaTheme.shape?.borderRadius;\n const borderRadiusStr: string | undefined = borderRadius !== undefined ? `${borderRadius}px` : undefined;\n\n // Build only the colors that the server actually provided.\n // Each nested object is constructed incrementally so that absent fields are\n // simply omitted rather than set to `undefined`, which would shadow the\n // base-theme defaults inside `createTheme`.\n let colors: RecursivePartial<ThemeConfig['colors']> | undefined;\n\n if (scheme?.palette) {\n colors = {};\n\n if (scheme.palette.primary) {\n colors.primary = scheme.palette.primary;\n }\n if (scheme.palette.secondary) {\n colors.secondary = scheme.palette.secondary;\n }\n if (scheme.palette.text) {\n colors.text = scheme.palette.text;\n }\n\n // Build background incrementally to avoid replacing the full base object.\n if (scheme.palette.background) {\n const bg: RecursivePartial<ThemeConfig['colors']['background']> = {};\n\n if (scheme.palette.background.default) {\n bg.body = {main: scheme.palette.background.default};\n }\n if (scheme.palette.background.paper) {\n bg.surface = scheme.palette.background.paper;\n }\n\n if (Object.keys(bg).length > 0) {\n colors.background = bg;\n }\n }\n }\n\n return {\n ...(flowMetaTheme.direction ? {direction: flowMetaTheme.direction} : {}),\n ...(borderRadiusStr\n ? {\n borderRadius: {\n large: borderRadiusStr,\n medium: borderRadiusStr,\n small: borderRadiusStr,\n },\n }\n : {}),\n ...(colors && Object.keys(colors).length > 0 ? {colors} : {}),\n ...(flowMetaTheme.typography?.fontFamily ? {typography: {fontFamily: flowMetaTheme.typography.fontFamily}} : {}),\n };\n};\n\nexport default buildThemeConfigFromFlowMeta;\n"],"mappings":";;;;;;;;;;;;;;AAiCA,MAAM,gCACJ,eACA,gBACkC;CAClC,MAAMA,SAA+C,cAAc,eAAe;CAClF,MAAMC,eAAmC,cAAc,OAAO;CAC9D,MAAMC,kBAAsC,iBAAiB,SAAY,GAAG,aAAa,MAAM;CAM/F,IAAIC;AAEJ,KAAI,QAAQ,SAAS;AACnB,WAAS,EAAE;AAEX,MAAI,OAAO,QAAQ,QACjB,QAAO,UAAU,OAAO,QAAQ;AAElC,MAAI,OAAO,QAAQ,UACjB,QAAO,YAAY,OAAO,QAAQ;AAEpC,MAAI,OAAO,QAAQ,KACjB,QAAO,OAAO,OAAO,QAAQ;AAI/B,MAAI,OAAO,QAAQ,YAAY;GAC7B,MAAMC,KAA4D,EAAE;AAEpE,OAAI,OAAO,QAAQ,WAAW,QAC5B,IAAG,OAAO,EAAC,MAAM,OAAO,QAAQ,WAAW,SAAQ;AAErD,OAAI,OAAO,QAAQ,WAAW,MAC5B,IAAG,UAAU,OAAO,QAAQ,WAAW;AAGzC,OAAI,OAAO,KAAK,GAAG,CAAC,SAAS,EAC3B,QAAO,aAAa;;;AAK1B,QAAO;EACL,GAAI,cAAc,YAAY,EAAC,WAAW,cAAc,WAAU,GAAG,EAAE;EACvE,GAAI,kBACA,EACE,cAAc;GACZ,OAAO;GACP,QAAQ;GACR,OAAO;GACR,EACF,GACD,EAAE;EACN,GAAI,UAAU,OAAO,KAAK,OAAO,CAAC,SAAS,IAAI,EAAC,QAAO,GAAG,EAAE;EAC5D,GAAI,cAAc,YAAY,aAAa,EAAC,YAAY,EAAC,YAAY,cAAc,WAAW,YAAW,EAAC,GAAG,EAAE;EAChH;;AAGH,2CAAe"}
1
+ {"version":3,"file":"buildThemeConfigFromFlowMeta.js","names":["scheme: FlowMetaThemeColorScheme | undefined","colors: RecursivePartial<ThemeConfig['colors']> | undefined","bg: RecursivePartial<ThemeConfig['colors']['background']>"],"sources":["../../src/utils/buildThemeConfigFromFlowMeta.ts"],"sourcesContent":["/**\n * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {\n FlowMetaTheme,\n FlowMetaThemeColorScheme,\n RecursivePartial,\n ThemeConfig,\n normalizeBorderRadius,\n} from '@thunderid/browser';\n\n/**\n * Converts a v2 `FlowMetaTheme` into a `RecursivePartial<ThemeConfig>` that\n * `createTheme` can consume.\n *\n * Only fields explicitly present in the FlowMeta response are included so that\n * `createTheme` can deep-merge them onto its base (light/dark) defaults without\n * accidentally dropping sibling keys that were not returned by the server.\n *\n * For example, when FlowMeta returns only `background.default` and\n * `background.paper`, only `body.main` and `surface` are set — the base\n * theme's `background.disabled` and `background.dark` are **not** overridden\n * and therefore keep their default CSS variable values.\n */\nconst buildThemeConfigFromFlowMeta = (\n flowMetaTheme: FlowMetaTheme,\n colorScheme: 'light' | 'dark',\n): RecursivePartial<ThemeConfig> => {\n const scheme: FlowMetaThemeColorScheme | undefined = flowMetaTheme.colorSchemes?.[colorScheme];\n const borderRadiusConfig = normalizeBorderRadius(flowMetaTheme.shape?.borderRadius);\n\n // Build only the colors that the server actually provided.\n // Each nested object is constructed incrementally so that absent fields are\n // simply omitted rather than set to `undefined`, which would shadow the\n // base-theme defaults inside `createTheme`.\n let colors: RecursivePartial<ThemeConfig['colors']> | undefined;\n\n if (scheme?.palette) {\n colors = {};\n\n if (scheme.palette.primary) {\n colors.primary = scheme.palette.primary;\n }\n if (scheme.palette.secondary) {\n colors.secondary = scheme.palette.secondary;\n }\n if (scheme.palette.text) {\n colors.text = scheme.palette.text;\n }\n\n // Build background incrementally to avoid replacing the full base object.\n if (scheme.palette.background) {\n const bg: RecursivePartial<ThemeConfig['colors']['background']> = {};\n\n if (scheme.palette.background.default) {\n bg.body = {main: scheme.palette.background.default};\n }\n if (scheme.palette.background.paper) {\n bg.surface = scheme.palette.background.paper;\n }\n\n if (Object.keys(bg).length > 0) {\n colors.background = bg;\n }\n }\n }\n\n return {\n ...flowMetaTheme,\n ...(flowMetaTheme.direction ? {direction: flowMetaTheme.direction} : {}),\n ...(borderRadiusConfig ? {borderRadius: borderRadiusConfig} : {}),\n ...(colors && Object.keys(colors).length > 0 ? {colors} : {}),\n ...(flowMetaTheme.typography?.fontFamily ? {typography: {fontFamily: flowMetaTheme.typography.fontFamily}} : {}),\n };\n};\n\nexport default buildThemeConfigFromFlowMeta;\n"],"mappings":";;;;;;;;;;;;;;;;AAuCA,MAAM,gCACJ,eACA,gBACkC;CAClC,MAAMA,SAA+C,cAAc,eAAe;CAClF,MAAM,qBAAqB,sBAAsB,cAAc,OAAO,aAAa;CAMnF,IAAIC;AAEJ,KAAI,QAAQ,SAAS;AACnB,WAAS,EAAE;AAEX,MAAI,OAAO,QAAQ,QACjB,QAAO,UAAU,OAAO,QAAQ;AAElC,MAAI,OAAO,QAAQ,UACjB,QAAO,YAAY,OAAO,QAAQ;AAEpC,MAAI,OAAO,QAAQ,KACjB,QAAO,OAAO,OAAO,QAAQ;AAI/B,MAAI,OAAO,QAAQ,YAAY;GAC7B,MAAMC,KAA4D,EAAE;AAEpE,OAAI,OAAO,QAAQ,WAAW,QAC5B,IAAG,OAAO,EAAC,MAAM,OAAO,QAAQ,WAAW,SAAQ;AAErD,OAAI,OAAO,QAAQ,WAAW,MAC5B,IAAG,UAAU,OAAO,QAAQ,WAAW;AAGzC,OAAI,OAAO,KAAK,GAAG,CAAC,SAAS,EAC3B,QAAO,aAAa;;;AAK1B,QAAO;EACL,GAAG;EACH,GAAI,cAAc,YAAY,EAAC,WAAW,cAAc,WAAU,GAAG,EAAE;EACvE,GAAI,qBAAqB,EAAC,cAAc,oBAAmB,GAAG,EAAE;EAChE,GAAI,UAAU,OAAO,KAAK,OAAO,CAAC,SAAS,IAAI,EAAC,QAAO,GAAG,EAAE;EAC5D,GAAI,cAAc,YAAY,aAAa,EAAC,YAAY,EAAC,YAAY,cAAc,WAAW,YAAW,EAAC,GAAG,EAAE;EAChH;;AAGH,2CAAe"}
@@ -40,7 +40,7 @@ const handlePasskeyRegistration = async (challengeData) => {
40
40
  return JSON.stringify(registrationResponse);
41
41
  } catch (error) {
42
42
  if (error instanceof ThunderIDRuntimeError) throw error;
43
- if (error instanceof Error) throw new ThunderIDRuntimeError(`Passkey registration failed: ${error.message}`, "browser-webauthn-registration-error", "browser", `WebAuthn registration failed with error: ${error.name}`);
43
+ if (error instanceof Error) throw new ThunderIDRuntimeError("Passkey registration failed. Please try again.", "browser-webauthn-registration-error", "browser", `WebAuthn registration failed with error: ${error.name}: ${error.message}`);
44
44
  throw new ThunderIDRuntimeError("Passkey registration failed due to an unexpected error.", "browser-webauthn-unexpected-error", "browser", "An unexpected error occurred during WebAuthn registration.");
45
45
  }
46
46
  };
@@ -80,7 +80,7 @@ const handlePasskeyAuthentication = async (challengeData) => {
80
80
  return JSON.stringify(authenticationResponse);
81
81
  } catch (error) {
82
82
  if (error instanceof ThunderIDRuntimeError) throw error;
83
- if (error instanceof Error) throw new ThunderIDRuntimeError(`Passkey authentication failed: ${error.message}`, "browser-webauthn-authentication-error", "browser", `WebAuthn authentication failed with error: ${error.name}`);
83
+ if (error instanceof Error) throw new ThunderIDRuntimeError("Passkey authentication failed. Please try again.", "browser-webauthn-authentication-error", "browser", `WebAuthn authentication failed with error: ${error.name}: ${error.message}`);
84
84
  throw new ThunderIDRuntimeError("Passkey authentication failed due to an unexpected error.", "browser-webauthn-unexpected-error", "browser", "An unexpected error occurred during WebAuthn authentication.");
85
85
  }
86
86
  };
@@ -1 +1 @@
1
- {"version":3,"file":"passkey.js","names":["creationOptions: any","publicKey: any","credential: PublicKeyCredential","response: AuthenticatorAttestationResponse","registrationResponse: any","requestOptions: any","response: AuthenticatorAssertionResponse","authenticationResponse: any"],"sources":["../../src/utils/passkey.ts"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {ThunderIDRuntimeError, arrayBufferToBase64url, base64urlToArrayBuffer} from '@thunderid/browser';\n\n/**\n * Handles WebAuthn/Passkey registration flow for browser environments.\n *\n * @param challengeData - JSON stringified challenge data containing WebAuthn creation options.\n * @returns Promise that resolves to a JSON string containing the WebAuthn registration response.\n */\nexport const handlePasskeyRegistration = async (challengeData: string): Promise<string> => {\n if (!window.navigator.credentials?.create) {\n throw new ThunderIDRuntimeError(\n 'WebAuthn is not supported in this browser.',\n 'browser-webauthn-not-supported',\n 'browser',\n 'WebAuthn/Passkey registration requires a browser that supports the Web Authentication API.',\n );\n }\n\n try {\n const creationOptions: any = JSON.parse(challengeData);\n\n // Decode challenge and user ID from base64url to BufferSource\n const publicKey: any = {\n ...creationOptions,\n challenge: base64urlToArrayBuffer(creationOptions.challenge),\n user: {\n ...creationOptions.user,\n id: base64urlToArrayBuffer(creationOptions.user.id),\n },\n ...(creationOptions.excludeCredentials && {\n excludeCredentials: creationOptions.excludeCredentials.map((cred: any) => ({\n ...cred,\n id: base64urlToArrayBuffer(cred.id),\n })),\n }),\n };\n\n const credential: PublicKeyCredential = (await navigator.credentials.create({\n publicKey,\n })) as PublicKeyCredential;\n\n if (!credential) {\n throw new ThunderIDRuntimeError(\n 'No credential returned from WebAuthn registration.',\n 'browser-webauthn-no-credential',\n 'browser',\n 'The WebAuthn registration ceremony completed but did not return a valid credential.',\n );\n }\n\n const response: AuthenticatorAttestationResponse = credential.response as AuthenticatorAttestationResponse;\n\n // Encode response fields back to base64url\n const registrationResponse: any = {\n id: credential.id,\n rawId: arrayBufferToBase64url(credential.rawId),\n response: {\n attestationObject: arrayBufferToBase64url(response.attestationObject),\n clientDataJSON: arrayBufferToBase64url(response.clientDataJSON),\n ...(response.getTransports && {\n transports: response.getTransports(),\n }),\n },\n type: credential.type,\n ...(credential.authenticatorAttachment && {\n authenticatorAttachment: credential.authenticatorAttachment,\n }),\n };\n\n return JSON.stringify(registrationResponse);\n } catch (error) {\n if (error instanceof ThunderIDRuntimeError) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Map specific WebAuthn errors to ThunderIDRuntimeError/friendly messages as needed\n throw new ThunderIDRuntimeError(\n `Passkey registration failed: ${error.message}`,\n 'browser-webauthn-registration-error',\n 'browser',\n `WebAuthn registration failed with error: ${error.name}`,\n );\n }\n\n throw new ThunderIDRuntimeError(\n 'Passkey registration failed due to an unexpected error.',\n 'browser-webauthn-unexpected-error',\n 'browser',\n 'An unexpected error occurred during WebAuthn registration.',\n );\n }\n};\n\n/**\n * Handles WebAuthn/Passkey authentication flow for browser environments.\n *\n * @param challengeData - JSON stringified challenge data containing WebAuthn request options.\n * @returns Promise that resolves to a JSON string containing the WebAuthn authentication response.\n */\nexport const handlePasskeyAuthentication = async (challengeData: string): Promise<string> => {\n if (!window.navigator.credentials?.get) {\n throw new ThunderIDRuntimeError(\n 'WebAuthn is not supported in this browser.',\n 'browser-webauthn-not-supported',\n 'browser',\n 'WebAuthn/Passkey authentication requires a browser that supports the Web Authentication API.',\n );\n }\n\n try {\n const requestOptions: any = JSON.parse(challengeData);\n\n // Decode challenge and allowed credentials from base64url to BufferSource\n const publicKey: any = {\n ...requestOptions,\n challenge: base64urlToArrayBuffer(requestOptions.challenge),\n ...(requestOptions.allowCredentials && {\n allowCredentials: requestOptions.allowCredentials.map((cred: any) => ({\n ...cred,\n id: base64urlToArrayBuffer(cred.id),\n })),\n }),\n };\n\n const credential: PublicKeyCredential = (await navigator.credentials.get({\n publicKey,\n })) as PublicKeyCredential;\n\n if (!credential) {\n throw new ThunderIDRuntimeError(\n 'No credential returned from WebAuthn authentication.',\n 'browser-webauthn-no-credential',\n 'browser',\n 'The WebAuthn authentication ceremony completed but did not return a valid credential.',\n );\n }\n\n const response: AuthenticatorAssertionResponse = credential.response as AuthenticatorAssertionResponse;\n\n // Encode response fields back to base64url\n const authenticationResponse: any = {\n id: credential.id,\n rawId: arrayBufferToBase64url(credential.rawId),\n response: {\n authenticatorData: arrayBufferToBase64url(response.authenticatorData),\n clientDataJSON: arrayBufferToBase64url(response.clientDataJSON),\n signature: arrayBufferToBase64url(response.signature),\n ...(response.userHandle && {\n userHandle: arrayBufferToBase64url(response.userHandle),\n }),\n },\n type: credential.type,\n ...(credential.authenticatorAttachment && {\n authenticatorAttachment: credential.authenticatorAttachment,\n }),\n };\n\n return JSON.stringify(authenticationResponse);\n } catch (error) {\n if (error instanceof ThunderIDRuntimeError) {\n throw error;\n }\n\n if (error instanceof Error) {\n throw new ThunderIDRuntimeError(\n `Passkey authentication failed: ${error.message}`,\n 'browser-webauthn-authentication-error',\n 'browser',\n `WebAuthn authentication failed with error: ${error.name}`,\n );\n }\n\n throw new ThunderIDRuntimeError(\n 'Passkey authentication failed due to an unexpected error.',\n 'browser-webauthn-unexpected-error',\n 'browser',\n 'An unexpected error occurred during WebAuthn authentication.',\n );\n }\n};\n"],"mappings":";;;;;;;;;AA0BA,MAAa,4BAA4B,OAAO,kBAA2C;AACzF,KAAI,CAAC,OAAO,UAAU,aAAa,OACjC,OAAM,IAAI,sBACR,8CACA,kCACA,WACA,6FACD;AAGH,KAAI;EACF,MAAMA,kBAAuB,KAAK,MAAM,cAAc;EAGtD,MAAMC,YAAiB;GACrB,GAAG;GACH,WAAW,uBAAuB,gBAAgB,UAAU;GAC5D,MAAM;IACJ,GAAG,gBAAgB;IACnB,IAAI,uBAAuB,gBAAgB,KAAK,GAAG;IACpD;GACD,GAAI,gBAAgB,sBAAsB,EACxC,oBAAoB,gBAAgB,mBAAmB,KAAK,UAAe;IACzE,GAAG;IACH,IAAI,uBAAuB,KAAK,GAAG;IACpC,EAAE,EACJ;GACF;EAED,MAAMC,aAAmC,MAAM,UAAU,YAAY,OAAO,EAC1E,WACD,CAAC;AAEF,MAAI,CAAC,WACH,OAAM,IAAI,sBACR,sDACA,kCACA,WACA,sFACD;EAGH,MAAMC,WAA6C,WAAW;EAG9D,MAAMC,uBAA4B;GAChC,IAAI,WAAW;GACf,OAAO,uBAAuB,WAAW,MAAM;GAC/C,UAAU;IACR,mBAAmB,uBAAuB,SAAS,kBAAkB;IACrE,gBAAgB,uBAAuB,SAAS,eAAe;IAC/D,GAAI,SAAS,iBAAiB,EAC5B,YAAY,SAAS,eAAe,EACrC;IACF;GACD,MAAM,WAAW;GACjB,GAAI,WAAW,2BAA2B,EACxC,yBAAyB,WAAW,yBACrC;GACF;AAED,SAAO,KAAK,UAAU,qBAAqB;UACpC,OAAO;AACd,MAAI,iBAAiB,sBACnB,OAAM;AAGR,MAAI,iBAAiB,MAEnB,OAAM,IAAI,sBACR,gCAAgC,MAAM,WACtC,uCACA,WACA,4CAA4C,MAAM,OACnD;AAGH,QAAM,IAAI,sBACR,2DACA,qCACA,WACA,6DACD;;;;;;;;;AAUL,MAAa,8BAA8B,OAAO,kBAA2C;AAC3F,KAAI,CAAC,OAAO,UAAU,aAAa,IACjC,OAAM,IAAI,sBACR,8CACA,kCACA,WACA,+FACD;AAGH,KAAI;EACF,MAAMC,iBAAsB,KAAK,MAAM,cAAc;EAGrD,MAAMJ,YAAiB;GACrB,GAAG;GACH,WAAW,uBAAuB,eAAe,UAAU;GAC3D,GAAI,eAAe,oBAAoB,EACrC,kBAAkB,eAAe,iBAAiB,KAAK,UAAe;IACpE,GAAG;IACH,IAAI,uBAAuB,KAAK,GAAG;IACpC,EAAE,EACJ;GACF;EAED,MAAMC,aAAmC,MAAM,UAAU,YAAY,IAAI,EACvE,WACD,CAAC;AAEF,MAAI,CAAC,WACH,OAAM,IAAI,sBACR,wDACA,kCACA,WACA,wFACD;EAGH,MAAMI,WAA2C,WAAW;EAG5D,MAAMC,yBAA8B;GAClC,IAAI,WAAW;GACf,OAAO,uBAAuB,WAAW,MAAM;GAC/C,UAAU;IACR,mBAAmB,uBAAuB,SAAS,kBAAkB;IACrE,gBAAgB,uBAAuB,SAAS,eAAe;IAC/D,WAAW,uBAAuB,SAAS,UAAU;IACrD,GAAI,SAAS,cAAc,EACzB,YAAY,uBAAuB,SAAS,WAAW,EACxD;IACF;GACD,MAAM,WAAW;GACjB,GAAI,WAAW,2BAA2B,EACxC,yBAAyB,WAAW,yBACrC;GACF;AAED,SAAO,KAAK,UAAU,uBAAuB;UACtC,OAAO;AACd,MAAI,iBAAiB,sBACnB,OAAM;AAGR,MAAI,iBAAiB,MACnB,OAAM,IAAI,sBACR,kCAAkC,MAAM,WACxC,yCACA,WACA,8CAA8C,MAAM,OACrD;AAGH,QAAM,IAAI,sBACR,6DACA,qCACA,WACA,+DACD"}
1
+ {"version":3,"file":"passkey.js","names":["creationOptions: any","publicKey: any","credential: PublicKeyCredential","response: AuthenticatorAttestationResponse","registrationResponse: any","requestOptions: any","response: AuthenticatorAssertionResponse","authenticationResponse: any"],"sources":["../../src/utils/passkey.ts"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {ThunderIDRuntimeError, arrayBufferToBase64url, base64urlToArrayBuffer} from '@thunderid/browser';\n\n/**\n * Handles WebAuthn/Passkey registration flow for browser environments.\n *\n * @param challengeData - JSON stringified challenge data containing WebAuthn creation options.\n * @returns Promise that resolves to a JSON string containing the WebAuthn registration response.\n */\nexport const handlePasskeyRegistration = async (challengeData: string): Promise<string> => {\n if (!window.navigator.credentials?.create) {\n throw new ThunderIDRuntimeError(\n 'WebAuthn is not supported in this browser.',\n 'browser-webauthn-not-supported',\n 'browser',\n 'WebAuthn/Passkey registration requires a browser that supports the Web Authentication API.',\n );\n }\n\n try {\n const creationOptions: any = JSON.parse(challengeData);\n\n // Decode challenge and user ID from base64url to BufferSource\n const publicKey: any = {\n ...creationOptions,\n challenge: base64urlToArrayBuffer(creationOptions.challenge),\n user: {\n ...creationOptions.user,\n id: base64urlToArrayBuffer(creationOptions.user.id),\n },\n ...(creationOptions.excludeCredentials && {\n excludeCredentials: creationOptions.excludeCredentials.map((cred: any) => ({\n ...cred,\n id: base64urlToArrayBuffer(cred.id),\n })),\n }),\n };\n\n const credential: PublicKeyCredential = (await navigator.credentials.create({\n publicKey,\n })) as PublicKeyCredential;\n\n if (!credential) {\n throw new ThunderIDRuntimeError(\n 'No credential returned from WebAuthn registration.',\n 'browser-webauthn-no-credential',\n 'browser',\n 'The WebAuthn registration ceremony completed but did not return a valid credential.',\n );\n }\n\n const response: AuthenticatorAttestationResponse = credential.response as AuthenticatorAttestationResponse;\n\n // Encode response fields back to base64url\n const registrationResponse: any = {\n id: credential.id,\n rawId: arrayBufferToBase64url(credential.rawId),\n response: {\n attestationObject: arrayBufferToBase64url(response.attestationObject),\n clientDataJSON: arrayBufferToBase64url(response.clientDataJSON),\n ...(response.getTransports && {\n transports: response.getTransports(),\n }),\n },\n type: credential.type,\n ...(credential.authenticatorAttachment && {\n authenticatorAttachment: credential.authenticatorAttachment,\n }),\n };\n\n return JSON.stringify(registrationResponse);\n } catch (error) {\n if (error instanceof ThunderIDRuntimeError) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Map specific WebAuthn errors to ThunderIDRuntimeError/friendly messages as needed\n throw new ThunderIDRuntimeError(\n 'Passkey registration failed. Please try again.',\n 'browser-webauthn-registration-error',\n 'browser',\n `WebAuthn registration failed with error: ${error.name}: ${error.message}`,\n );\n }\n\n throw new ThunderIDRuntimeError(\n 'Passkey registration failed due to an unexpected error.',\n 'browser-webauthn-unexpected-error',\n 'browser',\n 'An unexpected error occurred during WebAuthn registration.',\n );\n }\n};\n\n/**\n * Handles WebAuthn/Passkey authentication flow for browser environments.\n *\n * @param challengeData - JSON stringified challenge data containing WebAuthn request options.\n * @returns Promise that resolves to a JSON string containing the WebAuthn authentication response.\n */\nexport const handlePasskeyAuthentication = async (challengeData: string): Promise<string> => {\n if (!window.navigator.credentials?.get) {\n throw new ThunderIDRuntimeError(\n 'WebAuthn is not supported in this browser.',\n 'browser-webauthn-not-supported',\n 'browser',\n 'WebAuthn/Passkey authentication requires a browser that supports the Web Authentication API.',\n );\n }\n\n try {\n const requestOptions: any = JSON.parse(challengeData);\n\n // Decode challenge and allowed credentials from base64url to BufferSource\n const publicKey: any = {\n ...requestOptions,\n challenge: base64urlToArrayBuffer(requestOptions.challenge),\n ...(requestOptions.allowCredentials && {\n allowCredentials: requestOptions.allowCredentials.map((cred: any) => ({\n ...cred,\n id: base64urlToArrayBuffer(cred.id),\n })),\n }),\n };\n\n const credential: PublicKeyCredential = (await navigator.credentials.get({\n publicKey,\n })) as PublicKeyCredential;\n\n if (!credential) {\n throw new ThunderIDRuntimeError(\n 'No credential returned from WebAuthn authentication.',\n 'browser-webauthn-no-credential',\n 'browser',\n 'The WebAuthn authentication ceremony completed but did not return a valid credential.',\n );\n }\n\n const response: AuthenticatorAssertionResponse = credential.response as AuthenticatorAssertionResponse;\n\n // Encode response fields back to base64url\n const authenticationResponse: any = {\n id: credential.id,\n rawId: arrayBufferToBase64url(credential.rawId),\n response: {\n authenticatorData: arrayBufferToBase64url(response.authenticatorData),\n clientDataJSON: arrayBufferToBase64url(response.clientDataJSON),\n signature: arrayBufferToBase64url(response.signature),\n ...(response.userHandle && {\n userHandle: arrayBufferToBase64url(response.userHandle),\n }),\n },\n type: credential.type,\n ...(credential.authenticatorAttachment && {\n authenticatorAttachment: credential.authenticatorAttachment,\n }),\n };\n\n return JSON.stringify(authenticationResponse);\n } catch (error) {\n if (error instanceof ThunderIDRuntimeError) {\n throw error;\n }\n\n if (error instanceof Error) {\n throw new ThunderIDRuntimeError(\n 'Passkey authentication failed. Please try again.',\n 'browser-webauthn-authentication-error',\n 'browser',\n `WebAuthn authentication failed with error: ${error.name}: ${error.message}`,\n );\n }\n\n throw new ThunderIDRuntimeError(\n 'Passkey authentication failed due to an unexpected error.',\n 'browser-webauthn-unexpected-error',\n 'browser',\n 'An unexpected error occurred during WebAuthn authentication.',\n );\n }\n};\n"],"mappings":";;;;;;;;;AA0BA,MAAa,4BAA4B,OAAO,kBAA2C;AACzF,KAAI,CAAC,OAAO,UAAU,aAAa,OACjC,OAAM,IAAI,sBACR,8CACA,kCACA,WACA,6FACD;AAGH,KAAI;EACF,MAAMA,kBAAuB,KAAK,MAAM,cAAc;EAGtD,MAAMC,YAAiB;GACrB,GAAG;GACH,WAAW,uBAAuB,gBAAgB,UAAU;GAC5D,MAAM;IACJ,GAAG,gBAAgB;IACnB,IAAI,uBAAuB,gBAAgB,KAAK,GAAG;IACpD;GACD,GAAI,gBAAgB,sBAAsB,EACxC,oBAAoB,gBAAgB,mBAAmB,KAAK,UAAe;IACzE,GAAG;IACH,IAAI,uBAAuB,KAAK,GAAG;IACpC,EAAE,EACJ;GACF;EAED,MAAMC,aAAmC,MAAM,UAAU,YAAY,OAAO,EAC1E,WACD,CAAC;AAEF,MAAI,CAAC,WACH,OAAM,IAAI,sBACR,sDACA,kCACA,WACA,sFACD;EAGH,MAAMC,WAA6C,WAAW;EAG9D,MAAMC,uBAA4B;GAChC,IAAI,WAAW;GACf,OAAO,uBAAuB,WAAW,MAAM;GAC/C,UAAU;IACR,mBAAmB,uBAAuB,SAAS,kBAAkB;IACrE,gBAAgB,uBAAuB,SAAS,eAAe;IAC/D,GAAI,SAAS,iBAAiB,EAC5B,YAAY,SAAS,eAAe,EACrC;IACF;GACD,MAAM,WAAW;GACjB,GAAI,WAAW,2BAA2B,EACxC,yBAAyB,WAAW,yBACrC;GACF;AAED,SAAO,KAAK,UAAU,qBAAqB;UACpC,OAAO;AACd,MAAI,iBAAiB,sBACnB,OAAM;AAGR,MAAI,iBAAiB,MAEnB,OAAM,IAAI,sBACR,kDACA,uCACA,WACA,4CAA4C,MAAM,KAAK,IAAI,MAAM,UAClE;AAGH,QAAM,IAAI,sBACR,2DACA,qCACA,WACA,6DACD;;;;;;;;;AAUL,MAAa,8BAA8B,OAAO,kBAA2C;AAC3F,KAAI,CAAC,OAAO,UAAU,aAAa,IACjC,OAAM,IAAI,sBACR,8CACA,kCACA,WACA,+FACD;AAGH,KAAI;EACF,MAAMC,iBAAsB,KAAK,MAAM,cAAc;EAGrD,MAAMJ,YAAiB;GACrB,GAAG;GACH,WAAW,uBAAuB,eAAe,UAAU;GAC3D,GAAI,eAAe,oBAAoB,EACrC,kBAAkB,eAAe,iBAAiB,KAAK,UAAe;IACpE,GAAG;IACH,IAAI,uBAAuB,KAAK,GAAG;IACpC,EAAE,EACJ;GACF;EAED,MAAMC,aAAmC,MAAM,UAAU,YAAY,IAAI,EACvE,WACD,CAAC;AAEF,MAAI,CAAC,WACH,OAAM,IAAI,sBACR,wDACA,kCACA,WACA,wFACD;EAGH,MAAMI,WAA2C,WAAW;EAG5D,MAAMC,yBAA8B;GAClC,IAAI,WAAW;GACf,OAAO,uBAAuB,WAAW,MAAM;GAC/C,UAAU;IACR,mBAAmB,uBAAuB,SAAS,kBAAkB;IACrE,gBAAgB,uBAAuB,SAAS,eAAe;IAC/D,WAAW,uBAAuB,SAAS,UAAU;IACrD,GAAI,SAAS,cAAc,EACzB,YAAY,uBAAuB,SAAS,WAAW,EACxD;IACF;GACD,MAAM,WAAW;GACjB,GAAI,WAAW,2BAA2B,EACxC,yBAAyB,WAAW,yBACrC;GACF;AAED,SAAO,KAAK,UAAU,uBAAuB;UACtC,OAAO;AACd,MAAI,iBAAiB,sBACnB,OAAM;AAGR,MAAI,iBAAiB,MACnB,OAAM,IAAI,sBACR,oDACA,yCACA,WACA,8CAA8C,MAAM,KAAK,IAAI,MAAM,UACpE;AAGH,QAAM,IAAI,sBACR,6DACA,qCACA,WACA,+DACD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thunderid/react",
3
- "version": "0.10.1",
3
+ "version": "0.11.1",
4
4
  "description": "React SDK for ThunderID",
5
5
  "keywords": [
6
6
  "thunderid",
@@ -62,7 +62,7 @@
62
62
  "@floating-ui/react": "0.27.12",
63
63
  "dompurify": "3.4.11",
64
64
  "tslib": "2.8.1",
65
- "@thunderid/browser": "^0.10.1"
65
+ "@thunderid/browser": "^0.11.1"
66
66
  },
67
67
  "publishConfig": {
68
68
  "access": "public"