@oussemasahbeni/keycloakify-login-shadcn 250004.0.8 → 250004.0.10

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 (30) hide show
  1. package/README.md +317 -0
  2. package/keycloak-theme/components/ui/alert.tsx +69 -61
  3. package/keycloak-theme/components/ui/button.tsx +44 -38
  4. package/keycloak-theme/components/ui/card.tsx +60 -45
  5. package/keycloak-theme/components/ui/checkbox.tsx +24 -22
  6. package/keycloak-theme/components/ui/dropdown-menu.tsx +231 -176
  7. package/keycloak-theme/components/ui/field.tsx +51 -48
  8. package/keycloak-theme/components/ui/input-otp.tsx +56 -49
  9. package/keycloak-theme/components/ui/input.tsx +18 -21
  10. package/keycloak-theme/components/ui/label.tsx +19 -20
  11. package/keycloak-theme/components/ui/radio-group.tsx +27 -25
  12. package/keycloak-theme/components/ui/select.tsx +160 -121
  13. package/keycloak-theme/components/ui/separator.tsx +23 -23
  14. package/keycloak-theme/components/ui/tooltip.tsx +54 -24
  15. package/keycloak-theme/login/KcPage.tsx +0 -1
  16. package/keycloak-theme/login/components/Template/Template.tsx +2 -2
  17. package/keycloak-theme/login/components/Template/useInitializeTemplate.ts +3 -19
  18. package/keycloak-theme/login/index.css +3 -20
  19. package/keycloak-theme/login/pages/login/Form.tsx +49 -51
  20. package/keycloak-theme/login/pages/login/SocialProviders.tsx +9 -4
  21. package/keycloak-theme/login/pages/login/providers/github.svg +4 -3
  22. package/keycloak-theme/login/pages/login/providers/x.svg +4 -3
  23. package/keycloak-theme/login/pages/login/useProviderLogos.tsx +2 -3
  24. package/keycloak-theme/login/styleLevelCustomization.tsx +1 -0
  25. package/keycloak-theme/public/keycloak-theme/login/js/authChecker.js +95 -0
  26. package/keycloak-theme/public/keycloak-theme/login/js/passkeysConditionalAuth.js +86 -0
  27. package/keycloak-theme/public/keycloak-theme/login/js/rfc4648.js +185 -0
  28. package/keycloak-theme/public/keycloak-theme/login/js/webauthnAuthenticate.js +113 -0
  29. package/keycloak-theme/public/keycloak-theme/login/js/webauthnRegister.js +153 -0
  30. package/package.json +1 -1
