@keycloakify/svelte 0.0.1-rc.6 → 0.1.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 (196) hide show
  1. package/README.md +1 -1
  2. package/keycloakify-svelte/account/DefaultPage.svelte +42 -0
  3. package/keycloakify-svelte/account/DefaultPage.svelte.d.ts +6 -0
  4. package/keycloakify-svelte/account/KcContext/KcContext.d.ts +1 -0
  5. package/keycloakify-svelte/account/KcContext/KcContext.js +1 -0
  6. package/keycloakify-svelte/account/KcContext/index.d.ts +1 -0
  7. package/keycloakify-svelte/account/KcContext/index.js +1 -0
  8. package/keycloakify-svelte/account/Template.svelte +143 -0
  9. package/keycloakify-svelte/account/Template.svelte.d.ts +6 -0
  10. package/keycloakify-svelte/account/Template.useInitialize.d.ts +12 -0
  11. package/keycloakify-svelte/account/Template.useInitialize.js +19 -0
  12. package/keycloakify-svelte/account/TemplateProps.d.ts +12 -0
  13. package/keycloakify-svelte/account/TemplateProps.js +1 -0
  14. package/keycloakify-svelte/account/i18n/i18n.d.ts +15 -0
  15. package/keycloakify-svelte/account/i18n/i18n.js +1 -0
  16. package/keycloakify-svelte/account/i18n/i18nBuilder.d.ts +18 -0
  17. package/keycloakify-svelte/account/i18n/i18nBuilder.js +26 -0
  18. package/keycloakify-svelte/account/i18n/index.d.ts +1 -0
  19. package/keycloakify-svelte/account/i18n/index.js +1 -0
  20. package/keycloakify-svelte/account/i18n/useI18n.d.ts +28 -0
  21. package/keycloakify-svelte/account/i18n/useI18n.js +65 -0
  22. package/keycloakify-svelte/account/index.d.ts +2 -0
  23. package/keycloakify-svelte/account/index.js +1 -0
  24. package/keycloakify-svelte/account/pages/Account.svelte +182 -0
  25. package/keycloakify-svelte/account/pages/Account.svelte.d.ts +6 -0
  26. package/keycloakify-svelte/account/pages/Applications.svelte +173 -0
  27. package/keycloakify-svelte/account/pages/Applications.svelte.d.ts +6 -0
  28. package/keycloakify-svelte/account/pages/FederatedIdentity.svelte +114 -0
  29. package/keycloakify-svelte/account/pages/FederatedIdentity.svelte.d.ts +6 -0
  30. package/keycloakify-svelte/account/pages/Log.svelte +68 -0
  31. package/keycloakify-svelte/account/pages/Log.svelte.d.ts +6 -0
  32. package/keycloakify-svelte/account/pages/PageProps.d.ts +10 -0
  33. package/keycloakify-svelte/account/pages/PageProps.js +1 -0
  34. package/keycloakify-svelte/account/pages/Password.svelte +233 -0
  35. package/keycloakify-svelte/account/pages/Password.svelte.d.ts +6 -0
  36. package/keycloakify-svelte/account/pages/Sessions.svelte +88 -0
  37. package/keycloakify-svelte/account/pages/Sessions.svelte.d.ts +6 -0
  38. package/keycloakify-svelte/account/pages/Totp.svelte +287 -0
  39. package/keycloakify-svelte/account/pages/Totp.svelte.d.ts +6 -0
  40. package/keycloakify-svelte/additional-svelte-typings.d.ts +6 -0
  41. package/keycloakify-svelte/bin/200.index.js +399 -0
  42. package/keycloakify-svelte/bin/266.index.js +964 -0
  43. package/keycloakify-svelte/bin/279.index.js +4298 -0
  44. package/keycloakify-svelte/bin/709.index.js +494 -0
  45. package/keycloakify-svelte/bin/818.index.js +1037 -0
  46. package/keycloakify-svelte/bin/index.js +2454 -0
  47. package/keycloakify-svelte/bin/package.json +3 -0
  48. package/keycloakify-svelte/login/DefaultPage.svelte +135 -0
  49. package/keycloakify-svelte/login/DefaultPage.svelte.d.ts +12 -0
  50. package/keycloakify-svelte/login/KcContext/KcContext.d.ts +1 -0
  51. package/keycloakify-svelte/login/KcContext/KcContext.js +1 -0
  52. package/keycloakify-svelte/login/KcContext/index.d.ts +1 -0
  53. package/keycloakify-svelte/login/KcContext/index.js +1 -0
  54. package/keycloakify-svelte/login/Template.svelte +223 -0
  55. package/keycloakify-svelte/login/Template.svelte.d.ts +6 -0
  56. package/keycloakify-svelte/login/Template.useInitialize.d.ts +14 -0
  57. package/keycloakify-svelte/login/Template.useInitialize.js +55 -0
  58. package/keycloakify-svelte/login/TemplateProps.d.ts +20 -0
  59. package/keycloakify-svelte/login/TemplateProps.js +1 -0
  60. package/keycloakify-svelte/login/components/AddRemoveButtonsMultiValuedAttribute.svelte +57 -0
  61. package/keycloakify-svelte/login/components/AddRemoveButtonsMultiValuedAttribute.svelte.d.ts +18 -0
  62. package/keycloakify-svelte/login/components/FieldErrors.svelte +31 -0
  63. package/keycloakify-svelte/login/components/FieldErrors.svelte.d.ts +12 -0
  64. package/keycloakify-svelte/login/components/GroupLabel.svelte +68 -0
  65. package/keycloakify-svelte/login/components/GroupLabel.svelte.d.ts +15 -0
  66. package/keycloakify-svelte/login/components/InputFieldByType.svelte +58 -0
  67. package/keycloakify-svelte/login/components/InputFieldByType.svelte.d.ts +4 -0
  68. package/keycloakify-svelte/login/components/InputFieldByTypeProps.d.ts +16 -0
  69. package/keycloakify-svelte/login/components/InputFieldByTypeProps.js +1 -0
  70. package/keycloakify-svelte/login/components/InputTag.svelte +107 -0
  71. package/keycloakify-svelte/login/components/InputTag.svelte.d.ts +7 -0
  72. package/keycloakify-svelte/login/components/InputTagSelects.svelte +111 -0
  73. package/keycloakify-svelte/login/components/InputTagSelects.svelte.d.ts +4 -0
  74. package/keycloakify-svelte/login/components/LogoutOtherSessions.svelte +29 -0
  75. package/keycloakify-svelte/login/components/LogoutOtherSessions.svelte.d.ts +10 -0
  76. package/keycloakify-svelte/login/components/PasswordWrapper.svelte +43 -0
  77. package/keycloakify-svelte/login/components/PasswordWrapper.svelte.d.ts +13 -0
  78. package/keycloakify-svelte/login/components/SelectTag.svelte +72 -0
  79. package/keycloakify-svelte/login/components/SelectTag.svelte.d.ts +4 -0
  80. package/keycloakify-svelte/login/components/TermsAcceptance.svelte +56 -0
  81. package/keycloakify-svelte/login/components/TermsAcceptance.svelte.d.ts +13 -0
  82. package/keycloakify-svelte/login/components/TextareaTag.svelte +40 -0
  83. package/keycloakify-svelte/login/components/TextareaTag.svelte.d.ts +4 -0
  84. package/keycloakify-svelte/login/components/UserProfileFormFields.svelte +123 -0
  85. package/keycloakify-svelte/login/components/UserProfileFormFields.svelte.d.ts +6 -0
  86. package/keycloakify-svelte/login/components/UserProfileFormFieldsProps.d.ts +27 -0
  87. package/keycloakify-svelte/login/components/UserProfileFormFieldsProps.js +2 -0
  88. package/keycloakify-svelte/login/components/inputLabel.d.ts +3 -0
  89. package/keycloakify-svelte/login/components/inputLabel.js +12 -0
  90. package/keycloakify-svelte/login/i18n/i18n.d.ts +15 -0
  91. package/keycloakify-svelte/login/i18n/i18n.js +1 -0
  92. package/keycloakify-svelte/login/i18n/i18nBuilder.d.ts +18 -0
  93. package/keycloakify-svelte/login/i18n/i18nBuilder.js +26 -0
  94. package/keycloakify-svelte/login/i18n/index.d.ts +1 -0
  95. package/keycloakify-svelte/login/i18n/index.js +1 -0
  96. package/keycloakify-svelte/login/i18n/useI18n.d.ts +28 -0
  97. package/keycloakify-svelte/login/i18n/useI18n.js +65 -0
  98. package/keycloakify-svelte/login/index.d.ts +2 -0
  99. package/keycloakify-svelte/login/index.js +1 -0
  100. package/keycloakify-svelte/login/lib/useUserProfileForm.d.ts +66 -0
  101. package/keycloakify-svelte/login/lib/useUserProfileForm.js +63 -0
  102. package/keycloakify-svelte/login/pages/Code.svelte +46 -0
  103. package/keycloakify-svelte/login/pages/Code.svelte.d.ts +6 -0
  104. package/keycloakify-svelte/login/pages/DeleteAccountConfirm.svelte +77 -0
  105. package/keycloakify-svelte/login/pages/DeleteAccountConfirm.svelte.d.ts +6 -0
  106. package/keycloakify-svelte/login/pages/DeleteCredential.svelte +58 -0
  107. package/keycloakify-svelte/login/pages/DeleteCredential.svelte.d.ts +6 -0
  108. package/keycloakify-svelte/login/pages/Error.svelte +43 -0
  109. package/keycloakify-svelte/login/pages/Error.svelte.d.ts +6 -0
  110. package/keycloakify-svelte/login/pages/FrontchannelLogout.svelte +57 -0
  111. package/keycloakify-svelte/login/pages/FrontchannelLogout.svelte.d.ts +6 -0
  112. package/keycloakify-svelte/login/pages/IdpReviewUserProfile.svelte +80 -0
  113. package/keycloakify-svelte/login/pages/IdpReviewUserProfile.svelte.d.ts +11 -0
  114. package/keycloakify-svelte/login/pages/Info.svelte +66 -0
  115. package/keycloakify-svelte/login/pages/Info.svelte.d.ts +6 -0
  116. package/keycloakify-svelte/login/pages/Login.svelte +225 -0
  117. package/keycloakify-svelte/login/pages/Login.svelte.d.ts +6 -0
  118. package/keycloakify-svelte/login/pages/LoginConfigTotp.svelte +217 -0
  119. package/keycloakify-svelte/login/pages/LoginConfigTotp.svelte.d.ts +6 -0
  120. package/keycloakify-svelte/login/pages/LoginIdpLinkConfirm.svelte +60 -0
  121. package/keycloakify-svelte/login/pages/LoginIdpLinkConfirm.svelte.d.ts +6 -0
  122. package/keycloakify-svelte/login/pages/LoginIdpLinkConfirmOverride.svelte +59 -0
  123. package/keycloakify-svelte/login/pages/LoginIdpLinkConfirmOverride.svelte.d.ts +6 -0
  124. package/keycloakify-svelte/login/pages/LoginIdpLinkEmail.svelte +50 -0
  125. package/keycloakify-svelte/login/pages/LoginIdpLinkEmail.svelte.d.ts +6 -0
  126. package/keycloakify-svelte/login/pages/LoginOauth2DeviceVerifyUserCode.svelte +85 -0
  127. package/keycloakify-svelte/login/pages/LoginOauth2DeviceVerifyUserCode.svelte.d.ts +6 -0
  128. package/keycloakify-svelte/login/pages/LoginOauthGrant.svelte +126 -0
  129. package/keycloakify-svelte/login/pages/LoginOauthGrant.svelte.d.ts +6 -0
  130. package/keycloakify-svelte/login/pages/LoginOtp.svelte +128 -0
  131. package/keycloakify-svelte/login/pages/LoginOtp.svelte.d.ts +6 -0
  132. package/keycloakify-svelte/login/pages/LoginPageExpired.svelte +50 -0
  133. package/keycloakify-svelte/login/pages/LoginPageExpired.svelte.d.ts +6 -0
  134. package/keycloakify-svelte/login/pages/LoginPasskeysConditionalAuthenticate.svelte +240 -0
  135. package/keycloakify-svelte/login/pages/LoginPasskeysConditionalAuthenticate.svelte.d.ts +6 -0
  136. package/keycloakify-svelte/login/pages/LoginPasskeysConditionalAuthenticate.useScript.d.ts +21 -0
  137. package/keycloakify-svelte/login/pages/LoginPasskeysConditionalAuthenticate.useScript.js +57 -0
  138. package/keycloakify-svelte/login/pages/LoginPassword.svelte +120 -0
  139. package/keycloakify-svelte/login/pages/LoginPassword.svelte.d.ts +6 -0
  140. package/keycloakify-svelte/login/pages/LoginRecoveryAuthnCodeConfig.svelte +179 -0
  141. package/keycloakify-svelte/login/pages/LoginRecoveryAuthnCodeConfig.svelte.d.ts +6 -0
  142. package/keycloakify-svelte/login/pages/LoginRecoveryAuthnCodeConfig.useScript.d.ts +10 -0
  143. package/keycloakify-svelte/login/pages/LoginRecoveryAuthnCodeConfig.useScript.js +141 -0
  144. package/keycloakify-svelte/login/pages/LoginRecoveryAuthnCodeInput.svelte +94 -0
  145. package/keycloakify-svelte/login/pages/LoginRecoveryAuthnCodeInput.svelte.d.ts +6 -0
  146. package/keycloakify-svelte/login/pages/LoginResetOtp.svelte +86 -0
  147. package/keycloakify-svelte/login/pages/LoginResetOtp.svelte.d.ts +6 -0
  148. package/keycloakify-svelte/login/pages/LoginResetPassword.svelte +109 -0
  149. package/keycloakify-svelte/login/pages/LoginResetPassword.svelte.d.ts +6 -0
  150. package/keycloakify-svelte/login/pages/LoginUpdatePassword.svelte +149 -0
  151. package/keycloakify-svelte/login/pages/LoginUpdatePassword.svelte.d.ts +6 -0
  152. package/keycloakify-svelte/login/pages/LoginUpdateProfile.svelte +98 -0
  153. package/keycloakify-svelte/login/pages/LoginUpdateProfile.svelte.d.ts +11 -0
  154. package/keycloakify-svelte/login/pages/LoginUsername.svelte +182 -0
  155. package/keycloakify-svelte/login/pages/LoginUsername.svelte.d.ts +6 -0
  156. package/keycloakify-svelte/login/pages/LoginVerifyEmail.svelte +39 -0
  157. package/keycloakify-svelte/login/pages/LoginVerifyEmail.svelte.d.ts +6 -0
  158. package/keycloakify-svelte/login/pages/LoginX509Info.svelte +123 -0
  159. package/keycloakify-svelte/login/pages/LoginX509Info.svelte.d.ts +6 -0
  160. package/keycloakify-svelte/login/pages/LogoutConfirm.svelte +77 -0
  161. package/keycloakify-svelte/login/pages/LogoutConfirm.svelte.d.ts +6 -0
  162. package/keycloakify-svelte/login/pages/PageProps.d.ts +10 -0
  163. package/keycloakify-svelte/login/pages/PageProps.js +1 -0
  164. package/keycloakify-svelte/login/pages/Register.svelte +136 -0
  165. package/keycloakify-svelte/login/pages/Register.svelte.d.ts +11 -0
  166. package/keycloakify-svelte/login/pages/SamlPostForm.svelte +80 -0
  167. package/keycloakify-svelte/login/pages/SamlPostForm.svelte.d.ts +6 -0
  168. package/keycloakify-svelte/login/pages/SelectAuthenticator.svelte +63 -0
  169. package/keycloakify-svelte/login/pages/SelectAuthenticator.svelte.d.ts +6 -0
  170. package/keycloakify-svelte/login/pages/Terms.svelte +57 -0
  171. package/keycloakify-svelte/login/pages/Terms.svelte.d.ts +6 -0
  172. package/keycloakify-svelte/login/pages/UpdateEmail.svelte +104 -0
  173. package/keycloakify-svelte/login/pages/UpdateEmail.svelte.d.ts +11 -0
  174. package/keycloakify-svelte/login/pages/WebauthnAuthenticate.svelte +182 -0
  175. package/keycloakify-svelte/login/pages/WebauthnAuthenticate.svelte.d.ts +6 -0
  176. package/keycloakify-svelte/login/pages/WebauthnAuthenticate.useScript.d.ts +22 -0
  177. package/keycloakify-svelte/login/pages/WebauthnAuthenticate.useScript.js +49 -0
  178. package/keycloakify-svelte/login/pages/WebauthnError.svelte +86 -0
  179. package/keycloakify-svelte/login/pages/WebauthnError.svelte.d.ts +6 -0
  180. package/keycloakify-svelte/login/pages/WebauthnRegister.svelte +109 -0
  181. package/keycloakify-svelte/login/pages/WebauthnRegister.svelte.d.ts +6 -0
  182. package/keycloakify-svelte/login/pages/WebauthnRegister.useScript.d.ts +28 -0
  183. package/keycloakify-svelte/login/pages/WebauthnRegister.useScript.js +57 -0
  184. package/keycloakify-svelte/tools/useConst.d.ts +1 -0
  185. package/keycloakify-svelte/tools/useConst.js +4 -0
  186. package/keycloakify-svelte/tools/useInsertLinkTags.d.ts +12 -0
  187. package/keycloakify-svelte/tools/useInsertLinkTags.js +62 -0
  188. package/keycloakify-svelte/tools/useInsertScriptTags.d.ts +29 -0
  189. package/keycloakify-svelte/tools/useInsertScriptTags.js +77 -0
  190. package/keycloakify-svelte/tools/useReducer.d.ts +2 -0
  191. package/keycloakify-svelte/tools/useReducer.js +7 -0
  192. package/keycloakify-svelte/tools/useSetClassName.d.ts +4 -0
  193. package/keycloakify-svelte/tools/useSetClassName.js +15 -0
  194. package/keycloakify-svelte/tools/useState.d.ts +2 -0
  195. package/keycloakify-svelte/tools/useState.js +7 -0
  196. package/package.json +6 -3
