@asgardeo/react 0.8.0 → 0.9.0

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/index.js CHANGED
@@ -7683,11 +7683,159 @@ import {
7683
7683
  // src/components/presentation/auth/SignIn/v2/SignIn.tsx
7684
7684
  import { useState as useState16, useEffect as useEffect13, useRef as useRef4 } from "react";
7685
7685
  import {
7686
- AsgardeoRuntimeError as AsgardeoRuntimeError8,
7686
+ AsgardeoRuntimeError as AsgardeoRuntimeError9,
7687
7687
  EmbeddedFlowType,
7688
7688
  EmbeddedSignInFlowStatusV2,
7689
7689
  EmbeddedSignInFlowTypeV2
7690
7690
  } from "@asgardeo/browser";
7691
+
7692
+ // src/utils/v2/passkey.ts
7693
+ import { AsgardeoRuntimeError as AsgardeoRuntimeError8, arrayBufferToBase64url, base64urlToArrayBuffer } from "@asgardeo/browser";
7694
+ var handlePasskeyRegistration = async (challengeData) => {
7695
+ if (!window.navigator.credentials || !window.navigator.credentials.create) {
7696
+ throw new AsgardeoRuntimeError8(
7697
+ "WebAuthn is not supported in this browser.",
7698
+ "browser-webauthn-not-supported",
7699
+ "browser",
7700
+ "WebAuthn/Passkey registration requires a browser that supports the Web Authentication API."
7701
+ );
7702
+ }
7703
+ try {
7704
+ const creationOptions = JSON.parse(challengeData);
7705
+ const publicKey = {
7706
+ ...creationOptions,
7707
+ challenge: base64urlToArrayBuffer(creationOptions.challenge),
7708
+ user: {
7709
+ ...creationOptions.user,
7710
+ id: base64urlToArrayBuffer(creationOptions.user.id)
7711
+ },
7712
+ ...creationOptions.excludeCredentials && {
7713
+ excludeCredentials: creationOptions.excludeCredentials.map((cred) => ({
7714
+ ...cred,
7715
+ id: base64urlToArrayBuffer(cred.id)
7716
+ }))
7717
+ }
7718
+ };
7719
+ const credential = await navigator.credentials.create({
7720
+ publicKey
7721
+ });
7722
+ if (!credential) {
7723
+ throw new AsgardeoRuntimeError8(
7724
+ "No credential returned from WebAuthn registration.",
7725
+ "browser-webauthn-no-credential",
7726
+ "browser",
7727
+ "The WebAuthn registration ceremony completed but did not return a valid credential."
7728
+ );
7729
+ }
7730
+ const response = credential.response;
7731
+ const registrationResponse = {
7732
+ id: credential.id,
7733
+ rawId: arrayBufferToBase64url(credential.rawId),
7734
+ type: credential.type,
7735
+ response: {
7736
+ attestationObject: arrayBufferToBase64url(response.attestationObject),
7737
+ clientDataJSON: arrayBufferToBase64url(response.clientDataJSON),
7738
+ ...response.getTransports && {
7739
+ transports: response.getTransports()
7740
+ }
7741
+ },
7742
+ ...credential.authenticatorAttachment && {
7743
+ authenticatorAttachment: credential.authenticatorAttachment
7744
+ }
7745
+ };
7746
+ return JSON.stringify(registrationResponse);
7747
+ } catch (error) {
7748
+ if (error instanceof AsgardeoRuntimeError8) {
7749
+ throw error;
7750
+ }
7751
+ if (error instanceof Error) {
7752
+ throw new AsgardeoRuntimeError8(
7753
+ `Passkey registration failed: ${error.message}`,
7754
+ "browser-webauthn-registration-error",
7755
+ "browser",
7756
+ `WebAuthn registration failed with error: ${error.name}`
7757
+ );
7758
+ }
7759
+ throw new AsgardeoRuntimeError8(
7760
+ "Passkey registration failed due to an unexpected error.",
7761
+ "browser-webauthn-unexpected-error",
7762
+ "browser",
7763
+ "An unexpected error occurred during WebAuthn registration."
7764
+ );
7765
+ }
7766
+ };
7767
+ var handlePasskeyAuthentication = async (challengeData) => {
7768
+ if (!window.navigator.credentials || !window.navigator.credentials.get) {
7769
+ throw new AsgardeoRuntimeError8(
7770
+ "WebAuthn is not supported in this browser.",
7771
+ "browser-webauthn-not-supported",
7772
+ "browser",
7773
+ "WebAuthn/Passkey authentication requires a browser that supports the Web Authentication API."
7774
+ );
7775
+ }
7776
+ try {
7777
+ const requestOptions = JSON.parse(challengeData);
7778
+ const publicKey = {
7779
+ ...requestOptions,
7780
+ challenge: base64urlToArrayBuffer(requestOptions.challenge),
7781
+ ...requestOptions.allowCredentials && {
7782
+ allowCredentials: requestOptions.allowCredentials.map((cred) => ({
7783
+ ...cred,
7784
+ id: base64urlToArrayBuffer(cred.id)
7785
+ }))
7786
+ }
7787
+ };
7788
+ const credential = await navigator.credentials.get({
7789
+ publicKey
7790
+ });
7791
+ if (!credential) {
7792
+ throw new AsgardeoRuntimeError8(
7793
+ "No credential returned from WebAuthn authentication.",
7794
+ "browser-webauthn-no-credential",
7795
+ "browser",
7796
+ "The WebAuthn authentication ceremony completed but did not return a valid credential."
7797
+ );
7798
+ }
7799
+ const response = credential.response;
7800
+ const authenticationResponse = {
7801
+ id: credential.id,
7802
+ rawId: arrayBufferToBase64url(credential.rawId),
7803
+ type: credential.type,
7804
+ response: {
7805
+ authenticatorData: arrayBufferToBase64url(response.authenticatorData),
7806
+ clientDataJSON: arrayBufferToBase64url(response.clientDataJSON),
7807
+ signature: arrayBufferToBase64url(response.signature),
7808
+ ...response.userHandle && {
7809
+ userHandle: arrayBufferToBase64url(response.userHandle)
7810
+ }
7811
+ },
7812
+ ...credential.authenticatorAttachment && {
7813
+ authenticatorAttachment: credential.authenticatorAttachment
7814
+ }
7815
+ };
7816
+ return JSON.stringify(authenticationResponse);
7817
+ } catch (error) {
7818
+ if (error instanceof AsgardeoRuntimeError8) {
7819
+ throw error;
7820
+ }
7821
+ if (error instanceof Error) {
7822
+ throw new AsgardeoRuntimeError8(
7823
+ `Passkey authentication failed: ${error.message}`,
7824
+ "browser-webauthn-authentication-error",
7825
+ "browser",
7826
+ `WebAuthn authentication failed with error: ${error.name}`
7827
+ );
7828
+ }
7829
+ throw new AsgardeoRuntimeError8(
7830
+ "Passkey authentication failed due to an unexpected error.",
7831
+ "browser-webauthn-unexpected-error",
7832
+ "browser",
7833
+ "An unexpected error occurred during WebAuthn authentication."
7834
+ );
7835
+ }
7836
+ };
7837
+
7838
+ // src/components/presentation/auth/SignIn/v2/SignIn.tsx
7691
7839
  import { Fragment as Fragment12, jsx as jsx58 } from "react/jsx-runtime";
7692
7840
  var SignIn = ({ className, size = "medium", onSuccess, onError, variant, children }) => {
7693
7841
  const { applicationId, afterSignInUrl, signIn, isInitialized, isLoading } = useAsgardeo_default();
@@ -7697,8 +7845,17 @@ var SignIn = ({ className, size = "medium", onSuccess, onError, variant, childre
7697
7845
  const [isFlowInitialized, setIsFlowInitialized] = useState16(false);
7698
7846
  const [flowError, setFlowError] = useState16(null);
7699
7847
  const [isSubmitting, setIsSubmitting] = useState16(false);
7848
+ const [passkeyState, setPasskeyState] = useState16({
7849
+ isActive: false,
7850
+ challenge: null,
7851
+ creationOptions: null,
7852
+ flowId: null,
7853
+ actionId: null,
7854
+ error: null
7855
+ });
7700
7856
  const initializationAttemptedRef = useRef4(false);
7701
7857
  const oauthCodeProcessedRef = useRef4(false);
7858
+ const passkeyProcessedRef = useRef4(false);
7702
7859
  const setFlowId = (flowId) => {
7703
7860
  setCurrentFlowId(flowId);
7704
7861
  if (flowId) {
@@ -7757,7 +7914,7 @@ var SignIn = ({ className, size = "medium", onSuccess, onError, variant, childre
7757
7914
  const handleOAuthError = (error, errorDescription) => {
7758
7915
  clearFlowState();
7759
7916
  const errorMessage = errorDescription || `OAuth error: ${error}`;
7760
- const err = new AsgardeoRuntimeError8(errorMessage, "SIGN_IN_ERROR", "react");
7917
+ const err = new AsgardeoRuntimeError9(errorMessage, "SIGN_IN_ERROR", "react");
7761
7918
  setError(err);
7762
7919
  cleanupOAuthUrlParams(true);
7763
7920
  };
@@ -7804,7 +7961,7 @@ var SignIn = ({ className, size = "medium", onSuccess, onError, variant, childre
7804
7961
  handleAuthId(urlParams.authId);
7805
7962
  const effectiveApplicationId = applicationId || urlParams.applicationId;
7806
7963
  if (!urlParams.flowId && !effectiveApplicationId) {
7807
- const error = new AsgardeoRuntimeError8(
7964
+ const error = new AsgardeoRuntimeError9(
7808
7965
  "Either flowId or applicationId is required for authentication",
7809
7966
  "SIGN_IN_ERROR",
7810
7967
  "react"
@@ -7861,6 +8018,22 @@ var SignIn = ({ className, size = "medium", onSuccess, onError, variant, childre
7861
8018
  if (handleRedirection(response)) {
7862
8019
  return;
7863
8020
  }
8021
+ if (response.data?.additionalData?.["passkeyChallenge"] || response.data?.additionalData?.["passkeyCreationOptions"]) {
8022
+ const passkeyChallenge = response.data.additionalData["passkeyChallenge"];
8023
+ const passkeyCreationOptions = response.data.additionalData["passkeyCreationOptions"];
8024
+ const effectiveFlowIdForPasskey = response.flowId || effectiveFlowId;
8025
+ passkeyProcessedRef.current = false;
8026
+ setPasskeyState({
8027
+ isActive: true,
8028
+ challenge: passkeyChallenge,
8029
+ creationOptions: passkeyCreationOptions,
8030
+ flowId: effectiveFlowIdForPasskey,
8031
+ actionId: "submit",
8032
+ error: null
8033
+ });
8034
+ setIsSubmitting(false);
8035
+ return;
8036
+ }
7864
8037
  const { flowId, components: components2, ...rest } = normalizeFlowResponse(response, t, {
7865
8038
  resolveTranslations: !children
7866
8039
  });
@@ -7940,6 +8113,50 @@ var SignIn = ({ className, size = "medium", onSuccess, onError, variant, childre
7940
8113
  cleanupOAuthUrlParams(true);
7941
8114
  });
7942
8115
  }, [isFlowInitialized, currentFlowId, isInitialized, isLoading, isSubmitting, signIn]);
8116
+ useEffect13(() => {
8117
+ if (!passkeyState.isActive || !passkeyState.challenge && !passkeyState.creationOptions || !passkeyState.flowId) {
8118
+ return;
8119
+ }
8120
+ if (passkeyProcessedRef.current) {
8121
+ return;
8122
+ }
8123
+ passkeyProcessedRef.current = true;
8124
+ const performPasskeyProcess = async () => {
8125
+ let inputs;
8126
+ if (passkeyState.challenge) {
8127
+ const passkeyResponse = await handlePasskeyAuthentication(passkeyState.challenge);
8128
+ const passkeyResponseObj = JSON.parse(passkeyResponse);
8129
+ inputs = {
8130
+ credentialId: passkeyResponseObj.id,
8131
+ authenticatorData: passkeyResponseObj.response.authenticatorData,
8132
+ clientDataJSON: passkeyResponseObj.response.clientDataJSON,
8133
+ signature: passkeyResponseObj.response.signature,
8134
+ userHandle: passkeyResponseObj.response.userHandle
8135
+ };
8136
+ } else if (passkeyState.creationOptions) {
8137
+ const passkeyResponse = await handlePasskeyRegistration(passkeyState.creationOptions);
8138
+ const passkeyResponseObj = JSON.parse(passkeyResponse);
8139
+ inputs = {
8140
+ credentialId: passkeyResponseObj.id,
8141
+ clientDataJSON: passkeyResponseObj.response.clientDataJSON,
8142
+ attestationObject: passkeyResponseObj.response.attestationObject
8143
+ };
8144
+ } else {
8145
+ throw new Error("No passkey challenge or creation options available");
8146
+ }
8147
+ await handleSubmit({
8148
+ flowId: passkeyState.flowId,
8149
+ inputs
8150
+ });
8151
+ };
8152
+ performPasskeyProcess().then(() => {
8153
+ setPasskeyState({ isActive: false, challenge: null, creationOptions: null, flowId: null, actionId: null, error: null });
8154
+ }).catch((error) => {
8155
+ setPasskeyState((prev) => ({ ...prev, isActive: false, error }));
8156
+ setFlowError(error);
8157
+ onError?.(error);
8158
+ });
8159
+ }, [passkeyState.isActive, passkeyState.challenge, passkeyState.creationOptions, passkeyState.flowId]);
7943
8160
  if (children) {
7944
8161
  const renderProps = {
7945
8162
  initialize: initializeFlow,
@@ -9216,7 +9433,15 @@ var BaseSignUpContent2 = ({
9216
9433
  const [isFlowInitialized, setIsFlowInitialized] = useState18(false);
9217
9434
  const [currentFlow, setCurrentFlow] = useState18(null);
9218
9435
  const [apiError, setApiError] = useState18(null);
9436
+ const [passkeyState, setPasskeyState] = useState18({
9437
+ isActive: false,
9438
+ creationOptions: null,
9439
+ flowId: null,
9440
+ actionId: null,
9441
+ error: null
9442
+ });
9219
9443
  const initializationAttemptedRef = useRef6(false);
9444
+ const passkeyProcessedRef = useRef6(false);
9220
9445
  const normalizeFlowResponseLocal = useCallback12(
9221
9446
  (response) => {
9222
9447
  if (response?.data?.components && Array.isArray(response.data.components)) {
@@ -9356,6 +9581,20 @@ var BaseSignUpContent2 = ({
9356
9581
  if (handleRedirectionIfNeeded(response, component)) {
9357
9582
  return;
9358
9583
  }
9584
+ if (response.data?.additionalData?.["passkeyCreationOptions"]) {
9585
+ const passkeyCreationOptions = response.data.additionalData["passkeyCreationOptions"];
9586
+ const effectiveFlowIdForPasskey = response.flowId || currentFlow?.flowId;
9587
+ passkeyProcessedRef.current = false;
9588
+ setPasskeyState({
9589
+ isActive: true,
9590
+ creationOptions: passkeyCreationOptions,
9591
+ flowId: effectiveFlowIdForPasskey,
9592
+ actionId: component.id || "submit",
9593
+ error: null
9594
+ });
9595
+ setIsLoading(false);
9596
+ return;
9597
+ }
9359
9598
  setCurrentFlow(response);
9360
9599
  setupFormFields(response);
9361
9600
  }
@@ -9366,6 +9605,48 @@ var BaseSignUpContent2 = ({
9366
9605
  setIsLoading(false);
9367
9606
  }
9368
9607
  };
9608
+ useEffect15(() => {
9609
+ if (!passkeyState.isActive || !passkeyState.creationOptions || !passkeyState.flowId) {
9610
+ return;
9611
+ }
9612
+ if (passkeyProcessedRef.current) {
9613
+ return;
9614
+ }
9615
+ passkeyProcessedRef.current = true;
9616
+ const performPasskeyRegistration = async () => {
9617
+ const passkeyResponse = await handlePasskeyRegistration(passkeyState.creationOptions);
9618
+ const passkeyResponseObj = JSON.parse(passkeyResponse);
9619
+ const inputs = {
9620
+ credentialId: passkeyResponseObj.id,
9621
+ clientDataJSON: passkeyResponseObj.response.clientDataJSON,
9622
+ attestationObject: passkeyResponseObj.response.attestationObject
9623
+ };
9624
+ const payload = {
9625
+ flowId: passkeyState.flowId,
9626
+ flowType: currentFlow?.flowType || "REGISTRATION",
9627
+ actionId: passkeyState.actionId || "submit",
9628
+ inputs
9629
+ };
9630
+ const nextResponse = await onSubmit(payload);
9631
+ const processedResponse = normalizeFlowResponseLocal(nextResponse);
9632
+ onFlowChange?.(processedResponse);
9633
+ if (processedResponse.flowStatus === EmbeddedFlowStatus2.Complete) {
9634
+ onComplete?.(processedResponse);
9635
+ return;
9636
+ } else {
9637
+ setCurrentFlow(processedResponse);
9638
+ setupFormFields(processedResponse);
9639
+ return;
9640
+ }
9641
+ };
9642
+ performPasskeyRegistration().then(() => {
9643
+ setPasskeyState({ isActive: false, creationOptions: null, flowId: null, actionId: null, error: null });
9644
+ }).catch((error) => {
9645
+ setPasskeyState((prev) => ({ ...prev, isActive: false, error }));
9646
+ handleError(error);
9647
+ onError?.(error);
9648
+ });
9649
+ }, [passkeyState.isActive, passkeyState.creationOptions, passkeyState.flowId]);
9369
9650
  const handleRedirectionIfNeeded = (response, component) => {
9370
9651
  if (response?.type === EmbeddedFlowResponseType2.Redirection && response?.data?.redirectURL) {
9371
9652
  const redirectUrl = response.data.redirectURL;
@@ -15112,7 +15393,7 @@ var OrganizationSwitcher_default = OrganizationSwitcher;
15112
15393
 
15113
15394
  // src/index.ts
15114
15395
  import {
15115
- AsgardeoRuntimeError as AsgardeoRuntimeError9,
15396
+ AsgardeoRuntimeError as AsgardeoRuntimeError10,
15116
15397
  http,
15117
15398
  getActiveTheme as getActiveTheme2,
15118
15399
  navigate as navigate4,
@@ -15130,7 +15411,7 @@ export {
15130
15411
  AlertTitle,
15131
15412
  AsgardeoContext_default as AsgardeoContext,
15132
15413
  AsgardeoProvider_default as AsgardeoProvider,
15133
- AsgardeoRuntimeError9 as AsgardeoRuntimeError,
15414
+ AsgardeoRuntimeError10 as AsgardeoRuntimeError,
15134
15415
  BaseAcceptInvite_default as BaseAcceptInvite,
15135
15416
  BaseCreateOrganization,
15136
15417
  BaseInviteUser_default as BaseInviteUser,