Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for Keycloak 22.0.1 unable to create user with long email address #23132

Merged
merged 6 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ The old LinkedIn way based on OAuth seems to be completely removed from the link

```
kc.[sh|bat] start --features linkedin-oauth ...
```
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
= A new parameter for specify max length of email local part

A new parameter `--spi-user-profile-declarative-user-profile-max-email-local-part-length` is added to set max email local part length taking backwards compatibility
into consideration. The default value is 64. Example of usage:

```
kc.[sh|bat] start --spi-user-profile-declarative-user-profile-max-email-local-part-length=100 ...
```
4 changes: 4 additions & 0 deletions docs/documentation/upgrading/topics/keycloak/changes.adoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
== Migration Changes

=== Migrating to 22.0.4

include::changes-22_0_4.adoc[leveloffset=3]

=== Migrating to 22.0.2

include::changes-22_0_2.adoc[leveloffset=3]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
import java.net.IDN;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.keycloak.Config;

import static java.util.regex.Pattern.CASE_INSENSITIVE;

public class EmailValidationUtil {
private static final int MAX_LOCAL_PART_LENGTH = 64;

private static final String LOCAL_PART_ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~\u0080-\uFFFF-]";
private static final String LOCAL_PART_INSIDE_QUOTES_ATOM = "(?:[a-z0-9!#$%&'*.(),<>\\[\\]:; @+/=?^_`{|}~\u0080-\uFFFF-]|\\\\\\\\|\\\\\\\")";
/**
Expand All @@ -29,6 +28,8 @@ public class EmailValidationUtil {
*/
private static final Pattern EMAIL_DOMAIN_PATTERN = Pattern.compile(DOMAIN + "|\\[" + IP_DOMAIN + "\\]|" + "\\[IPv6:" + IP_V6_DOMAIN + "\\]", CASE_INSENSITIVE);

public static final String MAX_EMAIL_LOCAL_PART_LENGTH = "max-email-local-part-length";


public static boolean isValidEmail(String value) {
if ( value == null || value.length() == 0 ) {
Expand Down Expand Up @@ -56,7 +57,8 @@ public static boolean isValidEmail(String value) {
}

private static boolean isValidEmailLocalPart(String localPart) {
if ( localPart.length() > MAX_LOCAL_PART_LENGTH ) {

if ( localPart.length() > Config.scope("user-profile-declarative-user-profile").getInt(MAX_EMAIL_LOCAL_PART_LENGTH,64) ) {
return false;
}
Matcher matcher = LOCAL_PART_PATTERN.matcher( localPart );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public abstract class AbstractUserProfileProvider<U extends UserProfileProvider>

public static final String CONFIG_ADMIN_READ_ONLY_ATTRIBUTES = "admin-read-only-attributes";
public static final String CONFIG_READ_ONLY_ATTRIBUTES = "read-only-attributes";
public static final String MAX_EMAIL_LOCAL_PART_LENGTH = "max-email-local-part-length";

private static boolean editUsernameCondition(AttributeContext c) {
KeycloakSession session = c.getSession();
Expand Down Expand Up @@ -441,6 +442,12 @@ public List<ProviderConfigProperty> getConfigMetadata() {
.helpText("Array of regular expressions to identify fields that should be treated read-only so administrators can't change them.")
.add()

.property()
.name(MAX_EMAIL_LOCAL_PART_LENGTH)
.type(ProviderConfigProperty.STRING_TYPE)
.helpText("To set user profile max email local part length")
.add()

.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public void testEmailValidation() {
Assert.assertFalse(Validation.isEmailValid("abc@foo."));
Assert.assertFalse(Validation.isEmailValid("abc@foo..bar"));
Assert.assertTrue(Validation.isEmailValid("diegø@foo.com"));
Assert.assertTrue(Validation.isEmailValid("qwertyuiopasdfghjklz@foo.com"));
Assert.assertFalse(Validation.isEmailValid("qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyqwertyu@foo.com"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ spi-truststore-file-password=secret
spi-user-profile-provider=declarative-user-profile
spi-user-profile-declarative-user-profile-read-only-attributes=deniedFoo,deniedBar*,deniedSome/thing,deniedsome*thing
spi-user-profile-declarative-user-profile-admin-read-only-attributes=deniedSomeAdmin
spi-user-profile-declarative-user-profile-max-email-local-part-length=100

#password-blacklists path
spi-password-policy-password-blacklist-blacklists-path=${kc.home.dir:}/dependency/password-blacklists
Expand Down