-
Notifications
You must be signed in to change notification settings - Fork 6k
SAML Saml2WebSsoAuthenticationFilter SHOULD wrap AuthenticationConverter convert exception to AuthenticationException #9310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks, @GitHanter, for the suggestion. Can you elaborate on what problems you are experiencing from the code the way that it is? The reason I ask is that it's probably a bit too aggressive to state that any exception from |
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed. |
Because the @Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
@SuppressWarnings("unchecked")
protected void configure(HttpSecurity http) throws Exception {
//make all exception thrown from Saml2WebSsoAuthenticationFilter AuthenticationException, so the
//AuthenticationFailureHandler will take over control
ObjectPostProcessor<Saml2WebSsoAuthenticationFilter> objectPostProcessor = new ObjectPostProcessor<Saml2WebSsoAuthenticationFilter>() {
@Override
public <O extends Saml2WebSsoAuthenticationFilter> O postProcess(O object) {
Field field = ReflectionUtils.findField(Saml2WebSsoAuthenticationFilter.class, "authenticationConverter");
ReflectionUtils.makeAccessible(Objects.requireNonNull(field));
Saml2AuthenticationTokenConverter originalConverter = (Saml2AuthenticationTokenConverter) ReflectionUtils.getField(field, object);
AuthenticationConverter decorator = (request) -> {
try {
return Objects.requireNonNull(originalConverter).convert(request);
} catch (AuthenticationException ex) {
throw ex;
} catch (Exception ex) {
throw new Saml2AuthenticationException(new Saml2Error(SAML_SSO_INTERNAL_ERROR, ex.getMessage()), ex);
}
};
ReflectionUtils.setField(field, object, decorator);
return object;
}
};
} |
Thanks for the extra detail, @GitHanter. I wonder if the following would be simpler: AuthenticationConverter converter = new Saml2AuthenticationTokenConverter(...);
http
.saml2Login((saml2) -> saml2
.authenticationConverter(new MyExceptionWrappingAuthenticationConverter(converter))
); Would that work to remove the reflection? It may be valuable to change To better understand the right error code, under what circumstances are you getting an exception? Specifically, we need to be clear whether errors are the client's fault or the server's fault. |
@jzheaux For @Override
public UsernamePasswordAuthenticationToken convert(HttpServletRequest request) {
String header = request.getHeader(AUTHORIZATION);
if (header == null) {
return null;
}
header = header.trim();
if (!StringUtils.startsWithIgnoreCase(header, AUTHENTICATION_SCHEME_BASIC)) {
return null;
}
byte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);
byte[] decoded;
try {
decoded = Base64.getDecoder().decode(base64Token);
}
catch (IllegalArgumentException e) {
throw new BadCredentialsException(
"Failed to decode basic authentication token");
}
String token = new String(decoded, getCredentialsCharset(request));
int delim = token.indexOf(":");
if (delim == -1) {
throw new BadCredentialsException("Invalid basic authentication token");
}
UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(token.substring(0, delim), token.substring(delim + 1));
result.setDetails(this.authenticationDetailsSource.buildDetails(request));
return result;
} For @Override
public Saml2AuthenticationToken convert(HttpServletRequest request) {
RelyingPartyRegistration relyingPartyRegistration = this.relyingPartyRegistrationResolver.convert(request);
if (relyingPartyRegistration == null) {
return null;
}
String saml2Response = request.getParameter("SAMLResponse");
if (saml2Response == null) {
return null;
}
byte[] b = samlDecode(saml2Response);
saml2Response = inflateIfRequired(request, b);
return new Saml2AuthenticationToken(relyingPartyRegistration, saml2Response);
}
private String inflateIfRequired(HttpServletRequest request, byte[] b) {
if (HttpMethod.GET.matches(request.getMethod())) {
return samlInflate(b);
}
return new String(b, StandardCharsets.UTF_8);
}
private byte[] samlDecode(String s) {
return BASE64.decode(s);
} If |
Sounds great, @GitHanter. Would you be able to submit a PR that wraps the deflation and decoding and throws a It would be great to include some tests: First, in |
Sounds good, @GitHanter. In that case, please make sure that the two changes are in separate commits as this simplifies maintenance. |
…eption and inflate exception to Saml2AuthenticationException Update copyright year to 2021 Closes spring-projectsgh-9310
Saml2WebSsoAuthenticationFilter
doesn't catchAuthenticationConverter
convert exception, we should wrapper the exception as aSaml2AuthenticationException(Saml2ErrorCodes.INTERNAL_VALIDATION_ERROR, ex.getMessage(), ex)
.May be we can add a configure method to
Saml2LoginConfigurer
to configure propertyauthenticationConverter
ofSaml2WebSsoAuthenticationFilter
, e.g throughgetSharedOrBean
so that developer can customize it as a BeanThe text was updated successfully, but these errors were encountered: