Saml2WebSsoAuthenticationFilter adds authentication details
Closes gh-7722
This commit is contained in:
parent
84d173c310
commit
2fb8e66bc8
|
@ -19,6 +19,7 @@ package org.springframework.security.saml2.provider.service.servlet.filter;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.saml2.core.Saml2Error;
|
import org.springframework.security.saml2.core.Saml2Error;
|
||||||
|
@ -109,6 +110,7 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce
|
||||||
"No relying party registration found");
|
"No relying party registration found");
|
||||||
throw new Saml2AuthenticationException(saml2Error);
|
throw new Saml2AuthenticationException(saml2Error);
|
||||||
}
|
}
|
||||||
|
setDetails(request, authentication);
|
||||||
this.authenticationRequestRepository.removeAuthenticationRequest(request, response);
|
this.authenticationRequestRepository.removeAuthenticationRequest(request, response);
|
||||||
return getAuthenticationManager().authenticate(authentication);
|
return getAuthenticationManager().authenticate(authentication);
|
||||||
}
|
}
|
||||||
|
@ -138,4 +140,11 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setDetails(HttpServletRequest request, Authentication authentication) {
|
||||||
|
if (AbstractAuthenticationToken.class.isAssignableFrom(authentication.getClass())) {
|
||||||
|
Object details = this.authenticationDetailsSource.buildDetails(request);
|
||||||
|
((AbstractAuthenticationToken) authentication).setDetails(details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,7 +446,12 @@ public final class OpenSaml4AuthenticationProvider implements AuthenticationProv
|
||||||
String serializedResponse = token.getSaml2Response();
|
String serializedResponse = token.getSaml2Response();
|
||||||
Response response = parse(serializedResponse);
|
Response response = parse(serializedResponse);
|
||||||
process(token, response);
|
process(token, response);
|
||||||
return this.responseAuthenticationConverter.convert(new ResponseToken(response, token));
|
AbstractAuthenticationToken authenticationResponse = this.responseAuthenticationConverter
|
||||||
|
.convert(new ResponseToken(response, token));
|
||||||
|
if (authenticationResponse != null) {
|
||||||
|
authenticationResponse.setDetails(authentication.getDetails());
|
||||||
|
}
|
||||||
|
return authenticationResponse;
|
||||||
}
|
}
|
||||||
catch (Saml2AuthenticationException ex) {
|
catch (Saml2AuthenticationException ex) {
|
||||||
throw ex;
|
throw ex;
|
||||||
|
|
|
@ -352,6 +352,21 @@ public class OpenSaml4AuthenticationProviderTests {
|
||||||
.satisfies(errorOf(Saml2ErrorCodes.DECRYPTION_ERROR, "Failed to decrypt EncryptedData"));
|
.satisfies(errorOf(Saml2ErrorCodes.DECRYPTION_ERROR, "Failed to decrypt EncryptedData"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void authenticateWhenAuthenticationHasDetailsThenSucceeds() {
|
||||||
|
Response response = response();
|
||||||
|
Assertion assertion = assertion();
|
||||||
|
assertion.getSubject().getSubjectConfirmations()
|
||||||
|
.forEach((sc) -> sc.getSubjectConfirmationData().setAddress("10.10.10.10"));
|
||||||
|
TestOpenSamlObjects.signed(assertion, TestSaml2X509Credentials.assertingPartySigningCredential(),
|
||||||
|
RELYING_PARTY_ENTITY_ID);
|
||||||
|
response.getAssertions().add(assertion);
|
||||||
|
Saml2AuthenticationToken token = token(response, verifying(registration()));
|
||||||
|
token.setDetails("some-details");
|
||||||
|
Authentication authentication = this.provider.authenticate(token);
|
||||||
|
assertThat(authentication.getDetails()).isEqualTo("some-details");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void writeObjectWhenTypeIsSaml2AuthenticationThenNoException() throws IOException {
|
public void writeObjectWhenTypeIsSaml2AuthenticationThenNoException() throws IOException {
|
||||||
Response response = response();
|
Response response = response();
|
||||||
|
|
|
@ -25,12 +25,14 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.mock.web.MockFilterChain;
|
import org.springframework.mock.web.MockFilterChain;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.saml2.core.Saml2ParameterNames;
|
import org.springframework.security.saml2.core.Saml2ParameterNames;
|
||||||
import org.springframework.security.saml2.provider.service.authentication.AbstractSaml2AuthenticationRequest;
|
import org.springframework.security.saml2.provider.service.authentication.AbstractSaml2AuthenticationRequest;
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||||
|
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationToken;
|
||||||
import org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationTokens;
|
import org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationTokens;
|
||||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
||||||
|
@ -40,11 +42,13 @@ 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.Saml2AuthenticationTokenConverter;
|
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter;
|
||||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||||
|
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatNoException;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
@ -119,6 +123,36 @@ public class Saml2WebSsoAuthenticationFilterTests {
|
||||||
verify(authenticationRequestRepository).removeAuthenticationRequest(this.request, this.response);
|
verify(authenticationRequestRepository).removeAuthenticationRequest(this.request, this.response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void attemptAuthenticationAddsDetails() {
|
||||||
|
AuthenticationConverter authenticationConverter = mock(AuthenticationConverter.class);
|
||||||
|
final Saml2AuthenticationToken token = TestSaml2AuthenticationTokens.token();
|
||||||
|
given(authenticationConverter.convert(this.request)).willReturn(token);
|
||||||
|
final AuthenticationDetailsSource authenticationDetailsSource = mock(AuthenticationDetailsSource.class);
|
||||||
|
final WebAuthenticationDetails details = mock(WebAuthenticationDetails.class);
|
||||||
|
given(authenticationDetailsSource.buildDetails(this.request)).willReturn(details);
|
||||||
|
this.filter = new Saml2WebSsoAuthenticationFilter(authenticationConverter, "/some/other/path/{registrationId}");
|
||||||
|
this.filter.setAuthenticationManager((authentication) -> null);
|
||||||
|
this.filter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||||
|
this.request.setPathInfo("/some/other/path/idp-registration-id");
|
||||||
|
this.filter.attemptAuthentication(this.request, this.response);
|
||||||
|
Assertions.assertEquals(details, token.getDetails());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void attemptAuthenticationWhenAuthenticationNotAbstractAuthenticationTokenDoesNotAddDetails() {
|
||||||
|
AuthenticationConverter authenticationConverter = mock(AuthenticationConverter.class);
|
||||||
|
final Authentication authenticationWithoutDetails = mock(Authentication.class);
|
||||||
|
given(authenticationConverter.convert(this.request)).willReturn(authenticationWithoutDetails);
|
||||||
|
final AuthenticationDetailsSource authenticationDetailsSource = mock(AuthenticationDetailsSource.class);
|
||||||
|
this.filter = new Saml2WebSsoAuthenticationFilter(authenticationConverter, "/some/other/path/{registrationId}");
|
||||||
|
this.filter.setAuthenticationManager((authentication) -> null);
|
||||||
|
this.filter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||||
|
this.request.setPathInfo("/some/other/path/idp-registration-id");
|
||||||
|
assertThatNoException().isThrownBy(() -> this.filter.attemptAuthentication(this.request, this.response));
|
||||||
|
verifyNoInteractions(authenticationDetailsSource);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setAuthenticationRequestRepositoryWhenNullThenThrowsIllegalArgument() {
|
public void setAuthenticationRequestRepositoryWhenNullThenThrowsIllegalArgument() {
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setAuthenticationRequestRepository(null))
|
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setAuthenticationRequestRepository(null))
|
||||||
|
|
Loading…
Reference in New Issue