Open tyleragnew opened 5 years ago
Having the same problem. What was the solution?
To be investigated.
Hi @tyleragnew. I will soon work to replicate it, but if you already have more info about, could you please share with us the details?
Hi all - I ended up signing with SHA-1 on the IDP side - so this did fix the issue. Understood that this would not fix the issue if you don't control your IDP though...
Hi. Same problem on my side. Any news on this?
Hi Any updates on this issue.
The IDP provider is reluctant to change to SHA1 and even after changing the signing and messageDigest algorithm to SHA256 the requests from SP are sent with SHA1
SHA 256 should definitely be used. Security ;)
I got it working.
@garrit-schroeder
SHA 256 should definitely be used. Security ;)
I got it working.
@garrit-schroeder Can you help please
Sure i am preparing my conf. Hang on
Saml Security Java File:
`@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true) public class SamlSecurity extends SAMLWebSecurityConfigurerAdapter {
private final SAMLUserDetailsServiceImpl userDetailsService;
private final MemoryUserDetailsServiceImpl memoryUserDetailsService;
private String serverName;
private int serverPort;
@Bean
public AccessDeniedHandler accessDeniedHandler() {
return new CustomAccessDeniedHandler();
}
@Autowired
public SamlSecurity(@Value("${project.saml.server.name}") String serverName, @Value("${project.saml.server.port}")
int serverPort, SAMLUserDetailsServiceImpl userDetailsService, MemoryUserDetailsServiceImpl memoryUserDetailsService) {
this.serverName = serverName;
this.serverPort = serverPort;
this.userDetailsService = userDetailsService;
this.memoryUserDetailsService = memoryUserDetailsService;
}
// See `SAMLConfigBean Properties` section below for more info.
@Override
protected SAMLConfigBean samlConfigBean() {
return new SAMLConfigBeanBuilder()
.withIdpServerName("path_xml_of_idp.xml")
.withSpServerName(serverName)
.withSpHttpsPort(serverPort)
.withKeystoreResource(new DefaultResourceLoader().getResource("classpath:/saml/samlKeystore.jks"))
.withKeystorePassword("XX1XX")
.withKeystoreAlias("saml_key")
.withKeystorePrivateKeyPassword("XX1XX")
.withSuccessLoginDefaultUrl("X")
.withSuccessLogoutUrl("X")
.withFailedLoginDefaultUrl("X")
.withStoreCsrfTokenInCookie(true)
.withSamlUserDetailsService(userDetailsService)
.withAuthnContexts(authenticationContexts())
.build();
}
private Set<String> authenticationContexts() {
Set<String> context = new HashSet<>();
context.add(CustomAuthnContext.WINDOWS_INTEGRATED_AUTHN_CTX);
context.add(AuthnContext.PASSWORD_AUTHN_CTX);
return context;
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
samlizedConfig(http)
.authorizeRequests()
.antMatchers("X").permitAll()
.antMatchers("X")
.hasAnyAuthority(Authority.X)
.antMatchers("X")
.hasAuthority(Authority.Y)
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("X")
.failureUrl("X")
.usernameParameter("username")
.passwordParameter("password")
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler()).and()
.httpBasic().and()
.csrf().ignoringAntMatchers("/X");
}
@Override
public void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(samlAuthenticationProvider());
auth.userDetailsService(memoryUserDetailsService);
}
// call samlizedConfig(web) first to decorate web with SAML configuration
// before configuring app specific web security
@Override
public void configure(final WebSecurity web) throws Exception {
samlizedConfig(web).ignoring().antMatchers("static stuff");
}
}`
SAML Detail Service:
`
@Service public class SAMLUserDetailsServiceImpl extends X implements SAMLUserDetailsService {
public SAMLUserDetailsServiceImpl(X x) {
super(x);
}
public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException {
try {
String email = credential.getAttributeAsString("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").trim();
String firstName = credential.getAttributeAsString("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname").trim();
String lastName = credential.getAttributeAsString("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname").trim();
return a org.springframework.security.core.userdetails.User;
} catch (Exception e) {
Logger.info("saml login error: " + e.getMessage());
throw new UsernameNotFoundException(e.getMessage(), e);
}
}
}
`
Create SAML Keystore: under ./resources/saml/ for example:
`
KS_FILE=samlKeystore.jks KS_PASS=XX KS_KEY_PAIR_NAME=saml_key IDP_HOST=XX IDP_PORT=443 CERTIFICATE_FILE=file.cert
rm $KS_FILE echo "deleted old key store" keytool -genkeypair -v -keystore $KS_FILE -storepass $KS_PASS -alias $KS_KEY_PAIR_NAME -dname 'CN=test, OU=test, O=test, L=test, ST=test, C=test' -keypass $KS_PASS -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 3650 echo "created store with saml key pair" openssl s_client -host $IDP_HOST -port $IDP_PORT -prexit -showcerts </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > $CERTIFICATE_FILE echo "downloaded new adfs certificate" keytool -import -alias adfs -file $CERTIFICATE_FILE -keystore $KS_FILE -storepass $KS_PASS -noprompt echo "imported new adfs certificate" rm $CERTIFICATE_FILE echo "removed downloaded certificate file" `
In a @ControllerAdvice class i provide the following:
@Autowired
private MetadataManager metadata;
@Controller public void blabla(){ model.put("saml_id", metadata.getHostedSPName()); }
Thats all. I am not setting up metadata or anything else
Your host should now show your certs under http://example.com/saml/metadata
Saml Security Java File:
`@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true) public class SamlSecurity extends SAMLWebSecurityConfigurerAdapter {
private final SAMLUserDetailsServiceImpl userDetailsService; private final MemoryUserDetailsServiceImpl memoryUserDetailsService; private String serverName; private int serverPort; @Bean public AccessDeniedHandler accessDeniedHandler() { return new CustomAccessDeniedHandler(); } @Autowired public SamlSecurity(@Value("${project.saml.server.name}") String serverName, @Value("${project.saml.server.port}") int serverPort, SAMLUserDetailsServiceImpl userDetailsService, MemoryUserDetailsServiceImpl memoryUserDetailsService) { this.serverName = serverName; this.serverPort = serverPort; this.userDetailsService = userDetailsService; this.memoryUserDetailsService = memoryUserDetailsService; } // See `SAMLConfigBean Properties` section below for more info. @Override protected SAMLConfigBean samlConfigBean() { return new SAMLConfigBeanBuilder() .withIdpServerName("path_xml_of_idp.xml") .withSpServerName(serverName) .withSpHttpsPort(serverPort) .withKeystoreResource(new DefaultResourceLoader().getResource("classpath:/saml/samlKeystore.jks")) .withKeystorePassword("XX1XX") .withKeystoreAlias("saml_key") .withKeystorePrivateKeyPassword("XX1XX") .withSuccessLoginDefaultUrl("X") .withSuccessLogoutUrl("X") .withFailedLoginDefaultUrl("X") .withStoreCsrfTokenInCookie(true) .withSamlUserDetailsService(userDetailsService) .withAuthnContexts(authenticationContexts()) .build(); } private Set<String> authenticationContexts() { Set<String> context = new HashSet<>(); context.add(CustomAuthnContext.WINDOWS_INTEGRATED_AUTHN_CTX); context.add(AuthnContext.PASSWORD_AUTHN_CTX); return context; } @Override protected void configure(final HttpSecurity http) throws Exception { samlizedConfig(http) .authorizeRequests() .antMatchers("X").permitAll() .antMatchers("X") .hasAnyAuthority(Authority.X) .antMatchers("X") .hasAuthority(Authority.Y) .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("X") .failureUrl("X") .usernameParameter("username") .passwordParameter("password") .and() .exceptionHandling().accessDeniedHandler(accessDeniedHandler()).and() .httpBasic().and() .csrf().ignoringAntMatchers("/X"); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(samlAuthenticationProvider()); auth.userDetailsService(memoryUserDetailsService); } // call samlizedConfig(web) first to decorate web with SAML configuration // before configuring app specific web security @Override public void configure(final WebSecurity web) throws Exception { samlizedConfig(web).ignoring().antMatchers("static stuff"); }
}`
Important is that you specify the correct server name and port. These should appear in your /saml/metadata
I hope that helps you. I you have further questions. Don't hesitate to ask me.
Sorry folks, I very appreciate your passion, but this is not the right way to manage an issue. The code that have been posted does not iron out the case, but just reflect how to setup custom IdP in Spring SAML.
As stated by @tyleragnew, the SHA mismatch depends on the IdP configuration. In SAML-based authentication, IdP and SP need to agree on the cipher suite when establishing the trust relationship (see https://en.wikipedia.org/wiki/SAML_metadata).
If you run this application against a SHA-256 enabled Identity Provider, everything works accordingly (see: https://docs.spring.io/autorepo/docs/spring-security-saml/1.0.x-SNAPSHOT/reference/htmlsingle/).
Note: the issue is still open just because NO secure application must still rely on SHA-1, since it has been proved to be weak at collision attacks.
Describe the bug Unable to sign with SHA-256, even updating signingAlgorithm keeps it as SHA-1
To Reproduce
Where I'm updating signingAlgorithm
Error Response