diff --git a/themes/src/main/resources/theme/keycloak.v2/login/field.ftl b/themes/src/main/resources/theme/keycloak.v2/login/field.ftl
index 538f387052..845f5994f3 100644
--- a/themes/src/main/resources/theme/keycloak.v2/login/field.ftl
+++ b/themes/src/main/resources/theme/keycloak.v2/login/field.ftl
@@ -14,6 +14,7 @@
<#nested>
+
diff --git a/themes/src/main/resources/theme/keycloak.v2/login/register.ftl b/themes/src/main/resources/theme/keycloak.v2/login/register.ftl
index 726b4ffea7..0e06d693aa 100755
--- a/themes/src/main/resources/theme/keycloak.v2/login/register.ftl
+++ b/themes/src/main/resources/theme/keycloak.v2/login/register.ftl
@@ -13,7 +13,6 @@
#if>
<#elseif section = "form">
+
+
+
+
+
+
+
+
+
#if>
@layout.registrationLayout>
diff --git a/themes/src/main/resources/theme/keycloak.v2/login/resources/js/password-policy.js b/themes/src/main/resources/theme/keycloak.v2/login/resources/js/password-policy.js
new file mode 100644
index 0000000000..466bcc6636
--- /dev/null
+++ b/themes/src/main/resources/theme/keycloak.v2/login/resources/js/password-policy.js
@@ -0,0 +1,53 @@
+const policies = {
+ length: (policy, value) => {
+ if (value.length < policy.value) {
+ return templateError(policy);
+ }
+ },
+ maxLength: (policy, value) => {
+ if (value.length > policy.value) {
+ return templateError(policy);
+ }
+ },
+ upperCase: (policy, value) => {
+ if (
+ value.split("").filter((char) => char !== char.toUpperCase()).length >
+ policy.value
+ ) {
+ return templateError(policy);
+ }
+ },
+ lowerCase: (policy, value) => {
+ if (
+ value.split("").filter((char) => char !== char.toLowerCase()).length >
+ policy.value
+ ) {
+ return templateError(policy);
+ }
+ },
+ digits: (policy, value) => {
+ const digits = value.split("").filter((char) => char.match(/\d/));
+ if (digits.length < policy.value) {
+ return templateError(policy);
+ }
+ },
+ specialChars: (policy, value) => {
+ let specialChars = value.split("").filter((char) => char.match(/\W/));
+ if (specialChars.length < policy.value) {
+ return templateError(policy);
+ }
+ },
+};
+
+const templateError = (policy) => policy.error.replace("{0}", policy.value);
+
+export function validatePassword(password, activePolicies) {
+ const errors = [];
+ for (const p of activePolicies) {
+ const validationError = policies[p.name](p.policy, password);
+ if (validationError) {
+ errors.push(validationError);
+ }
+ }
+ return errors;
+}