Updated SAML config
This commit is contained in:
@@ -41,6 +41,10 @@ import org.springframework.security.saml2.provider.service.web.DefaultRelyingPar
|
|||||||
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
|
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
|
||||||
import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
|
import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
|
||||||
import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver;
|
import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class SamlConfig {
|
public class SamlConfig {
|
||||||
@@ -123,28 +127,34 @@ public class SamlConfig {
|
|||||||
return authnRequest;
|
return authnRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) {
|
public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) {
|
||||||
RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations);
|
RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations);
|
||||||
OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver);
|
OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver);
|
||||||
|
|
||||||
authenticationRequestResolver.setAuthnRequestCustomizer((context) -> {
|
authenticationRequestResolver.setAuthnRequestCustomizer((context) -> {
|
||||||
// Set the required attributes
|
|
||||||
AuthnRequest authnRequest = context.getAuthnRequest();
|
|
||||||
authnRequest.setID("_" + UUID.randomUUID().toString()); // Add a unique ID
|
|
||||||
authnRequest.setVersion(SAMLVersion.VERSION_20); // Ensure version is 2.0
|
|
||||||
authnRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI); // HTTP-POST
|
|
||||||
|
|
||||||
// Set Authentication Context
|
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
|
||||||
authnRequest.setRequestedAuthnContext(buildRequestedAuthnContext());
|
String hubId = (String) request.getAttribute("hubId");
|
||||||
|
|
||||||
// Log the SAML AuthnRequest after setting context
|
logger.info("Hub id " + hubId);
|
||||||
String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest);
|
|
||||||
logger.info("SAML AuthnRequest after setting context: " + samlRequest);
|
// Continue with normal AuthnRequest configuration
|
||||||
});
|
AuthnRequest authnRequest = context.getAuthnRequest();
|
||||||
|
authnRequest.setID("_" + UUID.randomUUID().toString()+":"+hubId);
|
||||||
|
authnRequest.setVersion(SAMLVersion.VERSION_20);
|
||||||
|
authnRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI);
|
||||||
|
authnRequest.setRequestedAuthnContext(buildRequestedAuthnContext());
|
||||||
|
|
||||||
|
|
||||||
|
// Log the SAML AuthnRequest after setting context
|
||||||
|
String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest);
|
||||||
|
logger.info("SAML AuthnRequest after setting context: " + samlRequest);
|
||||||
|
});
|
||||||
|
|
||||||
|
return authenticationRequestResolver;
|
||||||
|
}
|
||||||
|
|
||||||
return authenticationRequestResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RequestedAuthnContext buildRequestedAuthnContext() {
|
private RequestedAuthnContext buildRequestedAuthnContext() {
|
||||||
AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder();
|
AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder();
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package net.gepafin.tendermanagement.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class SamlRequestFilter extends OncePerRequestFilter {
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
String hub = request.getParameter("hubId");
|
||||||
|
if (hub != null) {
|
||||||
|
request.setAttribute("hubId", hub); // Store the hub ID as an attribute
|
||||||
|
}
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
package net.gepafin.tendermanagement.config;
|
package net.gepafin.tendermanagement.config;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -13,6 +18,8 @@ import org.springframework.security.saml2.provider.service.authentication.Saml2A
|
|||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
@@ -62,6 +69,27 @@ public class SamlSuccessHandler implements AuthenticationSuccessHandler {
|
|||||||
samlResponseLogEntity.setToken(token);
|
samlResponseLogEntity.setToken(token);
|
||||||
samlResponseLogRepository.save(samlResponseLogEntity);
|
samlResponseLogRepository.save(samlResponseLogEntity);
|
||||||
|
|
||||||
|
|
||||||
|
// Extracting raw SAML response
|
||||||
|
String samlResponse = samlAuth.getSaml2Response();
|
||||||
|
logger.info("Raw SAML Response: " + samlResponse);
|
||||||
|
|
||||||
|
// Parsing the SAML response as XML
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
|
factory.setNamespaceAware(true);
|
||||||
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||||
|
Document document = builder.parse(new ByteArrayInputStream(Base64.getDecoder().decode(samlResponse)));
|
||||||
|
|
||||||
|
// Extracting ID, InResponseTo, and IssueInstant from the Response element
|
||||||
|
Element responseElement = (Element) document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:protocol", "Response").item(0);
|
||||||
|
String responseId = responseElement.getAttribute("ID");
|
||||||
|
String inResponseTo = responseElement.getAttribute("InResponseTo");
|
||||||
|
String issueInstant = responseElement.getAttribute("IssueInstant");
|
||||||
|
|
||||||
|
logger.info("SAML Response ID: " + responseId);
|
||||||
|
logger.info("InResponseTo: " + inResponseTo);
|
||||||
|
logger.info("IssueInstant: " + issueInstant);
|
||||||
|
|
||||||
String redirectUrl = feBaseUrl;
|
String redirectUrl = feBaseUrl;
|
||||||
|
|
||||||
logger.info("SAML login successful for user: " + principal.getName());
|
logger.info("SAML login successful for user: " + principal.getName());
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt
|
|||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.saml2.provider.service.web.Saml2WebSsoAuthenticationRequestFilter;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
||||||
@@ -109,23 +110,19 @@ public class SecurityConfig {
|
|||||||
.requestMatchers("/v1/user/reset-password/initiate").permitAll()
|
.requestMatchers("/v1/user/reset-password/initiate").permitAll()
|
||||||
.requestMatchers("/v1/user/reset-password").permitAll()
|
.requestMatchers("/v1/user/reset-password").permitAll()
|
||||||
.anyRequest().authenticated())
|
.anyRequest().authenticated())
|
||||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
|
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
|
||||||
.exceptionHandling(exceptionHandling -> exceptionHandling
|
.exceptionHandling(exceptionHandling -> exceptionHandling
|
||||||
.authenticationEntryPoint((request, response, authException) -> {
|
.authenticationEntryPoint((request, response, authException) -> {
|
||||||
// Send 403 Forbidden when there is no JWT token provided
|
// Send 403 Forbidden when there is no JWT token provided
|
||||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden: Authentication token is missing or invalid");
|
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden: Authentication token is missing or invalid");
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class)
|
.addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class)
|
||||||
.addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class)
|
.addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class)
|
||||||
// Add SAML2 login configuration (for BENEFICIARI)
|
.addFilterBefore(new SamlRequestFilter(), Saml2WebSsoAuthenticationRequestFilter.class) // Add the custom SAML filter
|
||||||
/*
|
.saml2Login(saml -> saml.defaultSuccessUrl("/")
|
||||||
* .saml2Login(saml -> saml.loginPage("/saml/login") // Entry point for SAML
|
.successHandler(samlSuccessHandler)
|
||||||
* login .defaultSuccessUrl("/") // Redirect after successful SAML login );
|
.failureHandler(samlFailureHandler));
|
||||||
*/
|
|
||||||
.saml2Login(saml -> saml.defaultSuccessUrl("/").successHandler(samlSuccessHandler)
|
|
||||||
.failureHandler(samlFailureHandler));
|
|
||||||
|
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user