keycloakify 6.3.5 → 6.4.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.
Files changed (78) hide show
  1. package/README.md +6 -0
  2. package/lib/components/Error.d.ts +2 -1
  3. package/lib/components/Error.js +2 -2
  4. package/lib/components/Error.js.map +1 -1
  5. package/lib/components/IdpReviewUserProfile.d.ts +2 -1
  6. package/lib/components/IdpReviewUserProfile.js +2 -2
  7. package/lib/components/IdpReviewUserProfile.js.map +1 -1
  8. package/lib/components/Info.d.ts +2 -1
  9. package/lib/components/Info.js +2 -2
  10. package/lib/components/Info.js.map +1 -1
  11. package/lib/components/KcApp.d.ts +1 -0
  12. package/lib/components/KcApp.js.map +1 -1
  13. package/lib/components/Login.d.ts +2 -1
  14. package/lib/components/Login.js +2 -2
  15. package/lib/components/Login.js.map +1 -1
  16. package/lib/components/LoginConfigTotp.d.ts +2 -1
  17. package/lib/components/LoginConfigTotp.js +2 -2
  18. package/lib/components/LoginConfigTotp.js.map +1 -1
  19. package/lib/components/LoginIdpLinkConfirm.d.ts +2 -1
  20. package/lib/components/LoginIdpLinkConfirm.js +2 -2
  21. package/lib/components/LoginIdpLinkConfirm.js.map +1 -1
  22. package/lib/components/LoginIdpLinkEmail.d.ts +2 -1
  23. package/lib/components/LoginIdpLinkEmail.js +2 -2
  24. package/lib/components/LoginIdpLinkEmail.js.map +1 -1
  25. package/lib/components/LoginOtp.d.ts +2 -1
  26. package/lib/components/LoginOtp.js +2 -2
  27. package/lib/components/LoginOtp.js.map +1 -1
  28. package/lib/components/LoginPageExpired.d.ts +2 -1
  29. package/lib/components/LoginPageExpired.js +2 -2
  30. package/lib/components/LoginPageExpired.js.map +1 -1
  31. package/lib/components/LoginResetPassword.d.ts +2 -1
  32. package/lib/components/LoginResetPassword.js +2 -2
  33. package/lib/components/LoginResetPassword.js.map +1 -1
  34. package/lib/components/LoginUpdatePassword.d.ts +2 -1
  35. package/lib/components/LoginUpdatePassword.js +2 -2
  36. package/lib/components/LoginUpdatePassword.js.map +1 -1
  37. package/lib/components/LoginUpdateProfile.d.ts +2 -1
  38. package/lib/components/LoginUpdateProfile.js +2 -2
  39. package/lib/components/LoginUpdateProfile.js.map +1 -1
  40. package/lib/components/LoginVerifyEmail.d.ts +2 -1
  41. package/lib/components/LoginVerifyEmail.js +2 -2
  42. package/lib/components/LoginVerifyEmail.js.map +1 -1
  43. package/lib/components/LogoutConfirm.d.ts +2 -1
  44. package/lib/components/LogoutConfirm.js +2 -2
  45. package/lib/components/LogoutConfirm.js.map +1 -1
  46. package/lib/components/Register.d.ts +2 -1
  47. package/lib/components/Register.js +2 -2
  48. package/lib/components/Register.js.map +1 -1
  49. package/lib/components/RegisterUserProfile.d.ts +2 -1
  50. package/lib/components/RegisterUserProfile.js +2 -2
  51. package/lib/components/RegisterUserProfile.js.map +1 -1
  52. package/lib/components/Terms.d.ts +2 -1
  53. package/lib/components/Terms.js +2 -2
  54. package/lib/components/Terms.js.map +1 -1
  55. package/lib/components/UpdateUserProfile.d.ts +2 -1
  56. package/lib/components/UpdateUserProfile.js +2 -2
  57. package/lib/components/UpdateUserProfile.js.map +1 -1
  58. package/lib/tsconfig.tsbuildinfo +1 -1
  59. package/package.json +3 -3
  60. package/src/lib/components/Error.tsx +30 -24
  61. package/src/lib/components/IdpReviewUserProfile.tsx +41 -30
  62. package/src/lib/components/Info.tsx +41 -35
  63. package/src/lib/components/KcApp.tsx +64 -58
  64. package/src/lib/components/Login.tsx +174 -166
  65. package/src/lib/components/LoginConfigTotp.tsx +158 -152
  66. package/src/lib/components/LoginIdpLinkConfirm.tsx +42 -36
  67. package/src/lib/components/LoginIdpLinkEmail.tsx +30 -24
  68. package/src/lib/components/LoginOtp.tsx +75 -64
  69. package/src/lib/components/LoginPageExpired.tsx +34 -28
  70. package/src/lib/components/LoginResetPassword.tsx +63 -52
  71. package/src/lib/components/LoginUpdatePassword.tsx +101 -95
  72. package/src/lib/components/LoginUpdateProfile.tsx +103 -91
  73. package/src/lib/components/LoginVerifyEmail.tsx +30 -24
  74. package/src/lib/components/LogoutConfirm.tsx +53 -47
  75. package/src/lib/components/Register.tsx +126 -115
  76. package/src/lib/components/RegisterUserProfile.tsx +59 -48
  77. package/src/lib/components/Terms.tsx +51 -45
  78. package/src/lib/components/UpdateUserProfile.tsx +57 -51