@@ -0,0 +1,113 @@
1
+ /**
2
+ * This file has been claimed for ownership from @keycloakify/login-ui version 250004.6.5.
3
+ * To relinquish ownership and restore this file to its original content, run the following command:
4
+ *
5
+ * $ npx keycloakify own --path "login/js/webauthnAuthenticate.js" --public --revert
6
+ */
7
+
8
+
9
+
10
+ import { base64url } from "./rfc4648.js";
11
+
12
+ // singleton
13
+ let abortController = undefined;
14
+
15
+ export function signal() {
16
+ if (abortController) {
17
+ // abort the previous call
18
+ const abortError = new Error("Cancelling pending WebAuthn call");
19
+ abortError.name = "AbortError";
20
+ abortController.abort(abortError);
21
+ }
22
+
23
+ abortController = new AbortController();
24
+ return abortController.signal;
25
+ }
26
+
27
+ export async function authenticateByWebAuthn(input) {
28
+ if (!input.isUserIdentified) {
29
+ try {
30
+ const result = await doAuthenticate([], input.challenge, input.userVerification, input.rpId, input.createTimeout, input.errmsg);
31
+ returnSuccess(result);
32
+ } catch (error) {
33
+ returnFailure(error);
34
+ }
35
+ return;
36
+ }
37
+ checkAllowCredentials(input.challenge, input.userVerification, input.rpId, input.createTimeout, input.errmsg);
38
+ }
39
+
40
+ async function checkAllowCredentials(challenge, userVerification, rpId, createTimeout, errmsg) {
41
+ const allowCredentials = [];
42
+ const authnUse = document.forms['authn_select'].authn_use_chk;
43
+ if (authnUse !== undefined) {
44
+ if (authnUse.length === undefined) {
45
+ allowCredentials.push({
46
+ id: base64url.parse(authnUse.value, {loose: true}),
47
+ type: 'public-key',
48
+ });
49
+ } else {
50
+ authnUse.forEach((entry) =>
51
+ allowCredentials.push({
52
+ id: base64url.parse(entry.value, {loose: true}),
53
+ type: 'public-key',
54
+ }));
55
+ }
56
+ }
57
+ try {
58
+ const result = await doAuthenticate(allowCredentials, challenge, userVerification, rpId, createTimeout, errmsg);
59
+ returnSuccess(result);
60
+ } catch (error) {
61
+ returnFailure(error);
62
+ }
63
+ }
64
+
65
+ function doAuthenticate(allowCredentials, challenge, userVerification, rpId, createTimeout, errmsg) {
66
+ // Check if WebAuthn is supported by this browser
67
+ if (!window.PublicKeyCredential) {
68
+ returnFailure(errmsg);
69
+ return;
70
+ }
71
+
72
+ const publicKey = {
73
+ rpId : rpId,
74
+ challenge: base64url.parse(challenge, { loose: true })
75
+ };
76
+
77
+ if (createTimeout !== 0) {
78
+ publicKey.timeout = createTimeout * 1000;
79
+ }
80
+
81
+ if (allowCredentials.length) {
82
+ publicKey.allowCredentials = allowCredentials;
83
+ }
84
+
85
+ if (userVerification !== 'not specified') {
86
+ publicKey.userVerification = userVerification;
87
+ }
88
+
89
+ return navigator.credentials.get({
90
+ publicKey: publicKey,
91
+ signal: signal()
92
+ });
93
+ }
94
+
95
+ export function returnSuccess(result) {
96
+ document.getElementById("clientDataJSON").value = base64url.stringify(new Uint8Array(result.response.clientDataJSON), { pad: false });
97
+ document.getElementById("authenticatorData").value = base64url.stringify(new Uint8Array(result.response.authenticatorData), { pad: false });
98
+ document.getElementById("signature").value = base64url.stringify(new Uint8Array(result.response.signature), { pad: false });
99
+ document.getElementById("credentialId").value = result.id;
100
+ if (result.response.userHandle) {
101
+ document.getElementById("userHandle").value = base64url.stringify(new Uint8Array(result.response.userHandle), { pad: false });
102
+ }
103
+ document.getElementById("webauth").requestSubmit();
104
+ }
105
+
106
+ export function returnFailure(err) {
107
+ document.getElementById("error").value = err;
108
+ document.getElementById("webauth").requestSubmit();
109
+ }
110
+
111
+
112
+
113
+
@@ -0,0 +1,153 @@
1
+ /**
2
+ * This file has been claimed for ownership from @keycloakify/login-ui version 250004.6.5.
3
+ * To relinquish ownership and restore this file to its original content, run the following command:
4
+ *
5
+ * $ npx keycloakify own --path "login/js/webauthnRegister.js" --public --revert
6
+ */
7
+
8
+
9
+
10
+ import { base64url } from "./rfc4648.js";
11
+
12
+ export async function registerByWebAuthn(input) {
13
+
14
+ // Check if WebAuthn is supported by this browser
15
+ if (!window.PublicKeyCredential) {
16
+ returnFailure(input.errmsg);
17
+ return;
18
+ }
19
+
20
+ const publicKey = {
21
+ challenge: base64url.parse(input.challenge, {loose: true}),
22
+ rp: {id: input.rpId, name: input.rpEntityName},
23
+ user: {
24
+ id: base64url.parse(input.userid, {loose: true}),
25
+ name: input.username,
26
+ displayName: input.username
27
+ },
28
+ pubKeyCredParams: getPubKeyCredParams(input.signatureAlgorithms),
29
+ };
30
+
31
+ if (input.attestationConveyancePreference !== 'not specified') {
32
+ publicKey.attestation = input.attestationConveyancePreference;
33
+ }
34
+
35
+ const authenticatorSelection = {};
36
+ let isAuthenticatorSelectionSpecified = false;
37
+
38
+ if (input.authenticatorAttachment !== 'not specified') {
39
+ authenticatorSelection.authenticatorAttachment = input.authenticatorAttachment;
40
+ isAuthenticatorSelectionSpecified = true;
41
+ }
42
+
43
+ if (input.requireResidentKey !== 'not specified') {
44
+ if (input.requireResidentKey === 'Yes') {
45
+ authenticatorSelection.requireResidentKey = true;
46
+ } else {
47
+ authenticatorSelection.requireResidentKey = false;
48
+ }
49
+ isAuthenticatorSelectionSpecified = true;
50
+ }
51
+
52
+ if (input.userVerificationRequirement !== 'not specified') {
53
+ authenticatorSelection.userVerification = input.userVerificationRequirement;
54
+ isAuthenticatorSelectionSpecified = true;
55
+ }
56
+
57
+ if (isAuthenticatorSelectionSpecified) {
58
+ publicKey.authenticatorSelection = authenticatorSelection;
59
+ }
60
+
61
+ if (input.createTimeout !== 0) {
62
+ publicKey.timeout = input.createTimeout * 1000;
63
+ }
64
+
65
+ const excludeCredentials = getExcludeCredentials(input.excludeCredentialIds);
66
+ if (excludeCredentials.length > 0) {
67
+ publicKey.excludeCredentials = excludeCredentials;
68
+ }
69
+
70
+ try {
71
+ const result = await doRegister(publicKey);
72
+ returnSuccess(result, input.initLabel, input.initLabelPrompt);
73
+ } catch (error) {
74
+ returnFailure(error);
75
+ }
76
+ }
77
+
78
+ function doRegister(publicKey) {
79
+ return navigator.credentials.create({publicKey});
80
+ }
81
+
82
+ function getPubKeyCredParams(signatureAlgorithmsList) {
83
+ const pubKeyCredParams = [];
84
+ if (signatureAlgorithmsList.length === 0) {
85
+ pubKeyCredParams.push({type: "public-key", alg: -7});
86
+ return pubKeyCredParams;
87
+ }
88
+
89
+ for (const entry of signatureAlgorithmsList) {
90
+ pubKeyCredParams.push({
91
+ type: "public-key",
92
+ alg: entry
93
+ });
94
+ }
95
+
96
+ return pubKeyCredParams;
97
+ }
98
+
99
+ function getExcludeCredentials(excludeCredentialIds) {
100
+ const excludeCredentials = [];
101
+ if (excludeCredentialIds === "") {
102
+ return excludeCredentials;
103
+ }
104
+
105
+ for (const entry of excludeCredentialIds.split(',')) {
106
+ excludeCredentials.push({
107
+ type: "public-key",
108
+ id: base64url.parse(entry, {loose: true})
109
+ });
110
+ }
111
+
112
+ return excludeCredentials;
113
+ }
114
+
115
+ function getTransportsAsString(transportsList) {
116
+ if (!Array.isArray(transportsList)) {
117
+ return "";
118
+ }
119
+
120
+ return transportsList.join();
121
+ }
122
+
123
+ function returnSuccess(result, initLabel, initLabelPrompt) {
124
+ document.getElementById("clientDataJSON").value = base64url.stringify(new Uint8Array(result.response.clientDataJSON), {pad: false});
125
+ document.getElementById("attestationObject").value = base64url.stringify(new Uint8Array(result.response.attestationObject), {pad: false});
126
+ document.getElementById("publicKeyCredentialId").value = base64url.stringify(new Uint8Array(result.rawId), {pad: false});
127
+
128
+ if (typeof result.response.getTransports === "function") {
129
+ const transports = result.response.getTransports();
130
+ if (transports) {
131
+ document.getElementById("transports").value = getTransportsAsString(transports);
132
+ }
133
+ } else {
134
+ console.log("Your browser is not able to recognize supported transport media for the authenticator.");
135
+ }
136
+
137
+ let labelResult = window.prompt(initLabelPrompt, initLabel);
138
+ if (labelResult === null) {
139
+ labelResult = initLabel;
140
+ }
141
+ document.getElementById("authenticatorLabel").value = labelResult;
142
+
143
+ document.getElementById("register").requestSubmit();
144
+ }
145
+
146
+ function returnFailure(err) {
147
+ document.getElementById("error").value = err;
148
+ document.getElementById("register").requestSubmit();
149
+ }
150
+
151
+
152
+
153
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oussemasahbeni/keycloakify-login-shadcn",
3
- "version": "250004.0.8",
3
+ "version": "250004.0.10",
4
4
  "description": "Keycloakify Shadcn Theme extensions",
5
5
  "license": "MIT",
6
6
  "repository": {