From 61bccb005a675bda276fd299dce906d879a6d96b Mon Sep 17 00:00:00 2001 From: Viacheslav Klimov Date: Tue, 17 Mar 2026 11:35:30 +0200 Subject: [PATCH] Restore runtime SSRF validation in CustomOAuth2ClientMapper Keep both save-time validation (Oauth2ClientDataValidator) and runtime re-validation as defense-in-depth: DNS records can change between config save and OAuth2 login, creating a TOCTOU gap. --- .../security/auth/oauth2/CustomOAuth2ClientMapper.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java index 8477c69a99..97d24b8601 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java @@ -23,12 +23,15 @@ import org.springframework.security.oauth2.client.authentication.OAuth2Authentic import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.common.util.SsrfProtectionValidator; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig; import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; import org.thingsboard.server.common.data.oauth2.OAuth2Client; import org.thingsboard.server.dao.oauth2.OAuth2User; import org.thingsboard.server.queue.util.TbCoreComponent; + +import java.net.URI; import org.thingsboard.server.service.security.model.SecurityUser; @Service(value = "customOAuth2ClientMapper") @@ -64,6 +67,7 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme throw new RuntimeException("Can't convert principal to JSON string", e); } try { + SsrfProtectionValidator.validateUri(new URI(custom.getUrl())); return restTemplate.postForEntity(custom.getUrl(), request, OAuth2User.class).getBody(); } catch (Exception e) { log.error("There was an error during connection to custom mapper endpoint", e);