@@ -5,182 +5,188 @@ import type { KcContextBase } from "../getKcContext/KcContextBase";
5
5
  import { useCssAndCx } from "../tools/useCssAndCx";
6
6
  import type { I18n } from "../i18n";
7
7
 
8
- const LoginConfigTotp = memo(({ kcContext, i18n, ...props }: { kcContext: KcContextBase.LoginConfigTotp; i18n: I18n } & KcProps) => {
9
- const { url, isAppInitiatedAction, totp, mode, messagesPerField } = kcContext;
8
+ const LoginConfigTotp = memo(
9
+ ({
10
+ kcContext,
11
+ i18n,
12
+ doFetchDefaultThemeResources = true,
13
+ ...props
14
+ }: { kcContext: KcContextBase.LoginConfigTotp; i18n: I18n; doFetchDefaultThemeResources?: boolean } & KcProps) => {
15
+ const { url, isAppInitiatedAction, totp, mode, messagesPerField } = kcContext;
10
16
 
11
- const { cx } = useCssAndCx();
17
+ const { cx } = useCssAndCx();
12
18
 
13
- const { msg, msgStr } = i18n;
19
+ const { msg, msgStr } = i18n;
14
20
 
15
- const algToKeyUriAlg: Record<KcContextBase.LoginConfigTotp["totp"]["policy"]["algorithm"], string> = {
16
- HmacSHA1: "SHA1",
17
- HmacSHA256: "SHA256",
18
- HmacSHA512: "SHA512"
19
- };
21
+ const algToKeyUriAlg: Record<KcContextBase.LoginConfigTotp["totp"]["policy"]["algorithm"], string> = {
22
+ HmacSHA1: "SHA1",
23
+ HmacSHA256: "SHA256",
24
+ HmacSHA512: "SHA512"
25
+ };
20
26
 
21
- return (
22
- <Template
23
- {...{ kcContext, i18n, ...props }}
24
- doFetchDefaultThemeResources={true}
25
- headerNode={msg("loginTotpTitle")}
26
- formNode={
27
- <>
28
- <ol id="kc-totp-settings">
29
- <li>
30
- <p>{msg("loginTotpStep1")}</p>
27
+ return (
28
+ <Template
29
+ {...{ kcContext, i18n, doFetchDefaultThemeResources, ...props }}
30
+ headerNode={msg("loginTotpTitle")}
31
+ formNode={
32
+ <>
33
+ <ol id="kc-totp-settings">
34
+ <li>
35
+ <p>{msg("loginTotpStep1")}</p>
31
36
 
32
- <ul id="kc-totp-supported-apps">
33
- {totp.policy.supportedApplications.map(app => (
34
- <li>{app}</li>
35
- ))}
36
- </ul>
37
- </li>
37
+ <ul id="kc-totp-supported-apps">
38
+ {totp.policy.supportedApplications.map(app => (
39
+ <li>{app}</li>
40
+ ))}
41
+ </ul>
42
+ </li>
38
43
 
39
- {mode && mode == "manual" ? (
40
- <>
44
+ {mode && mode == "manual" ? (
45
+ <>
46
+ <li>
47
+ <p>{msg("loginTotpManualStep2")}</p>
48
+ <p>
49
+ <span id="kc-totp-secret-key">{totp.totpSecretEncoded}</span>
50
+ </p>
51
+ <p>
52
+ <a href={totp.qrUrl} id="mode-barcode">
53
+ {msg("loginTotpScanBarcode")}
54
+ </a>
55
+ </p>
56
+ </li>
57
+ <li>
58
+ <p>{msg("loginTotpManualStep3")}</p>
59
+ <p>
60
+ <ul>
61
+ <li id="kc-totp-type">
62
+ {msg("loginTotpType")}: {msg(`loginTotp.${totp.policy.type}`)}
63
+ </li>
64
+ <li id="kc-totp-algorithm">
65
+ {msg("loginTotpAlgorithm")}: {algToKeyUriAlg?.[totp.policy.algorithm] ?? totp.policy.algorithm}
66
+ </li>
67
+ <li id="kc-totp-digits">
68
+ {msg("loginTotpDigits")}: {totp.policy.digits}
69
+ </li>
70
+ {totp.policy.type === "totp" ? (
71
+ <li id="kc-totp-period">
72
+ {msg("loginTotpInterval")}: {totp.policy.period}
73
+ </li>
74
+ ) : (
75
+ <li id="kc-totp-counter">
76
+ {msg("loginTotpCounter")}: {totp.policy.initialCounter}
77
+ </li>
78
+ )}
79
+ </ul>
80
+ </p>
81
+ </li>
82
+ </>
83
+ ) : (
41
84
  <li>
42
- <p>{msg("loginTotpManualStep2")}</p>
43
- <p>
44
- <span id="kc-totp-secret-key">{totp.totpSecretEncoded}</span>
45
- </p>
85
+ <p>{msg("loginTotpStep2")}</p>
86
+ <img id="kc-totp-secret-qr-code" src={`data:image/png;base64, ${totp.totpSecretQrCode}`} alt="Figure: Barcode" />
87
+ <br />
46
88
  <p>
47
- <a href={totp.qrUrl} id="mode-barcode">
48
- {msg("loginTotpScanBarcode")}
89
+ <a href={totp.manualUrl} id="mode-manual">
90
+ {msg("loginTotpUnableToScan")}
49
91
  </a>
50
92
  </p>
51
93
  </li>
52
- <li>
53
- <p>{msg("loginTotpManualStep3")}</p>
54
- <p>
55
- <ul>
56
- <li id="kc-totp-type">
57
- {msg("loginTotpType")}: {msg(`loginTotp.${totp.policy.type}`)}
58
- </li>
59
- <li id="kc-totp-algorithm">
60
- {msg("loginTotpAlgorithm")}: {algToKeyUriAlg?.[totp.policy.algorithm] ?? totp.policy.algorithm}
61
- </li>
62
- <li id="kc-totp-digits">
63
- {msg("loginTotpDigits")}: {totp.policy.digits}
64
- </li>
65
- {totp.policy.type === "totp" ? (
66
- <li id="kc-totp-period">
67
- {msg("loginTotpInterval")}: {totp.policy.period}
68
- </li>
69
- ) : (
70
- <li id="kc-totp-counter">
71
- {msg("loginTotpCounter")}: {totp.policy.initialCounter}
72
- </li>
73
- )}
74
- </ul>
75
- </p>
76
- </li>
77
- </>
78
- ) : (
94
+ )}
79
95
  <li>
80
- <p>{msg("loginTotpStep2")}</p>
81
- <img id="kc-totp-secret-qr-code" src={`data:image/png;base64, ${totp.totpSecretQrCode}`} alt="Figure: Barcode" />
82
- <br />
83
- <p>
84
- <a href={totp.manualUrl} id="mode-manual">
85
- {msg("loginTotpUnableToScan")}
86
- </a>
87
- </p>
96
+ <p>{msg("loginTotpStep3")}</p>
97
+ <p>{msg("loginTotpStep3DeviceName")}</p>
88
98
  </li>
89
- )}
90
- <li>
91
- <p>{msg("loginTotpStep3")}</p>
92
- <p>{msg("loginTotpStep3DeviceName")}</p>
93
- </li>
94
- </ol>
99
+ </ol>
95
100
 
96
- <form action={url.loginAction} className={cx(props.kcFormClass)} id="kc-totp-settings-form" method="post">
97
- <div className={cx(props.kcFormGroupClass)}>
98
- <div className={cx(props.kcInputWrapperClass)}>
99
- <label htmlFor="totp" className={cx(props.kcLabelClass)}>
100
- {msg("authenticatorCode")}
101
- </label>{" "}
102
- <span className="required">*</span>
103
- </div>
104
- <div className={cx(props.kcInputWrapperClass)}>
105
- <input
106
- type="text"
107
- id="totp"
108
- name="totp"
109
- autoComplete="off"
110
- className={cx(props.kcInputClass)}
111
- aria-invalid={messagesPerField.existsError("totp")}
112
- />
101
+ <form action={url.loginAction} className={cx(props.kcFormClass)} id="kc-totp-settings-form" method="post">
102
+ <div className={cx(props.kcFormGroupClass)}>
103
+ <div className={cx(props.kcInputWrapperClass)}>
104
+ <label htmlFor="totp" className={cx(props.kcLabelClass)}>
105
+ {msg("authenticatorCode")}
106
+ </label>{" "}
107
+ <span className="required">*</span>
108
+ </div>
109
+ <div className={cx(props.kcInputWrapperClass)}>
110
+ <input
111
+ type="text"
112
+ id="totp"
113
+ name="totp"
114
+ autoComplete="off"
115
+ className={cx(props.kcInputClass)}
116
+ aria-invalid={messagesPerField.existsError("totp")}
117
+ />
113
118
 
114
- {messagesPerField.existsError("totp") && (
115
- <span id="input-error-otp-code" className={cx(props.kcInputErrorMessageClass)} aria-live="polite">
116
- {messagesPerField.get("totp")}
117
- </span>
118
- )}
119
+ {messagesPerField.existsError("totp") && (
120
+ <span id="input-error-otp-code" className={cx(props.kcInputErrorMessageClass)} aria-live="polite">
121
+ {messagesPerField.get("totp")}
122
+ </span>
123
+ )}
124
+ </div>
125
+ <input type="hidden" id="totpSecret" name="totpSecret" value={totp.totpSecret} />
126
+ {mode && <input type="hidden" id="mode" value={mode} />}
119
127
  </div>
120
- <input type="hidden" id="totpSecret" name="totpSecret" value={totp.totpSecret} />
121
- {mode && <input type="hidden" id="mode" value={mode} />}
122
- </div>
123
128
 
124
- <div className={cx(props.kcFormGroupClass)}>
125
- <div className={cx(props.kcInputWrapperClass)}>
126
- <label htmlFor="userLabel" className={cx(props.kcLabelClass)}>
127
- {msg("loginTotpDeviceName")}
128
- </label>{" "}
129
- {totp.otpCredentials.length >= 1 && <span className="required">*</span>}
130
- </div>
131
- <div className={cx(props.kcInputWrapperClass)}>
132
- <input
133
- type="text"
134
- id="userLabel"
135
- name="userLabel"
136
- autoComplete="off"
137
- className={cx(props.kcInputClass)}
138
- aria-invalid={messagesPerField.existsError("userLabel")}
139
- />
140
- {messagesPerField.existsError("userLabel") && (
141
- <span id="input-error-otp-label" className={cx(props.kcInputErrorMessageClass)} aria-live="polite">
142
- {messagesPerField.get("userLabel")}
143
- </span>
144
- )}
129
+ <div className={cx(props.kcFormGroupClass)}>
130
+ <div className={cx(props.kcInputWrapperClass)}>
131
+ <label htmlFor="userLabel" className={cx(props.kcLabelClass)}>
132
+ {msg("loginTotpDeviceName")}
133
+ </label>{" "}
134
+ {totp.otpCredentials.length >= 1 && <span className="required">*</span>}
135
+ </div>
136
+ <div className={cx(props.kcInputWrapperClass)}>
137
+ <input
138
+ type="text"
139
+ id="userLabel"
140
+ name="userLabel"
141
+ autoComplete="off"
142
+ className={cx(props.kcInputClass)}
143
+ aria-invalid={messagesPerField.existsError("userLabel")}
144
+ />
145
+ {messagesPerField.existsError("userLabel") && (
146
+ <span id="input-error-otp-label" className={cx(props.kcInputErrorMessageClass)} aria-live="polite">
147
+ {messagesPerField.get("userLabel")}
148
+ </span>
149
+ )}
150
+ </div>
145
151
  </div>
146
- </div>
147
152
 
148
- {isAppInitiatedAction ? (
149
- <>
153
+ {isAppInitiatedAction ? (
154
+ <>
155
+ <input
156
+ type="submit"
157
+ className={cx(props.kcButtonClass, props.kcButtonPrimaryClass, props.kcButtonLargeClass)}
158
+ id="saveTOTPBtn"
159
+ value={msgStr("doSubmit")}
160
+ />
161
+ <button
162
+ type="submit"
163
+ className={cx(
164
+ props.kcButtonClass,
165
+ props.kcButtonDefaultClass,
166
+ props.kcButtonLargeClass,
167
+ props.kcButtonLargeClass
168
+ )}
169
+ id="cancelTOTPBtn"
170
+ name="cancel-aia"
171
+ value="true"
172
+ >
173
+ ${msg("doCancel")}
174
+ </button>
175
+ </>
176
+ ) : (
150
177
  <input
151
178
  type="submit"
152
179
  className={cx(props.kcButtonClass, props.kcButtonPrimaryClass, props.kcButtonLargeClass)}
153
180
  id="saveTOTPBtn"
154
181
  value={msgStr("doSubmit")}
155
182
  />
156
- <button
157
- type="submit"
158
- className={cx(
159
- props.kcButtonClass,
160
- props.kcButtonDefaultClass,
161
- props.kcButtonLargeClass,
162
- props.kcButtonLargeClass
163
- )}
164
- id="cancelTOTPBtn"
165
- name="cancel-aia"
166
- value="true"
167
- >
168
- ${msg("doCancel")}
169
- </button>
170
- </>
171
- ) : (
172
- <input
173
- type="submit"
174
- className={cx(props.kcButtonClass, props.kcButtonPrimaryClass, props.kcButtonLargeClass)}
175
- id="saveTOTPBtn"
176
- value={msgStr("doSubmit")}
177
- />
178
- )}
179
- </form>
180
- </>
181
- }
182
- />
183
- );
184
- });
183
+ )}
184
+ </form>
185
+ </>
186
+ }
187
+ />
188
+ );
189
+ }
190
+ );
185
191
 