@@ -0,0 +1,182 @@
1
+ <script lang="ts">
2
+ import type { PageProps } from './PageProps';
3
+ import { useScript } from './WebauthnAuthenticate.useScript';
4
+ import { type ClassKey, getKcClsx } from 'keycloakify/login/lib/kcClsx';
5
+ import { clsx } from 'keycloakify/tools/clsx';
6
+ import type { CxArg } from 'keycloakify/tools/clsx_withTransform';
7
+ import type { KcContext } from '../KcContext';
8
+ import type { I18n } from '../i18n';
9
+
10
+ const {
11
+ Template,
12
+ kcContext,
13
+ i18n,
14
+ doUseDefaultCss,
15
+ classes,
16
+ }: PageProps<Extract<KcContext, { pageId: 'webauthn-authenticate.ftl' }>, I18n> = $props();
17
+
18
+ const { kcClsx } = getKcClsx({ doUseDefaultCss, classes });
19
+
20
+ const { url, realm, registrationDisabled, authenticators, shouldDisplayAuthenticators } = kcContext;
21
+
22
+ const { msg, msgStr, advancedMsg } = $i18n;
23
+
24
+ const authButtonId = 'authenticateWebAuthnButton';
25
+
26
+ useScript({
27
+ authButtonId,
28
+ kcContext,
29
+ i18n,
30
+ });
31
+ </script>
32
+
33
+ <Template
34
+ {kcContext}
35
+ {i18n}
36
+ {doUseDefaultCss}
37
+ {classes}
38
+ displayInfo={realm.registrationAllowed && !registrationDisabled}
39
+ >
40
+ {#snippet headerNode()}
41
+ {@render msg('webauthn-login-title')()}
42
+ {/snippet}
43
+ {#snippet infoNode()}
44
+ <div id="kc-registration">
45
+ <span>
46
+ {@render msg('noAccount')()}{' '}
47
+ <a
48
+ tabindex={6}
49
+ href={url.registrationUrl}
50
+ >
51
+ {@render msg('doRegister')()}
52
+ </a>
53
+ </span>
54
+ </div>
55
+ {/snippet}
56
+ <div
57
+ id="kc-form-webauthn"
58
+ class={kcClsx('kcFormClass')}
59
+ >
60
+ <form
61
+ id="webauth"
62
+ action={url.loginAction}
63
+ method="post"
64
+ >
65
+ <input
66
+ type="hidden"
67
+ id="clientDataJSON"
68
+ name="clientDataJSON"
69
+ />
70
+ <input
71
+ type="hidden"
72
+ id="authenticatorData"
73
+ name="authenticatorData"
74
+ />
75
+ <input
76
+ type="hidden"
77
+ id="signature"
78
+ name="signature"
79
+ />
80
+ <input
81
+ type="hidden"
82
+ id="credentialId"
83
+ name="credentialId"
84
+ />
85
+ <input
86
+ type="hidden"
87
+ id="userHandle"
88
+ name="userHandle"
89
+ />
90
+ <input
91
+ type="hidden"
92
+ id="error"
93
+ name="error"
94
+ />
95
+ </form>
96
+ <div class={clsx(kcClsx('kcFormGroupClass'), 'no-bottom-margin')}>
97
+ {#if authenticators}
98
+ <form
99
+ id="authn_select"
100
+ class={kcClsx('kcFormClass')}
101
+ >
102
+ {#each authenticators.authenticators as authenticator}
103
+ <input
104
+ type="hidden"
105
+ name="authn_use_chk"
106
+ value={authenticator.credentialId}
107
+ />
108
+ {/each}
109
+ </form>
110
+
111
+ {#if shouldDisplayAuthenticators}
112
+ {#if authenticators.authenticators.length > 1}
113
+ <p class={kcClsx('kcSelectAuthListItemTitle')}>{@render msg('webauthn-available-authenticators')()}</p>
114
+ {/if}
115
+ <div class={kcClsx('kcFormOptionsClass')}>
116
+ {#each authenticators.authenticators as authenticator, i}
117
+ <div
118
+ id={`kc-webauthn-authenticator-item-${i}`}
119
+ class={kcClsx('kcSelectAuthListItemClass')}
120
+ >
121
+ <div class={kcClsx('kcSelectAuthListItemIconClass')}>
122
+ <i
123
+ class={clsx(
124
+ (() => {
125
+ const klass = kcClsx(authenticator.transports.iconClass as CxArg<ClassKey>);
126
+ if (klass === authenticator.transports.iconClass) {
127
+ return kcClsx('kcWebAuthnDefaultIcon');
128
+ }
129
+ return klass;
130
+ })(),
131
+ kcClsx('kcSelectAuthListItemIconPropertyClass'),
132
+ )}
133
+ ></i>
134
+ </div>
135
+ <div class={kcClsx('kcSelectAuthListItemArrowIconClass')}>
136
+ <div
137
+ id={`kc-webauthn-authenticator-label-${i}`}
138
+ class={kcClsx('kcSelectAuthListItemHeadingClass')}
139
+ >
140
+ {@render advancedMsg(authenticator.label)()}
141
+ </div>
142
+ {#if authenticator.transports.displayNameProperties?.length}
143
+ <div
144
+ id={`kc-webauthn-authenticator-transport-${i}`}
145
+ class={kcClsx('kcSelectAuthListItemDescriptionClass')}
146
+ >
147
+ {#each authenticator.transports.displayNameProperties as displayNameProperty, i}
148
+ {@const hasNext = i !== authenticator.transports.displayNameProperties.length - 1}
149
+ {@render advancedMsg(displayNameProperty)()}
150
+ {#if hasNext}<span>, </span>{/if}
151
+ {/each}
152
+ </div>
153
+ {/if}
154
+ <div class={kcClsx('kcSelectAuthListItemDescriptionClass')}>
155
+ <span id={`kc-webauthn-authenticator-createdlabel-${i}`}>
156
+ {@render msg('webauthn-createdAt-label')()}
157
+ </span>
158
+ <span id={`kc-webauthn-authenticator-created-${i}`}>{authenticator.createdAt}</span>
159
+ </div>
160
+ <div class={kcClsx('kcSelectAuthListItemFillClass')}></div>
161
+ </div>
162
+ </div>
163
+ {/each}
164
+ </div>
165
+ {/if}
166
+ {/if}
167
+ <div
168
+ id="kc-form-buttons"
169
+ class={kcClsx('kcFormButtonsClass')}
170
+ >
171
+ <!-- svelte-ignore a11y_autofocus -->
172
+ <input
173
+ id={authButtonId}
174
+ type="button"
175
+ autofocus
176
+ value={msgStr('webauthn-doAuthenticate')}
177
+ class={kcClsx('kcButtonClass', 'kcButtonPrimaryClass', 'kcButtonBlockClass', 'kcButtonLargeClass')}
178
+ />
179
+ </div>
180
+ </div>
181
+ </div>
182
+ </Template>
@@ -0,0 +1,6 @@
1
+ import type { PageProps } from './PageProps';
2
+ import type { KcContext } from '../KcContext';
3
+ import type { I18n } from '../i18n';
4
+ declare const WebauthnAuthenticate: import("svelte").Component<PageProps<KcContext.WebauthnAuthenticate, I18n>, {}, "">;
5
+ type WebauthnAuthenticate = ReturnType<typeof WebauthnAuthenticate>;
6
+ export default WebauthnAuthenticate;
@@ -0,0 +1,22 @@
1
+ import type { KcContext } from '../KcContext';
2
+ import type { Readable } from 'svelte/store';
3
+ type KcContextLike = {
4
+ url: {
5
+ resourcesPath: string;
6
+ };
7
+ isUserIdentified: 'true' | 'false';
8
+ challenge: string;
9
+ userVerification: KcContext.WebauthnAuthenticate['userVerification'];
10
+ rpId: string;
11
+ createTimeout: number | string;
12
+ };
13
+ type I18nLike = {
14
+ msgStr: (key: 'webauthn-unsupported-browser-text') => string;
15
+ isFetchingTranslations: boolean;
16
+ };
17
+ export declare function useScript(params: {
18
+ authButtonId: string;
19
+ kcContext: KcContextLike;
20
+ i18n: Readable<I18nLike>;
21
+ }): void;
22
+ export {};
@@ -0,0 +1,49 @@
1
+ import { useInsertScriptTags } from '../../tools/useInsertScriptTags';
2
+ import { assert } from 'keycloakify/tools/assert';
3
+ import { waitForElementMountedOnDom } from 'keycloakify/tools/waitForElementMountedOnDom';
4
+ import { onMount } from 'svelte';
5
+ assert();
6
+ assert();
7
+ export function useScript(params) {
8
+ const { authButtonId, kcContext, i18n } = params;
9
+ const { url, isUserIdentified, challenge, userVerification, rpId, createTimeout } = kcContext;
10
+ onMount(() => {
11
+ const unsubscribe = i18n.subscribe(($i18n) => {
12
+ const { msgStr, isFetchingTranslations } = $i18n;
13
+ const { insertScriptTags } = useInsertScriptTags({
14
+ componentOrHookName: 'WebauthnAuthenticate',
15
+ scriptTags: [
16
+ {
17
+ type: 'module',
18
+ textContent: () => `
19
+
20
+ import { authenticateByWebAuthn } from "${url.resourcesPath}/js/webauthnAuthenticate.js";
21
+ const authButton = document.getElementById('${authButtonId}');
22
+ authButton.addEventListener("click", function() {
23
+ const input = {
24
+ isUserIdentified : ${isUserIdentified},
25
+ challenge : '${challenge}',
26
+ userVerification : '${userVerification}',
27
+ rpId : '${rpId}',
28
+ createTimeout : ${createTimeout},
29
+ errmsg : ${JSON.stringify(msgStr('webauthn-unsupported-browser-text'))}
30
+ };
31
+ authenticateByWebAuthn(input);
32
+ });
33
+ `,
34
+ },
35
+ ],
36
+ });
37
+ if (isFetchingTranslations) {
38
+ return;
39
+ }
40
+ (async () => {
41
+ await waitForElementMountedOnDom({
42
+ elementId: authButtonId,
43
+ });
44
+ insertScriptTags();
45
+ })();
46
+ });
47
+ return () => unsubscribe();
48
+ });
49
+ }
@@ -0,0 +1,86 @@
1
+ <script lang="ts">
2
+ import type { PageProps } from './PageProps';
3
+ import { getKcClsx } from 'keycloakify/login/lib/kcClsx';
4
+ import type { KcContext } from '../KcContext';
5
+ import type { I18n } from '../i18n';
6
+
7
+ const {
8
+ Template,
9
+ kcContext,
10
+ i18n,
11
+ doUseDefaultCss,
12
+ classes,
13
+ }: PageProps<Extract<KcContext, { pageId: 'webauthn-error.ftl' }>, I18n> = $props();
14
+
15
+ const { url, isAppInitiatedAction } = kcContext;
16
+
17
+ const { msg, msgStr } = $i18n;
18
+
19
+ const { kcClsx } = getKcClsx({
20
+ doUseDefaultCss,
21
+ classes,
22
+ });
23
+ </script>
24
+
25
+ <Template
26
+ {kcContext}
27
+ {i18n}
28
+ {doUseDefaultCss}
29
+ {classes}
30
+ displayMessage={true}
31
+ >
32
+ {#snippet headerNode()}
33
+ {@render msg('webauthn-error-title')()}
34
+ {/snippet}
35
+ <form
36
+ id="kc-error-credential-form"
37
+ class={kcClsx('kcFormClass')}
38
+ action={url.loginAction}
39
+ method="post"
40
+ >
41
+ <input
42
+ type="hidden"
43
+ id="executionValue"
44
+ name="authenticationExecution"
45
+ />
46
+ <input
47
+ type="hidden"
48
+ id="isSetRetry"
49
+ name="isSetRetry"
50
+ />
51
+ </form>
52
+ <input
53
+ tabindex={4}
54
+ onclick={() => {
55
+ // @ts-expect-error: Trusted Keycloak's code
56
+ document.getElementById('isSetRetry').value = 'retry';
57
+ // @ts-expect-error: Trusted Keycloak's code
58
+ document.getElementById('executionValue').value = '${execution}';
59
+ // @ts-expect-error: Trusted Keycloak's code
60
+ document.getElementById('kc-error-credential-form').submit();
61
+ }}
62
+ type="button"
63
+ class={kcClsx('kcButtonClass', 'kcButtonPrimaryClass', 'kcButtonBlockClass', 'kcButtonLargeClass')}
64
+ name="try-again"
65
+ id="kc-try-again"
66
+ value={msgStr('doTryAgain')}
67
+ />
68
+ {#if isAppInitiatedAction}
69
+ <form
70
+ action={url.loginAction}
71
+ class={kcClsx('kcFormClass')}
72
+ id="kc-webauthn-settings-form"
73
+ method="post"
74
+ >
75
+ <button
76
+ type="submit"
77
+ class={kcClsx('kcButtonClass', 'kcButtonDefaultClass', 'kcButtonBlockClass', 'kcButtonLargeClass')}
78
+ id="cancelWebAuthnAIA"
79
+ name="cancel-aia"
80
+ value="true"
81
+ >
82
+ {msgStr('doCancel')}
83
+ </button>
84
+ </form>
85
+ {/if}
86
+ </Template>
@@ -0,0 +1,6 @@
1
+ import type { PageProps } from './PageProps';
2
+ import type { KcContext } from '../KcContext';
3
+ import type { I18n } from '../i18n';
4
+ declare const WebauthnError: import("svelte").Component<PageProps<KcContext.WebauthnError, I18n>, {}, "">;
5
+ type WebauthnError = ReturnType<typeof WebauthnError>;
6
+ export default WebauthnError;
@@ -0,0 +1,109 @@
1
+ <script lang="ts">
2
+ import LogoutOtherSessions from '../components/LogoutOtherSessions.svelte';
3
+ import type { PageProps } from './PageProps';
4
+ import { useScript } from './WebauthnRegister.useScript';
5
+ import { getKcClsx } from 'keycloakify/login/lib/kcClsx';
6
+ import type { KcContext } from '../KcContext';
7
+ import type { I18n } from '../i18n';
8
+
9
+ const {
10
+ Template,
11
+ kcContext,
12
+ i18n,
13
+ doUseDefaultCss,
14
+ classes,
15
+ }: PageProps<Extract<KcContext, { pageId: 'webauthn-register.ftl' }>, I18n> = $props();
16
+
17
+ const { kcClsx } = getKcClsx({ doUseDefaultCss, classes });
18
+
19
+ const { url, isSetRetry, isAppInitiatedAction } = kcContext;
20
+
21
+ const { msg, msgStr } = $i18n;
22
+
23
+ const authButtonId = 'authenticateWebAuthnButton';
24
+
25
+ useScript({
26
+ authButtonId,
27
+ kcContext,
28
+ i18n,
29
+ });
30
+ </script>
31
+
32
+ <Template
33
+ {kcContext}
34
+ {i18n}
35
+ {doUseDefaultCss}
36
+ {classes}
37
+ >
38
+ {#snippet headerNode()}
39
+ <span class={kcClsx('kcWebAuthnKeyIcon')}></span>
40
+ {@render msg('webauthn-registration-title')()}
41
+ {/snippet}
42
+ <form
43
+ id="register"
44
+ class={kcClsx('kcFormClass')}
45
+ action={url.loginAction}
46
+ method="post"
47
+ >
48
+ <div class={kcClsx('kcFormGroupClass')}>
49
+ <input
50
+ type="hidden"
51
+ id="clientDataJSON"
52
+ name="clientDataJSON"
53
+ />
54
+ <input
55
+ type="hidden"
56
+ id="attestationObject"
57
+ name="attestationObject"
58
+ />
59
+ <input
60
+ type="hidden"
61
+ id="publicKeyCredentialId"
62
+ name="publicKeyCredentialId"
63
+ />
64
+ <input
65
+ type="hidden"
66
+ id="authenticatorLabel"
67
+ name="authenticatorLabel"
68
+ />
69
+ <input
70
+ type="hidden"
71
+ id="transports"
72
+ name="transports"
73
+ />
74
+ <input
75
+ type="hidden"
76
+ id="error"
77
+ name="error"
78
+ />
79
+ <LogoutOtherSessions
80
+ {kcClsx}
81
+ {i18n}
82
+ />
83
+ </div>
84
+ </form>
85
+ <input
86
+ type="submit"
87
+ class={kcClsx('kcButtonClass', 'kcButtonPrimaryClass', 'kcButtonBlockClass', 'kcButtonLargeClass')}
88
+ id={authButtonId}
89
+ value={msgStr('doRegisterSecurityKey')}
90
+ />
91
+ {#if !isSetRetry && isAppInitiatedAction}
92
+ <form
93
+ action={url.loginAction}
94
+ class={kcClsx('kcFormClass')}
95
+ id="kc-webauthn-settings-form"
96
+ method="post"
97
+ >
98
+ <button
99
+ type="submit"
100
+ class={kcClsx('kcButtonClass', 'kcButtonDefaultClass', 'kcButtonBlockClass', 'kcButtonLargeClass')}
101
+ id="cancelWebAuthnAIA"
102
+ name="cancel-aia"
103
+ value="true"
104
+ >
105
+ {@render msg('doCancel')()}
106
+ </button>
107
+ </form>
108
+ {/if}
109
+ </Template>
@@ -0,0 +1,6 @@
1
+ import type { PageProps } from './PageProps';
2
+ import type { KcContext } from '../KcContext';
3
+ import type { I18n } from '../i18n';
4
+ declare const WebauthnRegister: import("svelte").Component<PageProps<KcContext.WebauthnRegister, I18n>, {}, "">;
5
+ type WebauthnRegister = ReturnType<typeof WebauthnRegister>;
6
+ export default WebauthnRegister;
@@ -0,0 +1,28 @@
1
+ import type { Readable } from 'svelte/store';
2
+ type KcContextLike = {
3
+ url: {
4
+ resourcesPath: string;
5
+ };
6
+ challenge: string;
7
+ userid: string;
8
+ username: string;
9
+ signatureAlgorithms: string[];
10
+ rpEntityName: string;
11
+ rpId: string;
12
+ attestationConveyancePreference: string;
13
+ authenticatorAttachment: string;
14
+ requireResidentKey: string;
15
+ userVerificationRequirement: string;
16
+ createTimeout: number | string;
17
+ excludeCredentialIds: string;
18
+ };
19
+ type I18nLike = {
20
+ msgStr: (key: 'webauthn-registration-init-label' | 'webauthn-registration-init-label-prompt' | 'webauthn-unsupported-browser-text') => string;
21
+ isFetchingTranslations: boolean;
22
+ };
23
+ export declare function useScript(params: {
24
+ authButtonId: string;
25
+ kcContext: KcContextLike;
26
+ i18n: Readable<I18nLike>;
27
+ }): void;
28
+ export {};
@@ -0,0 +1,57 @@
1
+ import { useInsertScriptTags } from '../../tools/useInsertScriptTags';
2
+ import { assert } from 'keycloakify/tools/assert';
3
+ import { waitForElementMountedOnDom } from 'keycloakify/tools/waitForElementMountedOnDom';
4
+ import { onMount } from 'svelte';
5
+ assert();
6
+ assert();
7
+ export function useScript(params) {
8
+ const { authButtonId, kcContext, i18n } = params;
9
+ const { url, challenge, userid, username, signatureAlgorithms, rpEntityName, rpId, attestationConveyancePreference, authenticatorAttachment, requireResidentKey, userVerificationRequirement, createTimeout, excludeCredentialIds, } = kcContext;
10
+ onMount(() => {
11
+ const unsubscribe = i18n.subscribe(($i18n) => {
12
+ const { msgStr, isFetchingTranslations } = $i18n;
13
+ const { insertScriptTags } = useInsertScriptTags({
14
+ componentOrHookName: 'LoginRecoveryAuthnCodeConfig',
15
+ scriptTags: [
16
+ {
17
+ type: 'module',
18
+ textContent: () => `
19
+ import { registerByWebAuthn } from "${url.resourcesPath}/js/webauthnRegister.js";
20
+ const registerButton = document.getElementById('${authButtonId}');
21
+ registerButton.addEventListener("click", function() {
22
+ const input = {
23
+ challenge : '${challenge}',
24
+ userid : '${userid}',
25
+ username : '${username}',
26
+ signatureAlgorithms : ${JSON.stringify(signatureAlgorithms)},
27
+ rpEntityName : ${JSON.stringify(rpEntityName)},
28
+ rpId : ${JSON.stringify(rpId)},
29
+ attestationConveyancePreference : ${JSON.stringify(attestationConveyancePreference)},
30
+ authenticatorAttachment : ${JSON.stringify(authenticatorAttachment)},
31
+ requireResidentKey : ${JSON.stringify(requireResidentKey)},
32
+ userVerificationRequirement : ${JSON.stringify(userVerificationRequirement)},
33
+ createTimeout : ${createTimeout},
34
+ excludeCredentialIds : ${JSON.stringify(excludeCredentialIds)},
35
+ initLabel : ${JSON.stringify(msgStr('webauthn-registration-init-label'))},
36
+ initLabelPrompt : ${JSON.stringify(msgStr('webauthn-registration-init-label-prompt'))},
37
+ errmsg : ${JSON.stringify(msgStr('webauthn-unsupported-browser-text'))}
38
+ };
39
+ registerByWebAuthn(input);
40
+ });
41
+ `,
42
+ },
43
+ ],
44
+ });
45
+ if (isFetchingTranslations) {
46
+ return;
47
+ }
48
+ (async () => {
49
+ await waitForElementMountedOnDom({
50
+ elementId: authButtonId,
51
+ });
52
+ insertScriptTags();
53
+ })();
54
+ });
55
+ return () => unsubscribe();
56
+ });
57
+ }
@@ -0,0 +1 @@
1
+ export declare function useConst<T>(getValue: () => T): T;
@@ -0,0 +1,4 @@
1
+ export function useConst(getValue) {
2
+ const value = getValue();
3
+ return value;
4
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * NOTE: The component that use this hook can only be mounded once!
3
+ * And can't rerender with different hrefs.
4
+ * If it's mounted again the page will be reloaded.
5
+ * This simulates the behavior of a server rendered page that imports css stylesheet in the head.
6
+ */
7
+ export declare function useInsertLinkTags(params: {
8
+ componentOrHookName: string;
9
+ hrefs: string[];
10
+ }): {
11
+ areAllStyleSheetsLoaded: import("svelte/store").Readable<boolean>;
12
+ };
@@ -0,0 +1,62 @@
1
+ import { onMount } from 'svelte';
2
+ import { id } from 'tsafe/id';
3
+ import { useConst } from './useConst';
4
+ import { useReducer } from './useReducer';
5
+ const alreadyMountedComponentOrHookNames = new Set();
6
+ /**
7
+ * NOTE: The component that use this hook can only be mounded once!
8
+ * And can't rerender with different hrefs.
9
+ * If it's mounted again the page will be reloaded.
10
+ * This simulates the behavior of a server rendered page that imports css stylesheet in the head.
11
+ */
12
+ export function useInsertLinkTags(params) {
13
+ const { hrefs, componentOrHookName } = params;
14
+ onMount(() => {
15
+ const isAlreadyMounted = alreadyMountedComponentOrHookNames.has(componentOrHookName);
16
+ if (isAlreadyMounted) {
17
+ reload: {
18
+ if (new URL(window.location.href).searchParams.get('viewMode') === 'docs') {
19
+ // NOTE: Special case for Storybook, we want to avoid infinite reload loop.
20
+ break reload;
21
+ }
22
+ window.location.reload();
23
+ }
24
+ return;
25
+ }
26
+ alreadyMountedComponentOrHookNames.add(componentOrHookName);
27
+ });
28
+ const [areAllStyleSheetsLoaded, setAllStyleSheetsLoaded] = useReducer(() => true, false);
29
+ const refPrAllStyleSheetLoaded = useConst(() => ({
30
+ current: id(undefined),
31
+ }));
32
+ onMount(() => {
33
+ let isActive = true;
34
+ (refPrAllStyleSheetLoaded.current ??= (async () => {
35
+ let lastMountedHtmlElement = undefined;
36
+ const prs = [];
37
+ for (const href of hrefs) {
38
+ const htmlElement = document.createElement('link');
39
+ prs.push(new Promise((resolve) => htmlElement.addEventListener('load', () => resolve())));
40
+ htmlElement.rel = 'stylesheet';
41
+ htmlElement.href = href;
42
+ if (lastMountedHtmlElement !== undefined) {
43
+ lastMountedHtmlElement.insertAdjacentElement('afterend', htmlElement);
44
+ }
45
+ else {
46
+ document.head.prepend(htmlElement);
47
+ }
48
+ lastMountedHtmlElement = htmlElement;
49
+ }
50
+ await Promise.all(prs);
51
+ })()).then(() => {
52
+ if (!isActive) {
53
+ return;
54
+ }
55
+ setAllStyleSheetsLoaded();
56
+ });
57
+ return () => {
58
+ isActive = false;
59
+ };
60
+ });
61
+ return { areAllStyleSheetsLoaded };
62
+ }
@@ -0,0 +1,29 @@
1
+ export type ScriptTag = ScriptTag.TextContent | ScriptTag.Src;
2
+ export declare namespace ScriptTag {
3
+ type Common = {
4
+ type: 'text/javascript' | 'module';
5
+ };
6
+ export type TextContent = Common & {
7
+ textContent: string | (() => string);
8
+ };
9
+ export type Src = Common & {
10
+ src: string;
11
+ };
12
+ export {};
13
+ }
14
+ /**
15
+ * NOTE: The component that use this hook can only be mounded once!
16
+ * And can't rerender with different scriptTags.
17
+ * If it's mounted again the page will be reloaded.
18
+ * This simulates the behavior of a server rendered page that imports javascript in the head.
19
+ *
20
+ * The returned function is supposed to be called in a useEffect and
21
+ * will not download the scripts multiple times event if called more than once (react strict mode).
22
+ *
23
+ */
24
+ export declare function useInsertScriptTags(params: {
25
+ componentOrHookName: string;
26
+ scriptTags: ScriptTag[];
27
+ }): {
28
+ insertScriptTags: () => void;
29
+ };