Skip to content

Commit c6d0629

Browse files
committed
feat(saml): enhance SAML2 login success handling with improved user not found logging and provider reloading
1 parent 8d45e5b commit c6d0629

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

backend/src/main/java/com/park/utmstack/config/saml/SamlRelyingPartyRegistrationRepository.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
@Slf4j
1515
public class SamlRelyingPartyRegistrationRepository implements RelyingPartyRegistrationRepository {
1616

17-
private final Map<String, RelyingPartyRegistration> registrations = new ConcurrentHashMap<>();
17+
private volatile Map<String, RelyingPartyRegistration> registrations = new ConcurrentHashMap<>();
1818
private final SamlProvidersLoader providersLoader;
1919

2020
public SamlRelyingPartyRegistrationRepository(IdentityProviderConfigRepository jpaProviderRepository) {
@@ -24,7 +24,6 @@ public SamlRelyingPartyRegistrationRepository(IdentityProviderConfigRepository j
2424
SamlRegistrationBuilder registrationBuilder = new SamlRegistrationBuilder(encryptionKey, metadataFetcher);
2525
this.providersLoader = new SamlProvidersLoader(registrationBuilder);
2626

27-
// Load providers on initialization
2827
loadProviders(jpaProviderRepository);
2928
}
3029

@@ -34,22 +33,30 @@ public RelyingPartyRegistration findByRegistrationId(String registrationId) {
3433
}
3534

3635
public void reloadProviders(IdentityProviderConfigRepository jpaProviderRepository) {
37-
registrations.clear();
38-
loadProviders(jpaProviderRepository);
36+
try {
37+
registrations = loadActiveProviders(jpaProviderRepository);
38+
log.info("SAML providers reloaded successfully: {} providers loaded", registrations.size());
39+
} catch (Exception e) {
40+
log.error("Failed to reload SAML providers - keeping previous configuration", e);
41+
}
3942
}
4043

4144
/**
4245
* Loads SAML providers using the specialized loader.
4346
* Delegates all async loading logic to SamlProvidersLoader.
47+
* App will start without providers if loading fails.
4448
*/
4549
private void loadProviders(IdentityProviderConfigRepository jpaProviderRepository) {
4650
try {
47-
List<IdentityProviderConfig> activeProviders = jpaProviderRepository.findAllByActiveTrue();
48-
Map<String, RelyingPartyRegistration> loadedRegistrations =
49-
providersLoader.loadProvidersAsync(activeProviders);
50-
registrations.putAll(loadedRegistrations);
51+
registrations = loadActiveProviders(jpaProviderRepository);
52+
if (registrations.isEmpty()) {
53+
log.warn("No active SAML2 providers found. SAML2 authentication will not be available.");
54+
} else {
55+
log.info("Successfully loaded {} SAML2 provider(s) on startup", registrations.size());
56+
}
5157
} catch (Exception e) {
52-
log.error("Error during SAML provider loading: {}", e.getMessage(), e);
58+
log.error("Error during SAML provider loading - app will start without SAML2 authentication: {}",
59+
e.getMessage(), e);
5360
}
5461
}
5562

@@ -68,4 +75,11 @@ private String getValidatedEncryptionKey() {
6875
return encryptionKey;
6976
}
7077

78+
private Map<String, RelyingPartyRegistration> loadActiveProviders(IdentityProviderConfigRepository repo) {
79+
List<IdentityProviderConfig> activeProviders = repo.findAllByActiveTrue();
80+
Map<String, RelyingPartyRegistration> loaded = providersLoader.loadProvidersAsync(activeProviders);
81+
return new ConcurrentHashMap<>(loaded);
82+
}
83+
84+
7185
}

backend/src/main/java/com/park/utmstack/security/saml/Saml2LoginSuccessHandler.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import org.springframework.security.core.authority.SimpleGrantedAuthority;
1313
import org.springframework.security.core.context.SecurityContextHolder;
1414
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
15-
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
1615
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
1716
import org.springframework.web.util.UriComponentsBuilder;
1817

@@ -22,9 +21,6 @@
2221
import java.net.URI;
2322
import java.util.Collection;
2423
import java.util.Objects;
25-
import java.util.Optional;
26-
27-
import static com.park.utmstack.config.Constants.FRONT_BASE_URL;
2824

2925
/**
3026
* Success handler for SAML2 login.
@@ -38,7 +34,6 @@ public class Saml2LoginSuccessHandler implements AuthenticationSuccessHandler {
3834

3935
private final TokenProvider tokenProvider;
4036
private final UserRepository userRepository;
41-
private final Saml2LoginFailureHandler failureHandler;
4237

4338

4439
@Override
@@ -48,14 +43,16 @@ public void onAuthenticationSuccess(HttpServletRequest request,
4843

4944
String scheme = Objects.requireNonNullElse(request.getHeader("X-Forwarded-Proto"), request.getScheme());
5045
String host = Objects.requireNonNullElse(request.getHeader("Host"), request.getServerName());
51-
5246
String frontBaseUrl = scheme + "://" + host;
5347

5448
Saml2AuthenticatedPrincipal samlUser = (Saml2AuthenticatedPrincipal) authentication.getPrincipal();
5549
String username = samlUser.getName();
5650

5751
User user = userRepository.findOneByLogin(username)
58-
.orElseThrow(() -> new BadCredentialsException("The provided credentials do not match any active user account."));
52+
.orElseThrow(() -> {
53+
log.warn("SAML2 authentication successful for '{}' but user not found in local database", username);
54+
return new BadCredentialsException("User not provisioned in local system");
55+
});
5956

6057
Collection<? extends GrantedAuthority> authorities = Objects.requireNonNull(user.getAuthorities())
6158
.stream()
@@ -75,6 +72,7 @@ public void onAuthenticationSuccess(HttpServletRequest request,
7572
.build()
7673
.toUri();
7774

75+
log.info("SAML2 login successful for user: {}", username);
7876
response.sendRedirect(redirectUri.toString());
7977
}
8078
}

0 commit comments

Comments
 (0)