@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/cjs/index.js +465 -184
- package/dist/cjs/index.js.map +4 -4
- package/dist/index.js +286 -5
- package/dist/index.js.map +4 -4
- package/dist/utils/v2/passkey.d.ts +31 -0
- package/package.json +3 -3
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
15414
|
+
AsgardeoRuntimeError10 as AsgardeoRuntimeError,
|
|
15134
15415
|
BaseAcceptInvite_default as BaseAcceptInvite,
|
|
15135
15416
|
BaseCreateOrganization,
|
|
15136
15417
|
BaseInviteUser_default as BaseInviteUser,
|