|
|
@@ -17,16 +17,25 @@
|
|
|
package org.springframework.security.web.webauthn.authentication;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
|
|
|
import jakarta.servlet.ServletException;
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
|
+import org.jspecify.annotations.Nullable;
|
|
|
import tools.jackson.databind.json.JsonMapper;
|
|
|
|
|
|
import org.springframework.core.ResolvableType;
|
|
|
+import org.springframework.http.HttpInputMessage;
|
|
|
import org.springframework.http.HttpMethod;
|
|
|
+import org.springframework.http.HttpOutputMessage;
|
|
|
import org.springframework.http.HttpStatus;
|
|
|
+import org.springframework.http.MediaType;
|
|
|
+import org.springframework.http.converter.AbstractSmartHttpMessageConverter;
|
|
|
import org.springframework.http.converter.GenericHttpMessageConverter;
|
|
|
+import org.springframework.http.converter.HttpMessageNotReadableException;
|
|
|
+import org.springframework.http.converter.HttpMessageNotWritableException;
|
|
|
import org.springframework.http.converter.SmartHttpMessageConverter;
|
|
|
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
|
|
import org.springframework.http.server.ServletServerHttpRequest;
|
|
|
@@ -38,7 +47,6 @@ import org.springframework.security.web.authentication.AuthenticationEntryPointF
|
|
|
import org.springframework.security.web.authentication.HttpMessageConverterAuthenticationSuccessHandler;
|
|
|
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
|
|
|
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
|
|
-import org.springframework.security.web.http.GenericHttpMessageConverterAdapter;
|
|
|
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
|
|
|
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
|
|
|
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
|
|
|
@@ -74,8 +82,8 @@ import static org.springframework.security.web.servlet.util.matcher.PathPatternR
|
|
|
*/
|
|
|
public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
|
|
|
|
|
- private GenericHttpMessageConverter<Object> converter = new GenericHttpMessageConverterAdapter<>(
|
|
|
- new JacksonJsonHttpMessageConverter(JsonMapper.builder().addModule(new WebauthnJacksonModule()).build()));
|
|
|
+ private SmartHttpMessageConverter<Object> converter = new JacksonJsonHttpMessageConverter(
|
|
|
+ JsonMapper.builder().addModule(new WebauthnJacksonModule()).build());
|
|
|
|
|
|
private PublicKeyCredentialRequestOptionsRepository requestOptionsRepository = new HttpSessionPublicKeyCredentialRequestOptionsRepository();
|
|
|
|
|
|
@@ -96,7 +104,7 @@ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessi
|
|
|
PublicKeyCredential<AuthenticatorAssertionResponse> publicKeyCredential = null;
|
|
|
try {
|
|
|
publicKeyCredential = (PublicKeyCredential<AuthenticatorAssertionResponse>) this.converter
|
|
|
- .read(resolvableType.getType(), getClass(), httpRequest);
|
|
|
+ .read(resolvableType, httpRequest, null);
|
|
|
}
|
|
|
catch (Exception ex) {
|
|
|
throw new BadCredentialsException("Unable to authenticate the PublicKeyCredential", ex);
|
|
|
@@ -118,10 +126,12 @@ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessi
|
|
|
* {@code PublicKeyCredential<AuthenticatorAssertionResponse>} to the response. The
|
|
|
* default is @{code MappingJackson2HttpMessageConverter}
|
|
|
* @param converter the {@link GenericHttpMessageConverter} to use. Cannot be null.
|
|
|
+ * @deprecated use {@link #setConverter(SmartHttpMessageConverter)}
|
|
|
*/
|
|
|
+ @Deprecated(forRemoval = true, since = "7.0")
|
|
|
public void setConverter(GenericHttpMessageConverter<Object> converter) {
|
|
|
Assert.notNull(converter, "converter cannot be null");
|
|
|
- this.converter = converter;
|
|
|
+ this.converter = new GenericHttpMessageConverterAdapter<>(converter);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -133,7 +143,7 @@ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessi
|
|
|
*/
|
|
|
public void setConverter(SmartHttpMessageConverter<Object> converter) {
|
|
|
Assert.notNull(converter, "converter cannot be null");
|
|
|
- this.converter = new GenericHttpMessageConverterAdapter<>(converter);
|
|
|
+ this.converter = converter;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -147,4 +157,55 @@ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessi
|
|
|
this.requestOptionsRepository = requestOptionsRepository;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Adapts a {@link GenericHttpMessageConverter} to a
|
|
|
+ * {@link SmartHttpMessageConverter}.
|
|
|
+ *
|
|
|
+ * @param <T> The type
|
|
|
+ * @author Rob Winch
|
|
|
+ * @since 7.0
|
|
|
+ */
|
|
|
+ private static final class GenericHttpMessageConverterAdapter<T> extends AbstractSmartHttpMessageConverter<T> {
|
|
|
+
|
|
|
+ private final GenericHttpMessageConverter<T> delegate;
|
|
|
+
|
|
|
+ private GenericHttpMessageConverterAdapter(GenericHttpMessageConverter<T> delegate) {
|
|
|
+ Assert.notNull(delegate, "delegate cannot be null");
|
|
|
+ this.delegate = delegate;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean canRead(Class<?> clazz, @Nullable MediaType mediaType) {
|
|
|
+ return this.delegate.canRead(clazz, mediaType);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
|
|
|
+ return this.delegate.canWrite(clazz, mediaType);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<MediaType> getSupportedMediaTypes() {
|
|
|
+ return this.delegate.getSupportedMediaTypes();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<MediaType> getSupportedMediaTypes(Class<?> clazz) {
|
|
|
+ return this.delegate.getSupportedMediaTypes(clazz);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void writeInternal(T t, ResolvableType type, HttpOutputMessage outputMessage,
|
|
|
+ @Nullable Map<String, Object> hints) throws IOException, HttpMessageNotWritableException {
|
|
|
+ this.delegate.write(t, null, outputMessage);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T read(ResolvableType type, HttpInputMessage inputMessage, @Nullable Map<String, Object> hints)
|
|
|
+ throws IOException, HttpMessageNotReadableException {
|
|
|
+ return this.delegate.read(type.getType(), null, inputMessage);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|