186
192
  export default LoginConfigTotp;
@@ -5,44 +5,50 @@ import type { KcContextBase } from "../getKcContext/KcContextBase";
5
5
  import { useCssAndCx } from "../tools/useCssAndCx";
6
6
  import type { I18n } from "../i18n";
7
7
 
8
- const LoginIdpLinkConfirm = memo(({ kcContext, i18n, ...props }: { kcContext: KcContextBase.LoginIdpLinkConfirm; i18n: I18n } & KcProps) => {
9
- const { url, idpAlias } = kcContext;
8
+ const LoginIdpLinkConfirm = memo(
9
+ ({
10
+ kcContext,
11
+ i18n,
12
+ doFetchDefaultThemeResources = true,
13
+ ...props
14
+ }: { kcContext: KcContextBase.LoginIdpLinkConfirm; i18n: I18n; doFetchDefaultThemeResources?: boolean } & KcProps) => {
15
+ const { url, idpAlias } = kcContext;
10
16
 
11
- const { msg } = i18n;
17
+ const { msg } = i18n;
12
18
 
13
- const { cx } = useCssAndCx();
19
+ const { cx } = useCssAndCx();
14
20
 
15
- return (
16
- <Template
17
- {...{ kcContext, i18n, ...props }}
18
- doFetchDefaultThemeResources={true}
19
- headerNode={msg("confirmLinkIdpTitle")}
20
- formNode={
21
- <form id="kc-register-form" action={url.loginAction} method="post">
22
- <div className={cx(props.kcFormGroupClass)}>
23
- <button
24
- type="submit"
25
- className={cx(props.kcButtonClass, props.kcButtonDefaultClass, props.kcButtonBlockClass, props.kcButtonLargeClass)}
26
- name="submitAction"
27
- id="updateProfile"
28
- value="updateProfile"
29
- >
30
- {msg("confirmLinkIdpReviewProfile")}
31
- </button>
32
- <button
33
- type="submit"
34
- className={cx(props.kcButtonClass, props.kcButtonDefaultClass, props.kcButtonBlockClass, props.kcButtonLargeClass)}
35
- name="submitAction"
36
- id="linkAccount"
37
- value="linkAccount"
38
- >
39
- {msg("confirmLinkIdpContinue", idpAlias)}
40
- </button>
41
- </div>
42
- </form>
43
- }
44
- />
45
- );
46
- });
21
+ return (
22
+ <Template
23
+ {...{ kcContext, i18n, doFetchDefaultThemeResources, ...props }}
24
+ headerNode={msg("confirmLinkIdpTitle")}
25
+ formNode={
26
+ <form id="kc-register-form" action={url.loginAction} method="post">
27
+ <div className={cx(props.kcFormGroupClass)}>
28
+ <button
29
+ type="submit"
30
+ className={cx(props.kcButtonClass, props.kcButtonDefaultClass, props.kcButtonBlockClass, props.kcButtonLargeClass)}
31
+ name="submitAction"
32
+ id="updateProfile"
33
+ value="updateProfile"
34
+ >
35
+ {msg("confirmLinkIdpReviewProfile")}
36
+ </button>
37
+ <button
38
+ type="submit"
39
+ className={cx(props.kcButtonClass, props.kcButtonDefaultClass, props.kcButtonBlockClass, props.kcButtonLargeClass)}
40
+ name="submitAction"
41
+ id="linkAccount"
42
+ value="linkAccount"
43
+ >
44
+ {msg("confirmLinkIdpContinue", idpAlias)}
45
+ </button>
46
+ </div>
47
+ </form>
48
+ }
49
+ />
50
+ );
51
+ }
52
+ );
47
53
 
