diff --git a/account/sessions.ftl b/account/sessions.ftl index 89851a1..b57ea11 100755 --- a/account/sessions.ftl +++ b/account/sessions.ftl @@ -1,46 +1,46 @@ <#import "template.ftl" as layout> <@layout.mainLayout active='sessions' bodyClass='sessions'; section> -
-
-

${msg("sessionsHtmlTitle")}

-
+
+
+

${msg("sessionsHtmlTitle")}

+
- - - - - - - - - - +
${msg("ip")}${msg("started")}${msg("lastAccess")}${msg("expires")}${msg("clients")}
+ + + + + + + + + - - <#list sessions.sessions as session> - - - - - - - - - -
${msg("ip")}${msg("started")}${msg("lastAccess")}${msg("expires")}${msg("clients")}
${session.ipAddress}${session.started?datetime}${session.lastAccess?datetime}${session.expires?datetime} - <#list session.clients as client> - ${client}
- -
+ + <#list sessions.sessions as session> + + ${session.ipAddress} + ${session.started?datetime} + ${session.lastAccess?datetime} + ${session.expires?datetime} + + <#list session.clients as client> + ${client}
+ + + + + + -
- - -
+
+ + +
diff --git a/account/template.ftl b/account/template.ftl index e5053a3..885b20e 100644 --- a/account/template.ftl +++ b/account/template.ftl @@ -13,6 +13,7 @@ + <#if properties.stylesCommon?has_content> <#list properties.stylesCommon?split(' ') as style> @@ -59,16 +60,17 @@ pub.solar/ <#if realm.internationalizationEnabled && locale.supported?size gt 1> - +
diff --git a/login/webauthn-authenticate.ftl b/login/webauthn-authenticate.ftl index a07f750..00eb269 100644 --- a/login/webauthn-authenticate.ftl +++ b/login/webauthn-authenticate.ftl @@ -1,168 +1,168 @@ - <#import "template.ftl" as layout> - <@layout.registrationLayout; section> - <#if section = "title"> - title - <#elseif section = "header"> - ${kcSanitize(msg("webauthn-login-title"))?no_esc} - <#elseif section = "form"> -
-
- - - - - - -
+ <#import "template.ftl" as layout> + <@layout.registrationLayout; section> + <#if section = "title"> + title + <#elseif section = "header"> + ${kcSanitize(msg("webauthn-login-title"))?no_esc} + <#elseif section = "form"> +
+
+ + + + + + +
-
- <#if authenticators??> -
- <#list authenticators.authenticators as authenticator> - +
+ <#if authenticators??> + + <#list authenticators.authenticators as authenticator> + + + + + <#if shouldDisplayAuthenticators?? && shouldDisplayAuthenticators> + <#if authenticators.authenticators?size gt 1> +

${kcSanitize(msg("webauthn-available-authenticators"))?no_esc}

+ + +
+ <#list authenticators.authenticators as authenticator> +
+
+ +
+
+
+ ${kcSanitize(msg('${authenticator.label}'))?no_esc} +
+ + <#if authenticator.transports?? && authenticator.transports.displayNameProperties?has_content> +
+ <#list authenticator.transports.displayNameProperties as nameProperty> + ${kcSanitize(msg('${nameProperty!}'))?no_esc} + <#if nameProperty?has_next> + , + - - - <#if shouldDisplayAuthenticators?? && shouldDisplayAuthenticators> - <#if authenticators.authenticators?size gt 1> -

${kcSanitize(msg("webauthn-available-authenticators"))?no_esc}

- - -
- <#list authenticators.authenticators as authenticator> -
-
- -
-
-
- ${kcSanitize(msg('${authenticator.label}'))?no_esc} -
- - <#if authenticator.transports?? && authenticator.transports.displayNameProperties?has_content> -
- <#list authenticator.transports.displayNameProperties as nameProperty> - ${kcSanitize(msg('${nameProperty!}'))?no_esc} - <#if nameProperty?has_next> - , - - -
- - -
- - ${kcSanitize(msg('webauthn-createdAt-label'))?no_esc} - - - ${kcSanitize(authenticator.createdAt)?no_esc} - -
-
-
-
- -
+
- -
- +
+ + ${kcSanitize(msg('webauthn-createdAt-label'))?no_esc} + + + ${kcSanitize(authenticator.createdAt)?no_esc} + +
+
+
+
+ + + +
+
+
+
- - - + + - <#elseif section = "info"> + function checkAllowCredentials() { + let allowCredentials = []; + let authn_use = document.forms['authn_select'].authn_use_chk; - - + if (authn_use !== undefined) { + if (authn_use.length === undefined) { + allowCredentials.push({ + id: base64url.decode(authn_use.value, {loose: true}), + type: 'public-key', + }); + } else { + for (let i = 0; i < authn_use.length; i++) { + allowCredentials.push({ + id: base64url.decode(authn_use[i].value, {loose: true}), + type: 'public-key', + }); + } + } + } + doAuthenticate(allowCredentials); + } + + + function doAuthenticate(allowCredentials) { + + // Check if WebAuthn is supported by this browser + if (!window.PublicKeyCredential) { + $("#error").val("${msg("webauthn-unsupported-browser-text")?no_esc}"); + $("#webauth").submit(); + return; + } + + let challenge = "${challenge}"; + let userVerification = "${userVerification}"; + let rpId = "${rpId}"; + let publicKey = { + rpId : rpId, + challenge: base64url.decode(challenge, { loose: true }) + }; + + let createTimeout = ${createTimeout}; + if (createTimeout !== 0) publicKey.timeout = createTimeout * 1000; + + if (allowCredentials.length) { + publicKey.allowCredentials = allowCredentials; + } + + if (userVerification !== 'not specified') publicKey.userVerification = userVerification; + + navigator.credentials.get({publicKey}) + .then((result) => { + window.result = result; + + let clientDataJSON = result.response.clientDataJSON; + let authenticatorData = result.response.authenticatorData; + let signature = result.response.signature; + + $("#clientDataJSON").val(base64url.encode(new Uint8Array(clientDataJSON), { pad: false })); + $("#authenticatorData").val(base64url.encode(new Uint8Array(authenticatorData), { pad: false })); + $("#signature").val(base64url.encode(new Uint8Array(signature), { pad: false })); + $("#credentialId").val(result.id); + if(result.response.userHandle) { + $("#userHandle").val(base64url.encode(new Uint8Array(result.response.userHandle), { pad: false })); + } + $("#webauth").submit(); + }) + .catch((err) => { + $("#error").val(err); + $("#webauth").submit(); + }) + ; + } + + + <#elseif section = "info"> + + +