Only reuse SMTP authentication data for testing endpoint when the same auth, host, port and user are passed

Closes #39486

Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
rmartinc 2025-05-20 10:17:18 +02:00 committed by Marek Posolda
parent cf47bef66b
commit 598154bc58
2 changed files with 28 additions and 5 deletions

View File

@ -55,6 +55,7 @@ import org.keycloak.common.ClientConnection;
import org.keycloak.common.Profile;
import org.keycloak.common.VerificationException;
import org.keycloak.common.util.PemUtils;
import org.keycloak.email.EmailAuthenticator;
import org.keycloak.email.EmailTemplateProvider;
import org.keycloak.events.EventQuery;
import org.keycloak.events.EventStoreProvider;
@ -117,6 +118,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -1134,27 +1136,39 @@ public class RealmAdminResource {
@APIResponse(responseCode = "500", description = "Internal Server Error")
})
public Response testSMTPConnection(Map<String, String> settings) throws Exception {
auth.realm().requireManageRealm();
try {
UserModel user = auth.adminAuth().getUser();
if (user.getEmail() == null) {
throw ErrorResponse.error("Logged in user does not have an e-mail.", Response.Status.INTERNAL_SERVER_ERROR);
}
if (ComponentRepresentation.SECRET_VALUE.equals(settings.get("password"))) {
if (ComponentRepresentation.SECRET_VALUE.equals(settings.get("password"))
&& reuseConfiguredAuthenticationForSmtp(settings, EmailAuthenticator.AuthenticatorType.BASIC)) {
settings.put("password", realm.getSmtpConfig().get("password"));
}
if (ComponentRepresentation.SECRET_VALUE.equals(settings.get("authTokenClientSecret"))) {
if (ComponentRepresentation.SECRET_VALUE.equals(settings.get("authTokenClientSecret"))
&& reuseConfiguredAuthenticationForSmtp(settings, EmailAuthenticator.AuthenticatorType.TOKEN)) {
settings.put("authTokenClientSecret", realm.getSmtpConfig().get("authTokenClientSecret"));
}
session.getProvider(EmailTemplateProvider.class).sendSmtpTestEmail(settings, user);
} catch (Exception e) {
e.printStackTrace();
logger.errorf("Failed to send email \n %s", e.getCause());
logger.errorf(e, "Failed to send email \n %s", e.getCause());
throw ErrorResponse.error("Failed to send email", Response.Status.INTERNAL_SERVER_ERROR);
}
return Response.noContent().build();
}
private boolean reuseConfiguredAuthenticationForSmtp(Map<String, String> settings, EmailAuthenticator.AuthenticatorType type) {
// just reuse the configured authentication if the same authenticator, host, port and user are passed
return Boolean.parseBoolean(settings.get("auth")) && Boolean.parseBoolean(realm.getSmtpConfig().get("auth"))
&& settings.getOrDefault("authType", EmailAuthenticator.AuthenticatorType.BASIC.name()).equalsIgnoreCase(type.name())
&& realm.getSmtpConfig().getOrDefault("authType", EmailAuthenticator.AuthenticatorType.BASIC.name()).equalsIgnoreCase(type.name())
&& Objects.equals(settings.getOrDefault("host", ""), realm.getSmtpConfig().getOrDefault("host", ""))
&& Objects.equals(settings.getOrDefault("port", "25"), realm.getSmtpConfig().getOrDefault("port", "25"))
&& Objects.equals(settings.getOrDefault("user", ""), realm.getSmtpConfig().getOrDefault("user", ""));
}
@Path("identity-provider")
public IdentityProvidersResource getIdentityProviderResource() {
return new IdentityProvidersResource(realm, session, this.auth, adminEvent);

View File

@ -27,7 +27,6 @@ import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.Constants;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import jakarta.mail.internet.MimeMessage;
@ -123,6 +122,12 @@ public class SMTPConnectionTest {
Response response = realm.testSMTPConnection(settings("127.0.0.1", "3025", "auto@keycloak.org", "true", null, null,
"admin@localhost", SECRET_VALUE));
assertStatus(response, 204);
// no reuse password if the server is different (localhost) to the saved one (127.0.0.1)
mailServer.credentials("admin@localhost", password);
response = realm.testSMTPConnection(settings("localhost", "3025", "auto@keycloak.org", "true", null, null,
"admin@localhost", SECRET_VALUE));
assertStatus(response, 500);
}
@Test
@ -156,6 +161,10 @@ public class SMTPConnectionTest {
assertMailReceived();
assertEventsEmpty(realm);
// no reuse password if the server is different (localhost) to the saved one (127.0.0.1)
final var thirdResponse = realm.testSMTPConnection(settings("localhost", "3025", "auto@keycloak.org", "true", null, null,
"admin@localhost", keycloakUrls.getToken(managedRealm.getName()), "test-smtp-client-I", SECRET_VALUE, "basic"));
assertStatus(thirdResponse, 500);
}
@Test