48
54
  export default LoginIdpLinkConfirm;
@@ -4,31 +4,37 @@ import type { KcProps } from "./KcProps";
4
4
  import type { KcContextBase } from "../getKcContext/KcContextBase";
5
5
  import type { I18n } from "../i18n";
6
6
 
7
- const LoginIdpLinkEmail = memo(({ kcContext, i18n, ...props }: { kcContext: KcContextBase.LoginIdpLinkEmail; i18n: I18n } & KcProps) => {
8
- const { url, realm, brokerContext, idpAlias } = kcContext;
7
+ const LoginIdpLinkEmail = memo(
8
+ ({
9
+ kcContext,
10
+ i18n,
11
+ doFetchDefaultThemeResources = true,
12
+ ...props
13
+ }: { kcContext: KcContextBase.LoginIdpLinkEmail; i18n: I18n; doFetchDefaultThemeResources?: boolean } & KcProps) => {
14
+ const { url, realm, brokerContext, idpAlias } = kcContext;
9
15
 
10
- const { msg } = i18n;
16
+ const { msg } = i18n;
11
17
 
12
- return (
13
- <Template
14
- {...{ kcContext, i18n, ...props }}
15
- doFetchDefaultThemeResources={true}
16
- headerNode={msg("emailLinkIdpTitle", idpAlias)}
17
- formNode={
18
- <>
19
- <p id="instruction1" className="instruction">
20
- {msg("emailLinkIdp1", idpAlias, brokerContext.username, realm.displayName)}
21
- </p>
22
- <p id="instruction2" className="instruction">
23
- {msg("emailLinkIdp2")} <a href={url.loginAction}>{msg("doClickHere")}</a> {msg("emailLinkIdp3")}
24
- </p>
25
- <p id="instruction3" className="instruction">
26
- {msg("emailLinkIdp4")} <a href={url.loginAction}>{msg("doClickHere")}</a> {msg("emailLinkIdp5")}
27
- </p>
28
- </>
29
- }
30
- />
31
- );
32
- });
18
+ return (
19
+ <Template
20
+ {...{ kcContext, i18n, doFetchDefaultThemeResources, ...props }}
21
+ headerNode={msg("emailLinkIdpTitle", idpAlias)}
22
+ formNode={
23
+ <>
24
+ <p id="instruction1" className="instruction">
25
+ {msg("emailLinkIdp1", idpAlias, brokerContext.username, realm.displayName)}
26
+ </p>
27
+ <p id="instruction2" className="instruction">
28
+ {msg("emailLinkIdp2")} <a href={url.loginAction}>{msg("doClickHere")}</a> {msg("emailLinkIdp3")}
29
+ </p>
30
+ <p id="instruction3" className="instruction">
31
+ {msg("emailLinkIdp4")} <a href={url.loginAction}>{msg("doClickHere")}</a> {msg("emailLinkIdp5")}
32
+ </p>
33
+ </>
34
+ }
35
+ />
36
+ );
37
+ }
38
+ );
33
39
 
34
40
  export default LoginIdpLinkEmail;