@asgardeo/react 0.8.0 → 0.9.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.
package/dist/index.js CHANGED
@@ -789,8 +789,15 @@ var AsgardeoReactClient = class extends AsgardeoBrowserClient {
789
789
  const firstArg = args[0];
790
790
  const baseUrl = config?.baseUrl;
791
791
  if (config.platform === Platform.AsgardeoV2) {
792
+ const authIdFromUrl = new URL(window.location.href).searchParams.get("authId");
793
+ const authIdFromStorage = sessionStorage.getItem("asgardeo_auth_id");
794
+ const authId = authIdFromUrl || authIdFromStorage;
795
+ if (authIdFromUrl && !authIdFromStorage) {
796
+ sessionStorage.setItem("asgardeo_auth_id", authIdFromUrl);
797
+ }
792
798
  return executeEmbeddedSignUpFlowV2({
793
799
  baseUrl,
800
+ authId,
794
801
  payload: typeof firstArg === "object" && "flowType" in firstArg ? { ...firstArg, verbose: true } : firstArg
795
802
  });
796
803
  }
@@ -7683,11 +7690,159 @@ import {
7683
7690
  // src/components/presentation/auth/SignIn/v2/SignIn.tsx
7684
7691
  import { useState as useState16, useEffect as useEffect13, useRef as useRef4 } from "react";
7685
7692
  import {
7686
- AsgardeoRuntimeError as AsgardeoRuntimeError8,
7693
+ AsgardeoRuntimeError as AsgardeoRuntimeError9,
7687
7694
  EmbeddedFlowType,
7688
7695
  EmbeddedSignInFlowStatusV2,
7689
7696
  EmbeddedSignInFlowTypeV2
7690
7697
  } from "@asgardeo/browser";
7698
+
7699
+ // src/utils/v2/passkey.ts
7700
+ import { AsgardeoRuntimeError as AsgardeoRuntimeError8, arrayBufferToBase64url, base64urlToArrayBuffer } from "@asgardeo/browser";
7701
+ var handlePasskeyRegistration = async (challengeData) => {
7702
+ if (!window.navigator.credentials || !window.navigator.credentials.create) {
7703
+ throw new AsgardeoRuntimeError8(
7704
+ "WebAuthn is not supported in this browser.",
7705
+ "browser-webauthn-not-supported",
7706
+ "browser",
7707
+ "WebAuthn/Passkey registration requires a browser that supports the Web Authentication API."
7708
+ );
7709
+ }
7710
+ try {
7711
+ const creationOptions = JSON.parse(challengeData);
7712
+ const publicKey = {
7713
+ ...creationOptions,
7714
+ challenge: base64urlToArrayBuffer(creationOptions.challenge),
7715
+ user: {
7716
+ ...creationOptions.user,
7717
+ id: base64urlToArrayBuffer(creationOptions.user.id)
7718
+ },
7719
+ ...creationOptions.excludeCredentials && {
7720
+ excludeCredentials: creationOptions.excludeCredentials.map((cred) => ({
7721
+ ...cred,
7722
+ id: base64urlToArrayBuffer(cred.id)
7723
+ }))
7724
+ }
7725
+ };
7726
+ const credential = await navigator.credentials.create({
7727
+ publicKey
7728
+ });
7729
+ if (!credential) {
7730
+ throw new AsgardeoRuntimeError8(
7731
+ "No credential returned from WebAuthn registration.",
7732
+ "browser-webauthn-no-credential",
7733
+ "browser",
7734
+ "The WebAuthn registration ceremony completed but did not return a valid credential."
7735
+ );
7736
+ }
7737
+ const response = credential.response;
7738
+ const registrationResponse = {
7739
+ id: credential.id,
7740
+ rawId: arrayBufferToBase64url(credential.rawId),
7741
+ type: credential.type,
7742
+ response: {
7743
+ attestationObject: arrayBufferToBase64url(response.attestationObject),
7744
+ clientDataJSON: arrayBufferToBase64url(response.clientDataJSON),
7745
+ ...response.getTransports && {
7746
+ transports: response.getTransports()
7747
+ }
7748
+ },
7749
+ ...credential.authenticatorAttachment && {
7750
+ authenticatorAttachment: credential.authenticatorAttachment
7751
+ }
7752
+ };
7753
+ return JSON.stringify(registrationResponse);
7754
+ } catch (error) {
7755
+ if (error instanceof AsgardeoRuntimeError8) {
7756
+ throw error;
7757
+ }
7758
+ if (error instanceof Error) {
7759
+ throw new AsgardeoRuntimeError8(
7760
+ `Passkey registration failed: ${error.message}`,
7761
+ "browser-webauthn-registration-error",
7762
+ "browser",
7763
+ `WebAuthn registration failed with error: ${error.name}`
7764
+ );
7765
+ }
7766
+ throw new AsgardeoRuntimeError8(
7767
+ "Passkey registration failed due to an unexpected error.",
7768
+ "browser-webauthn-unexpected-error",
7769
+ "browser",
7770
+ "An unexpected error occurred during WebAuthn registration."
7771
+ );
7772
+ }
7773
+ };
7774
+ var handlePasskeyAuthentication = async (challengeData) => {
7775
+ if (!window.navigator.credentials || !window.navigator.credentials.get) {
7776
+ throw new AsgardeoRuntimeError8(
7777
+ "WebAuthn is not supported in this browser.",
7778
+ "browser-webauthn-not-supported",
7779
+ "browser",
7780
+ "WebAuthn/Passkey authentication requires a browser that supports the Web Authentication API."
7781
+ );
7782
+ }
7783
+ try {
7784
+ const requestOptions = JSON.parse(challengeData);
7785
+ const publicKey = {
7786
+ ...requestOptions,
7787
+ challenge: base64urlToArrayBuffer(requestOptions.challenge),
7788
+ ...requestOptions.allowCredentials && {
7789
+ allowCredentials: requestOptions.allowCredentials.map((cred) => ({
7790
+ ...cred,
7791
+ id: base64urlToArrayBuffer(cred.id)
7792
+ }))
7793
+ }
7794
+ };
7795
+ const credential = await navigator.credentials.get({
7796
+ publicKey
7797
+ });
7798
+ if (!credential) {
7799
+ throw new AsgardeoRuntimeError8(
7800
+ "No credential returned from WebAuthn authentication.",
7801
+ "browser-webauthn-no-credential",
7802
+ "browser",
7803
+ "The WebAuthn authentication ceremony completed but did not return a valid credential."
7804
+ );
7805
+ }
7806
+ const response = credential.response;
7807
+ const authenticationResponse = {
7808
+ id: credential.id,
7809
+ rawId: arrayBufferToBase64url(credential.rawId),
7810
+ type: credential.type,
7811
+ response: {
7812
+ authenticatorData: arrayBufferToBase64url(response.authenticatorData),
7813
+ clientDataJSON: arrayBufferToBase64url(response.clientDataJSON),
7814
+ signature: arrayBufferToBase64url(response.signature),
7815
+ ...response.userHandle && {
7816
+ userHandle: arrayBufferToBase64url(response.userHandle)
7817
+ }
7818
+ },
7819
+ ...credential.authenticatorAttachment && {
7820
+ authenticatorAttachment: credential.authenticatorAttachment
7821
+ }
7822
+ };
7823
+ return JSON.stringify(authenticationResponse);
7824
+ } catch (error) {
7825
+ if (error instanceof AsgardeoRuntimeError8) {
7826
+ throw error;
7827
+ }
7828
+ if (error instanceof Error) {
7829
+ throw new AsgardeoRuntimeError8(
7830
+ `Passkey authentication failed: ${error.message}`,
7831
+ "browser-webauthn-authentication-error",
7832
+ "browser",
7833
+ `WebAuthn authentication failed with error: ${error.name}`
7834
+ );
7835
+ }
7836
+ throw new AsgardeoRuntimeError8(
7837
+ "Passkey authentication failed due to an unexpected error.",
7838
+ "browser-webauthn-unexpected-error",
7839
+ "browser",
7840
+ "An unexpected error occurred during WebAuthn authentication."
7841
+ );
7842
+ }
7843
+ };
7844
+
7845
+ // src/components/presentation/auth/SignIn/v2/SignIn.tsx
7691
7846
  import { Fragment as Fragment12, jsx as jsx58 } from "react/jsx-runtime";
7692
7847
  var SignIn = ({ className, size = "medium", onSuccess, onError, variant, children }) => {
7693
7848
  const { applicationId, afterSignInUrl, signIn, isInitialized, isLoading } = useAsgardeo_default();
@@ -7697,8 +7852,17 @@ var SignIn = ({ className, size = "medium", onSuccess, onError, variant, childre
7697
7852
  const [isFlowInitialized, setIsFlowInitialized] = useState16(false);
7698
7853
  const [flowError, setFlowError] = useState16(null);
7699
7854
  const [isSubmitting, setIsSubmitting] = useState16(false);
7855
+ const [passkeyState, setPasskeyState] = useState16({
7856
+ isActive: false,
7857
+ challenge: null,
7858
+ creationOptions: null,
7859
+ flowId: null,
7860
+ actionId: null,
7861
+ error: null
7862
+ });
7700
7863
  const initializationAttemptedRef = useRef4(false);
7701
7864
  const oauthCodeProcessedRef = useRef4(false);
7865
+ const passkeyProcessedRef = useRef4(false);
7702
7866
  const setFlowId = (flowId) => {
7703
7867
  setCurrentFlowId(flowId);
7704
7868
  if (flowId) {
@@ -7757,7 +7921,7 @@ var SignIn = ({ className, size = "medium", onSuccess, onError, variant, childre
7757
7921
  const handleOAuthError = (error, errorDescription) => {
7758
7922
  clearFlowState();
7759
7923
  const errorMessage = errorDescription || `OAuth error: ${error}`;
7760
- const err = new AsgardeoRuntimeError8(errorMessage, "SIGN_IN_ERROR", "react");
7924
+ const err = new AsgardeoRuntimeError9(errorMessage, "SIGN_IN_ERROR", "react");
7761
7925
  setError(err);
7762
7926
  cleanupOAuthUrlParams(true);
7763
7927
  };
@@ -7804,7 +7968,7 @@ var SignIn = ({ className, size = "medium", onSuccess, onError, variant, childre
7804
7968
  handleAuthId(urlParams.authId);
7805
7969
  const effectiveApplicationId = applicationId || urlParams.applicationId;
7806
7970
  if (!urlParams.flowId && !effectiveApplicationId) {
7807
- const error = new AsgardeoRuntimeError8(
7971
+ const error = new AsgardeoRuntimeError9(
7808
7972
  "Either flowId or applicationId is required for authentication",
7809
7973
  "SIGN_IN_ERROR",
7810
7974
  "react"
@@ -7861,6 +8025,22 @@ var SignIn = ({ className, size = "medium", onSuccess, onError, variant, childre
7861
8025
  if (handleRedirection(response)) {
7862
8026
  return;
7863
8027
  }
8028
+ if (response.data?.additionalData?.["passkeyChallenge"] || response.data?.additionalData?.["passkeyCreationOptions"]) {
8029
+ const passkeyChallenge = response.data.additionalData["passkeyChallenge"];
8030
+ const passkeyCreationOptions = response.data.additionalData["passkeyCreationOptions"];
8031
+ const effectiveFlowIdForPasskey = response.flowId || effectiveFlowId;
8032
+ passkeyProcessedRef.current = false;
8033
+ setPasskeyState({
8034
+ isActive: true,
8035
+ challenge: passkeyChallenge,
8036
+ creationOptions: passkeyCreationOptions,
8037
+ flowId: effectiveFlowIdForPasskey,
8038
+ actionId: "submit",
8039
+ error: null
8040
+ });
8041
+ setIsSubmitting(false);
8042
+ return;
8043
+ }
7864
8044
  const { flowId, components: components2, ...rest } = normalizeFlowResponse(response, t, {
7865
8045
  resolveTranslations: !children
7866
8046
  });
@@ -7940,6 +8120,50 @@ var SignIn = ({ className, size = "medium", onSuccess, onError, variant, childre
7940
8120
  cleanupOAuthUrlParams(true);
7941
8121
  });
7942
8122
  }, [isFlowInitialized, currentFlowId, isInitialized, isLoading, isSubmitting, signIn]);
8123
+ useEffect13(() => {
8124
+ if (!passkeyState.isActive || !passkeyState.challenge && !passkeyState.creationOptions || !passkeyState.flowId) {
8125
+ return;
8126
+ }
8127
+ if (passkeyProcessedRef.current) {
8128
+ return;
8129
+ }
8130
+ passkeyProcessedRef.current = true;
8131
+ const performPasskeyProcess = async () => {
8132
+ let inputs;
8133
+ if (passkeyState.challenge) {
8134
+ const passkeyResponse = await handlePasskeyAuthentication(passkeyState.challenge);
8135
+ const passkeyResponseObj = JSON.parse(passkeyResponse);
8136
+ inputs = {
8137
+ credentialId: passkeyResponseObj.id,
8138
+ authenticatorData: passkeyResponseObj.response.authenticatorData,
8139
+ clientDataJSON: passkeyResponseObj.response.clientDataJSON,
8140
+ signature: passkeyResponseObj.response.signature,
8141
+ userHandle: passkeyResponseObj.response.userHandle
8142
+ };
8143
+ } else if (passkeyState.creationOptions) {
8144
+ const passkeyResponse = await handlePasskeyRegistration(passkeyState.creationOptions);
8145
+ const passkeyResponseObj = JSON.parse(passkeyResponse);
8146
+ inputs = {
8147
+ credentialId: passkeyResponseObj.id,
8148
+ clientDataJSON: passkeyResponseObj.response.clientDataJSON,
8149
+ attestationObject: passkeyResponseObj.response.attestationObject
8150
+ };
8151
+ } else {
8152
+ throw new Error("No passkey challenge or creation options available");
8153
+ }
8154
+ await handleSubmit({
8155
+ flowId: passkeyState.flowId,
8156
+ inputs
8157
+ });
8158
+ };
8159
+ performPasskeyProcess().then(() => {
8160
+ setPasskeyState({ isActive: false, challenge: null, creationOptions: null, flowId: null, actionId: null, error: null });
8161
+ }).catch((error) => {
8162
+ setPasskeyState((prev) => ({ ...prev, isActive: false, error }));
8163
+ setFlowError(error);
8164
+ onError?.(error);
8165
+ });
8166
+ }, [passkeyState.isActive, passkeyState.challenge, passkeyState.creationOptions, passkeyState.flowId]);
7943
8167
  if (children) {
7944
8168
  const renderProps = {
7945
8169
  initialize: initializeFlow,
@@ -9216,7 +9440,15 @@ var BaseSignUpContent2 = ({
9216
9440
  const [isFlowInitialized, setIsFlowInitialized] = useState18(false);
9217
9441
  const [currentFlow, setCurrentFlow] = useState18(null);
9218
9442
  const [apiError, setApiError] = useState18(null);
9443
+ const [passkeyState, setPasskeyState] = useState18({
9444
+ isActive: false,
9445
+ creationOptions: null,
9446
+ flowId: null,
9447
+ actionId: null,
9448
+ error: null
9449
+ });
9219
9450
  const initializationAttemptedRef = useRef6(false);
9451
+ const passkeyProcessedRef = useRef6(false);
9220
9452
  const normalizeFlowResponseLocal = useCallback12(
9221
9453
  (response) => {
9222
9454
  if (response?.data?.components && Array.isArray(response.data.components)) {
@@ -9356,6 +9588,20 @@ var BaseSignUpContent2 = ({
9356
9588
  if (handleRedirectionIfNeeded(response, component)) {
9357
9589
  return;
9358
9590
  }
9591
+ if (response.data?.additionalData?.["passkeyCreationOptions"]) {
9592
+ const passkeyCreationOptions = response.data.additionalData["passkeyCreationOptions"];
9593
+ const effectiveFlowIdForPasskey = response.flowId || currentFlow?.flowId;
9594
+ passkeyProcessedRef.current = false;
9595
+ setPasskeyState({
9596
+ isActive: true,
9597
+ creationOptions: passkeyCreationOptions,
9598
+ flowId: effectiveFlowIdForPasskey,
9599
+ actionId: component.id || "submit",
9600
+ error: null
9601
+ });
9602
+ setIsLoading(false);
9603
+ return;
9604
+ }
9359
9605
  setCurrentFlow(response);
9360
9606
  setupFormFields(response);
9361
9607
  }
@@ -9366,6 +9612,48 @@ var BaseSignUpContent2 = ({
9366
9612
  setIsLoading(false);
9367
9613
  }
9368
9614
  };
9615
+ useEffect15(() => {
9616
+ if (!passkeyState.isActive || !passkeyState.creationOptions || !passkeyState.flowId) {
9617
+ return;
9618
+ }
9619
+ if (passkeyProcessedRef.current) {
9620
+ return;
9621
+ }
9622
+ passkeyProcessedRef.current = true;
9623
+ const performPasskeyRegistration = async () => {
9624
+ const passkeyResponse = await handlePasskeyRegistration(passkeyState.creationOptions);
9625
+ const passkeyResponseObj = JSON.parse(passkeyResponse);
9626
+ const inputs = {
9627
+ credentialId: passkeyResponseObj.id,
9628
+ clientDataJSON: passkeyResponseObj.response.clientDataJSON,
9629
+ attestationObject: passkeyResponseObj.response.attestationObject
9630
+ };
9631
+ const payload = {
9632
+ flowId: passkeyState.flowId,
9633
+ flowType: currentFlow?.flowType || "REGISTRATION",
9634
+ actionId: passkeyState.actionId || "submit",
9635
+ inputs
9636
+ };
9637
+ const nextResponse = await onSubmit(payload);
9638
+ const processedResponse = normalizeFlowResponseLocal(nextResponse);
9639
+ onFlowChange?.(processedResponse);
9640
+ if (processedResponse.flowStatus === EmbeddedFlowStatus2.Complete) {
9641
+ onComplete?.(processedResponse);
9642
+ return;
9643
+ } else {
9644
+ setCurrentFlow(processedResponse);
9645
+ setupFormFields(processedResponse);
9646
+ return;
9647
+ }
9648
+ };
9649
+ performPasskeyRegistration().then(() => {
9650
+ setPasskeyState({ isActive: false, creationOptions: null, flowId: null, actionId: null, error: null });
9651
+ }).catch((error) => {
9652
+ setPasskeyState((prev) => ({ ...prev, isActive: false, error }));
9653
+ handleError(error);
9654
+ onError?.(error);
9655
+ });
9656
+ }, [passkeyState.isActive, passkeyState.creationOptions, passkeyState.flowId]);
9369
9657
  const handleRedirectionIfNeeded = (response, component) => {
9370
9658
  if (response?.type === EmbeddedFlowResponseType2.Redirection && response?.data?.redirectURL) {
9371
9659
  const redirectUrl = response.data.redirectURL;
@@ -9749,6 +10037,11 @@ var SignUp2 = ({
9749
10037
  const handleOnSubmit = async (payload) => await signUp(payload);
9750
10038
  const handleComplete = (response) => {
9751
10039
  onComplete?.(response);
10040
+ const oauthRedirectUrl = response?.redirectUrl;
10041
+ if (shouldRedirectAfterSignUp && oauthRedirectUrl) {
10042
+ window.location.href = oauthRedirectUrl;
10043
+ return;
10044
+ }
9752
10045
  if (shouldRedirectAfterSignUp && response?.type !== EmbeddedFlowResponseType4.Redirection && afterSignUpUrl) {
9753
10046
  window.location.href = afterSignUpUrl;
9754
10047
  }
@@ -15112,7 +15405,7 @@ var OrganizationSwitcher_default = OrganizationSwitcher;
15112
15405
 
15113
15406
  // src/index.ts
15114
15407
  import {
15115
- AsgardeoRuntimeError as AsgardeoRuntimeError9,
15408
+ AsgardeoRuntimeError as AsgardeoRuntimeError10,
15116
15409
  http,
15117
15410
  getActiveTheme as getActiveTheme2,
15118
15411
  navigate as navigate4,
@@ -15130,7 +15423,7 @@ export {
15130
15423
  AlertTitle,
15131
15424
  AsgardeoContext_default as AsgardeoContext,
15132
15425
  AsgardeoProvider_default as AsgardeoProvider,
15133
- AsgardeoRuntimeError9 as AsgardeoRuntimeError,
15426
+ AsgardeoRuntimeError10 as AsgardeoRuntimeError,
15134
15427
  BaseAcceptInvite_default as BaseAcceptInvite,
15135
15428
  BaseCreateOrganization,
15136
15429
  BaseInviteUser_default as BaseInviteUser,