@ory/elements-react 1.0.0-rc.3 → 1.0.0-rc.4
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/CHANGELOG.md +13 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +199 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +197 -47
- package/dist/index.mjs.map +1 -1
- package/dist/theme/default/index.js +153 -121
- package/dist/theme/default/index.js.map +1 -1
- package/dist/theme/default/index.mjs +62 -32
- package/dist/theme/default/index.mjs.map +1 -1
- package/package.json +6 -6
- package/tsconfig.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## 1.0.0-rc.4 (2025-05-15)
|
|
2
|
+
|
|
3
|
+
### 🩹 Fixes
|
|
4
|
+
|
|
5
|
+
- properly handle missing fields in OIDC registration ([#534](https://github.com/ory/elements/pull/534))
|
|
6
|
+
- incorrect if branching in handle error ([#533](https://github.com/ory/elements/pull/533))
|
|
7
|
+
- re-enable method chooser on mfa method active screens ([#530](https://github.com/ory/elements/pull/530))
|
|
8
|
+
|
|
9
|
+
### ❤️ Thank You
|
|
10
|
+
|
|
11
|
+
- hackerman @aeneasr
|
|
12
|
+
- Jonas Hungershausen
|
|
13
|
+
|
|
1
14
|
## 1.0.0-rc.3 (2025-05-09)
|
|
2
15
|
|
|
3
16
|
### 🩹 Fixes
|
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -322,9 +322,7 @@ function parseStateFromFlow(flow) {
|
|
|
322
322
|
return { current: "method_active", method: "code" };
|
|
323
323
|
} else if (methodWithMessage) {
|
|
324
324
|
return { current: "method_active", method: methodWithMessage.group };
|
|
325
|
-
} else if (flow.flow.active && !["default", "identifier_first"
|
|
326
|
-
flow.flow.active
|
|
327
|
-
)) {
|
|
325
|
+
} else if (flow.flow.active && !["default", "identifier_first"].includes(flow.flow.active)) {
|
|
328
326
|
return { current: "method_active", method: flow.flow.active };
|
|
329
327
|
} else if (isChoosingMethod(flow)) {
|
|
330
328
|
const authMethods = nodesToAuthMethodGroups(flow.flow.ui.nodes);
|
|
@@ -362,14 +360,20 @@ function useFormStateReducer(flow) {
|
|
|
362
360
|
const formStateReducer = (state, action2) => {
|
|
363
361
|
switch (action2.type) {
|
|
364
362
|
case "action_flow_update": {
|
|
365
|
-
if (selectedMethod)
|
|
363
|
+
if (selectedMethod) {
|
|
366
364
|
return { current: "method_active", method: selectedMethod };
|
|
365
|
+
}
|
|
367
366
|
return parseStateFromFlow(action2.flow);
|
|
368
367
|
}
|
|
369
368
|
case "action_select_method": {
|
|
370
369
|
setSelectedMethod(action2.method);
|
|
371
370
|
return { current: "method_active", method: action2.method };
|
|
372
371
|
}
|
|
372
|
+
case "action_clear_active_method": {
|
|
373
|
+
return {
|
|
374
|
+
current: "select_method"
|
|
375
|
+
};
|
|
376
|
+
}
|
|
373
377
|
}
|
|
374
378
|
return state;
|
|
375
379
|
};
|
|
@@ -678,6 +682,134 @@ function replaceWindowFlowId(flow) {
|
|
|
678
682
|
url.searchParams.set("flow", flow);
|
|
679
683
|
window.location.href = url.toString();
|
|
680
684
|
}
|
|
685
|
+
function isGenericErrorResponse(response) {
|
|
686
|
+
return typeof response === "object" && !!response && "error" in response && typeof response.error === "object" && !!response.error && "id" in response.error;
|
|
687
|
+
}
|
|
688
|
+
function isNeedsPrivilegedSessionError(response) {
|
|
689
|
+
return isGenericErrorResponse(response) && response.error.id === "session_refresh_required";
|
|
690
|
+
}
|
|
691
|
+
function isSelfServiceFlowExpiredError(response) {
|
|
692
|
+
return isGenericErrorResponse(response) && response.error.id === "self_service_flow_expired";
|
|
693
|
+
}
|
|
694
|
+
function isBrowserLocationChangeRequired(response) {
|
|
695
|
+
return isGenericErrorResponse(response) && isGenericErrorResponse(response) && response.error.id === "browser_location_change_required";
|
|
696
|
+
}
|
|
697
|
+
function isAddressNotVerified(response) {
|
|
698
|
+
return isGenericErrorResponse(response) && response.error.id === "session_verified_address_required";
|
|
699
|
+
}
|
|
700
|
+
function isCsrfError(response) {
|
|
701
|
+
return isGenericErrorResponse(response) && response.error.id === "security_csrf_violation";
|
|
702
|
+
}
|
|
703
|
+
var isResponseError = (err) => {
|
|
704
|
+
if (err instanceof clientFetch.ResponseError) {
|
|
705
|
+
return true;
|
|
706
|
+
}
|
|
707
|
+
return typeof err === "object" && !!err && "name" in err && err.name === "ResponseError";
|
|
708
|
+
};
|
|
709
|
+
var isFetchError = (err) => {
|
|
710
|
+
return err instanceof clientFetch.FetchError;
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
// src/util/sdk-helpers/urlHelpers.ts
|
|
714
|
+
var verificationUrl = (config) => config.sdk.url + "/self-service/verification/browser";
|
|
715
|
+
var handleFlowError = (opts) => async (err) => {
|
|
716
|
+
var _a;
|
|
717
|
+
if (!isResponseError(err)) {
|
|
718
|
+
if (isFetchError(err)) {
|
|
719
|
+
throw new clientFetch.FetchError(
|
|
720
|
+
err,
|
|
721
|
+
"Unable to call the API endpoint. Ensure that CORS is set up correctly and that you have provided a valid SDK URL to Ory Elements."
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
throw err;
|
|
725
|
+
}
|
|
726
|
+
const contentType = err.response.headers.get("content-type") || "";
|
|
727
|
+
if (contentType.includes("application/json")) {
|
|
728
|
+
const body = await toBody(err.response);
|
|
729
|
+
if (isSelfServiceFlowExpiredError(body)) {
|
|
730
|
+
opts.onRestartFlow(body.use_flow_id);
|
|
731
|
+
return;
|
|
732
|
+
} else if (isAddressNotVerified(body)) {
|
|
733
|
+
for (const continueWith of ((_a = body.error.details) == null ? void 0 : _a.continue_with) || []) {
|
|
734
|
+
if (continueWith.action === "show_verification_ui" && continueWith.flow.url) {
|
|
735
|
+
opts.onRedirect(continueWith.flow.url, true);
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
opts.onRedirect(verificationUrl(opts.config), true);
|
|
740
|
+
return;
|
|
741
|
+
} else if (isBrowserLocationChangeRequired(body) && body.redirect_browser_to) {
|
|
742
|
+
opts.onRedirect(body.redirect_browser_to, true);
|
|
743
|
+
return;
|
|
744
|
+
} else if (isNeedsPrivilegedSessionError(body) && body.redirect_browser_to) {
|
|
745
|
+
opts.onRedirect(body.redirect_browser_to, true);
|
|
746
|
+
return;
|
|
747
|
+
} else if (isCsrfError(body)) {
|
|
748
|
+
opts.onRestartFlow();
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
switch (err.response.status) {
|
|
752
|
+
case 404:
|
|
753
|
+
opts.onRestartFlow();
|
|
754
|
+
return;
|
|
755
|
+
case 410:
|
|
756
|
+
opts.onRestartFlow();
|
|
757
|
+
return;
|
|
758
|
+
case 400:
|
|
759
|
+
return opts.onValidationError(
|
|
760
|
+
await err.response.json()
|
|
761
|
+
);
|
|
762
|
+
case 403:
|
|
763
|
+
opts.onRestartFlow();
|
|
764
|
+
return;
|
|
765
|
+
case 422: {
|
|
766
|
+
throw new clientFetch.ResponseError(
|
|
767
|
+
err.response,
|
|
768
|
+
"The API returned an error code indicating a required redirect, but the SDK is outdated and does not know how to handle the action. Received response: " + await err.response.json()
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
throw new clientFetch.ResponseError(
|
|
773
|
+
err.response,
|
|
774
|
+
"The Ory API endpoint returned a response code the SDK does not know how to handle. Please check the network tab for more information. Received response: " + await err.response.json()
|
|
775
|
+
);
|
|
776
|
+
} else if (
|
|
777
|
+
// Not a JSON response? If it's a text response we will return an error informing the user that the response is not JSON.
|
|
778
|
+
contentType.includes("text/") || contentType.includes("html") || contentType.includes("xml")
|
|
779
|
+
) {
|
|
780
|
+
await logResponseError(err.response, true);
|
|
781
|
+
throw new clientFetch.ResponseError(
|
|
782
|
+
err.response,
|
|
783
|
+
`The Ory API endpoint returned an unexpected HTML or text response. Check your console output for details.`
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
await logResponseError(err.response, false);
|
|
787
|
+
throw new clientFetch.ResponseError(
|
|
788
|
+
err.response,
|
|
789
|
+
"The Ory API endpoint returned unexpected content type `" + contentType + "`. Check your console output for details."
|
|
790
|
+
);
|
|
791
|
+
};
|
|
792
|
+
async function toBody(response) {
|
|
793
|
+
try {
|
|
794
|
+
return await response.clone().json();
|
|
795
|
+
} catch (e) {
|
|
796
|
+
await logResponseError(response, true, [e]);
|
|
797
|
+
throw new clientFetch.ResponseError(
|
|
798
|
+
response,
|
|
799
|
+
"Unable to decode API response using JSON."
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
async function logResponseError(response, printBody, wrap) {
|
|
804
|
+
console.error("Unable to decode API response", {
|
|
805
|
+
response: {
|
|
806
|
+
status: response.status,
|
|
807
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
808
|
+
body: printBody ? await response.clone().text() : void 0
|
|
809
|
+
},
|
|
810
|
+
errors: wrap
|
|
811
|
+
});
|
|
812
|
+
}
|
|
681
813
|
|
|
682
814
|
// src/util/onSubmitLogin.ts
|
|
683
815
|
async function onSubmitLogin({ flow }, config, {
|
|
@@ -699,7 +831,7 @@ async function onSubmitLogin({ flow }, config, {
|
|
|
699
831
|
window.location.href = // eslint-disable-next-line promise/always-return
|
|
700
832
|
(_a2 = flow.return_to) != null ? _a2 : config.sdk.url + "/self-service/login/browser";
|
|
701
833
|
}).catch(
|
|
702
|
-
|
|
834
|
+
handleFlowError({
|
|
703
835
|
onRestartFlow: (useFlowId) => {
|
|
704
836
|
if (useFlowId) {
|
|
705
837
|
replaceWindowFlowId(useFlowId);
|
|
@@ -713,7 +845,8 @@ async function onSubmitLogin({ flow }, config, {
|
|
|
713
845
|
flowType: clientFetch.FlowType.Login
|
|
714
846
|
});
|
|
715
847
|
},
|
|
716
|
-
onRedirect
|
|
848
|
+
onRedirect,
|
|
849
|
+
config
|
|
717
850
|
})
|
|
718
851
|
);
|
|
719
852
|
}
|
|
@@ -738,7 +871,7 @@ async function onSubmitRecovery({ flow }, config, {
|
|
|
738
871
|
flowType: clientFetch.FlowType.Recovery
|
|
739
872
|
});
|
|
740
873
|
}).catch(
|
|
741
|
-
|
|
874
|
+
handleFlowError({
|
|
742
875
|
onRestartFlow: (useFlowId) => {
|
|
743
876
|
if (useFlowId) {
|
|
744
877
|
replaceWindowFlowId(useFlowId);
|
|
@@ -757,7 +890,8 @@ async function onSubmitRecovery({ flow }, config, {
|
|
|
757
890
|
});
|
|
758
891
|
}
|
|
759
892
|
},
|
|
760
|
-
onRedirect
|
|
893
|
+
onRedirect,
|
|
894
|
+
config
|
|
761
895
|
})
|
|
762
896
|
);
|
|
763
897
|
}
|
|
@@ -792,7 +926,7 @@ async function onSubmitRegistration({ flow }, config, {
|
|
|
792
926
|
}
|
|
793
927
|
onRedirect(clientFetch.registrationUrl(config), true);
|
|
794
928
|
}).catch(
|
|
795
|
-
|
|
929
|
+
handleFlowError({
|
|
796
930
|
onRestartFlow: (useFlowId) => {
|
|
797
931
|
if (useFlowId) {
|
|
798
932
|
replaceWindowFlowId(useFlowId);
|
|
@@ -806,7 +940,8 @@ async function onSubmitRegistration({ flow }, config, {
|
|
|
806
940
|
flowType: clientFetch.FlowType.Registration
|
|
807
941
|
});
|
|
808
942
|
},
|
|
809
|
-
onRedirect
|
|
943
|
+
onRedirect,
|
|
944
|
+
config
|
|
810
945
|
})
|
|
811
946
|
);
|
|
812
947
|
}
|
|
@@ -831,7 +966,7 @@ async function onSubmitSettings({ flow }, config, {
|
|
|
831
966
|
flowType: clientFetch.FlowType.Settings
|
|
832
967
|
});
|
|
833
968
|
}).catch(
|
|
834
|
-
|
|
969
|
+
handleFlowError({
|
|
835
970
|
onRestartFlow: (useFlowId) => {
|
|
836
971
|
if (useFlowId) {
|
|
837
972
|
replaceWindowFlowId(useFlowId);
|
|
@@ -845,7 +980,8 @@ async function onSubmitSettings({ flow }, config, {
|
|
|
845
980
|
flowType: clientFetch.FlowType.Settings
|
|
846
981
|
});
|
|
847
982
|
},
|
|
848
|
-
onRedirect
|
|
983
|
+
onRedirect,
|
|
984
|
+
config
|
|
849
985
|
})
|
|
850
986
|
).catch((err) => {
|
|
851
987
|
if (clientFetch.isResponseError(err)) {
|
|
@@ -873,7 +1009,7 @@ async function onSubmitVerification({ flow }, config, {
|
|
|
873
1009
|
flowType: clientFetch.FlowType.Verification
|
|
874
1010
|
})
|
|
875
1011
|
).catch(
|
|
876
|
-
|
|
1012
|
+
handleFlowError({
|
|
877
1013
|
onRestartFlow: (useFlowId) => {
|
|
878
1014
|
if (useFlowId) {
|
|
879
1015
|
replaceWindowFlowId(useFlowId);
|
|
@@ -887,7 +1023,8 @@ async function onSubmitVerification({ flow }, config, {
|
|
|
887
1023
|
flowType: clientFetch.FlowType.Verification
|
|
888
1024
|
});
|
|
889
1025
|
},
|
|
890
|
-
onRedirect
|
|
1026
|
+
onRedirect,
|
|
1027
|
+
config
|
|
891
1028
|
})
|
|
892
1029
|
);
|
|
893
1030
|
}
|
|
@@ -1144,7 +1281,20 @@ var NodeInput = ({
|
|
|
1144
1281
|
case clientFetch.UiNodeInputAttributesTypeEnum.Submit:
|
|
1145
1282
|
case clientFetch.UiNodeInputAttributesTypeEnum.Button:
|
|
1146
1283
|
if (isSocial) {
|
|
1147
|
-
return
|
|
1284
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1285
|
+
Node2.OidcButton,
|
|
1286
|
+
{
|
|
1287
|
+
node,
|
|
1288
|
+
attributes: attrs,
|
|
1289
|
+
onClick: () => {
|
|
1290
|
+
setValue(
|
|
1291
|
+
"provider",
|
|
1292
|
+
node.attributes.value
|
|
1293
|
+
);
|
|
1294
|
+
setValue("method", node.group);
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
);
|
|
1148
1298
|
}
|
|
1149
1299
|
if (isResendNode || isScreenSelectionNode) {
|
|
1150
1300
|
return null;
|
|
@@ -1234,6 +1384,37 @@ var Node = ({ node, onClick }) => {
|
|
|
1234
1384
|
}
|
|
1235
1385
|
return null;
|
|
1236
1386
|
};
|
|
1387
|
+
function OryTwoStepCardStateMethodActive({
|
|
1388
|
+
formState
|
|
1389
|
+
}) {
|
|
1390
|
+
const { Form } = useComponents();
|
|
1391
|
+
const { flow, flowType, dispatchFormState } = useOryFlow();
|
|
1392
|
+
const { ui } = flow;
|
|
1393
|
+
const nodeSorter = useNodeSorter();
|
|
1394
|
+
const sortNodes = (a, b) => nodeSorter(a, b, { flowType });
|
|
1395
|
+
const groupsToShow = useNodeGroupsWithVisibleNodes(ui.nodes);
|
|
1396
|
+
const finalNodes = getFinalNodes(groupsToShow, formState.method);
|
|
1397
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(OryCard, { children: [
|
|
1398
|
+
/* @__PURE__ */ jsxRuntime.jsx(OryCardHeader, {}),
|
|
1399
|
+
/* @__PURE__ */ jsxRuntime.jsxs(OryCardContent, { children: [
|
|
1400
|
+
/* @__PURE__ */ jsxRuntime.jsx(OryCardValidationMessages, {}),
|
|
1401
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1402
|
+
OryForm,
|
|
1403
|
+
{
|
|
1404
|
+
"data-testid": `ory/form/methods/local`,
|
|
1405
|
+
onAfterSubmit: handleAfterFormSubmit(dispatchFormState),
|
|
1406
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(Form.Group, { children: [
|
|
1407
|
+
ui.nodes.filter(
|
|
1408
|
+
(n) => clientFetch.isUiNodeScriptAttributes(n.attributes) || n.group === clientFetch.UiNodeGroupEnum.Default || n.group === clientFetch.UiNodeGroupEnum.Profile
|
|
1409
|
+
).map((node, k) => /* @__PURE__ */ jsxRuntime.jsx(Node, { node }, k)),
|
|
1410
|
+
finalNodes.sort(sortNodes).map((node, k) => /* @__PURE__ */ jsxRuntime.jsx(Node, { node }, k))
|
|
1411
|
+
] })
|
|
1412
|
+
}
|
|
1413
|
+
)
|
|
1414
|
+
] }),
|
|
1415
|
+
/* @__PURE__ */ jsxRuntime.jsx(OryCardFooter, {})
|
|
1416
|
+
] });
|
|
1417
|
+
}
|
|
1237
1418
|
function OryFormOidcButtons() {
|
|
1238
1419
|
const {
|
|
1239
1420
|
flow: { ui }
|
|
@@ -1264,8 +1445,10 @@ function OryFormOidcButtons() {
|
|
|
1264
1445
|
}
|
|
1265
1446
|
function OryFormSocialButtonsForm() {
|
|
1266
1447
|
const {
|
|
1267
|
-
flow: { ui }
|
|
1448
|
+
flow: { ui },
|
|
1449
|
+
formState
|
|
1268
1450
|
} = useOryFlow();
|
|
1451
|
+
console.log(formState);
|
|
1269
1452
|
const filteredNodes = ui.nodes.filter(
|
|
1270
1453
|
(node) => node.group === clientFetch.UiNodeGroupEnum.Saml || node.group === clientFetch.UiNodeGroupEnum.Oidc
|
|
1271
1454
|
);
|
|
@@ -1274,39 +1457,6 @@ function OryFormSocialButtonsForm() {
|
|
|
1274
1457
|
}
|
|
1275
1458
|
return /* @__PURE__ */ jsxRuntime.jsx(OryFormProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(OryForm, { "data-testid": `ory/form/methods/oidc-saml`, children: /* @__PURE__ */ jsxRuntime.jsx(OryFormOidcButtons, {}) }) });
|
|
1276
1459
|
}
|
|
1277
|
-
function OryTwoStepCardStateMethodActive({
|
|
1278
|
-
formState
|
|
1279
|
-
}) {
|
|
1280
|
-
const { Form } = useComponents();
|
|
1281
|
-
const { flow, flowType, dispatchFormState } = useOryFlow();
|
|
1282
|
-
const { ui } = flow;
|
|
1283
|
-
const nodeSorter = useNodeSorter();
|
|
1284
|
-
const sortNodes = (a, b) => nodeSorter(a, b, { flowType });
|
|
1285
|
-
const groupsToShow = useNodeGroupsWithVisibleNodes(ui.nodes);
|
|
1286
|
-
const finalNodes = getFinalNodes(groupsToShow, formState.method);
|
|
1287
|
-
const selectedMethodIsSocial = formState.method === clientFetch.UiNodeGroupEnum.Oidc || formState.method === clientFetch.UiNodeGroupEnum.Saml;
|
|
1288
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(OryCard, { children: [
|
|
1289
|
-
/* @__PURE__ */ jsxRuntime.jsx(OryCardHeader, {}),
|
|
1290
|
-
/* @__PURE__ */ jsxRuntime.jsxs(OryCardContent, { children: [
|
|
1291
|
-
/* @__PURE__ */ jsxRuntime.jsx(OryCardValidationMessages, {}),
|
|
1292
|
-
selectedMethodIsSocial && /* @__PURE__ */ jsxRuntime.jsx(OryFormSocialButtonsForm, {}),
|
|
1293
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1294
|
-
OryForm,
|
|
1295
|
-
{
|
|
1296
|
-
"data-testid": `ory/form/methods/local`,
|
|
1297
|
-
onAfterSubmit: handleAfterFormSubmit(dispatchFormState),
|
|
1298
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(Form.Group, { children: [
|
|
1299
|
-
ui.nodes.filter(
|
|
1300
|
-
(n) => clientFetch.isUiNodeScriptAttributes(n.attributes) || n.group === clientFetch.UiNodeGroupEnum.Default || n.group === clientFetch.UiNodeGroupEnum.Profile
|
|
1301
|
-
).map((node, k) => /* @__PURE__ */ jsxRuntime.jsx(Node, { node }, k)),
|
|
1302
|
-
finalNodes.sort(sortNodes).map((node, k) => /* @__PURE__ */ jsxRuntime.jsx(Node, { node }, k))
|
|
1303
|
-
] })
|
|
1304
|
-
}
|
|
1305
|
-
)
|
|
1306
|
-
] }),
|
|
1307
|
-
/* @__PURE__ */ jsxRuntime.jsx(OryCardFooter, {})
|
|
1308
|
-
] });
|
|
1309
|
-
}
|
|
1310
1460
|
function OryTwoStepCardStateProvideIdentifier() {
|
|
1311
1461
|
const { Form, Card } = useComponents();
|
|
1312
1462
|
const { flowType, flow, dispatchFormState } = useOryFlow();
|