1
0
mirror of synced 2026-05-22 21:33:16 +00:00

Add webauthn Jackson 3 support and deprecate Jackson 2 one

Since this module was already using the jackson sub-package for Jackson 2
support, both Jackson 2 and Jackson 3 support lives in the same subpackage
and the former package-private classes has been renamed with a Jackson2
qualifier.

See gh-17832
Signed-off-by: Sébastien Deleuze <sdeleuze@users.noreply.github.com>
This commit is contained in:
Sébastien Deleuze
2025-09-10 22:15:07 +02:00
committed by Rob Winch
parent 48854c3ac9
commit 702a177e25
80 changed files with 2504 additions and 191 deletions
+1
View File
@@ -15,6 +15,7 @@ dependencies {
optional 'org.springframework:spring-jdbc'
optional 'org.springframework:spring-tx'
optional 'tools.jackson.core:jackson-databind'
provided 'jakarta.servlet:jakarta.servlet-api'
@@ -22,13 +22,13 @@ import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -36,7 +36,7 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
import org.springframework.security.web.webauthn.jackson.WebauthnJackson2Module;
import org.springframework.security.web.webauthn.jackson.WebauthnJacksonModule;
import org.springframework.security.web.webauthn.management.ImmutablePublicKeyCredentialRequestOptionsRequest;
import org.springframework.security.web.webauthn.management.WebAuthnRelyingPartyOperations;
import org.springframework.util.Assert;
@@ -63,8 +63,8 @@ public class PublicKeyCredentialRequestOptionsFilter extends OncePerRequestFilte
private PublicKeyCredentialRequestOptionsRepository requestOptionsRepository = new HttpSessionPublicKeyCredentialRequestOptionsRepository();
private HttpMessageConverter<Object> converter = new MappingJackson2HttpMessageConverter(
Jackson2ObjectMapperBuilder.json().modules(new WebauthnJackson2Module()).build());
private HttpMessageConverter<Object> converter = new JacksonJsonHttpMessageConverter(
JsonMapper.builder().addModule(new WebauthnJacksonModule()).build());
/**
* Creates a new instance with the provided {@link WebAuthnRelyingPartyOperations}.
@@ -21,13 +21,14 @@ import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.core.ResolvableType;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.SmartHttpMessageConverter;
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
@@ -40,7 +41,7 @@ import org.springframework.security.web.context.HttpSessionSecurityContextReposi
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
import org.springframework.security.web.webauthn.jackson.WebauthnJackson2Module;
import org.springframework.security.web.webauthn.jackson.WebauthnJacksonModule;
import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest;
import org.springframework.util.Assert;
@@ -49,8 +50,7 @@ import static org.springframework.security.web.servlet.util.matcher.PathPatternR
/**
* Authenticates {@code PublicKeyCredential<AuthenticatorAssertionResponse>} that is
* parsed from the body of the {@link HttpServletRequest} using the
* {@link #setConverter(GenericHttpMessageConverter)}. An example request is provided
* below:
* {@link #setConverter(SmartHttpMessageConverter)}. An example request is provided below:
*
* <pre>
* {
@@ -72,8 +72,8 @@ import static org.springframework.security.web.servlet.util.matcher.PathPatternR
*/
public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private GenericHttpMessageConverter<Object> converter = new MappingJackson2HttpMessageConverter(
Jackson2ObjectMapperBuilder.json().modules(new WebauthnJackson2Module()).build());
private SmartHttpMessageConverter<Object> converter = new JacksonJsonHttpMessageConverter(
JsonMapper.builder().addModule(new WebauthnJacksonModule()).build());
private PublicKeyCredentialRequestOptionsRepository requestOptionsRepository = new HttpSessionPublicKeyCredentialRequestOptionsRepository();
@@ -94,7 +94,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);
@@ -114,10 +114,11 @@ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessi
/**
* Sets the {@link GenericHttpMessageConverter} to use for writing
* {@code PublicKeyCredential<AuthenticatorAssertionResponse>} to the response. The
* default is @{code MappingJackson2HttpMessageConverter}
* default is @{code Jackson2HttpMessageConverter}
* @param converter the {@link GenericHttpMessageConverter} to use. Cannot be null.
*/
public void setConverter(GenericHttpMessageConverter<Object> converter) {
// TODO Accept HttpMessageConverter
public void setConverter(SmartHttpMessageConverter<Object> converter) {
Assert.notNull(converter, "converter cannot be null");
this.converter = converter;
}
@@ -0,0 +1,37 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.AttestationConveyancePreference;
/**
* Jackson mixin for {@link AttestationConveyancePreference}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AttestationConveyancePreferenceMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonSerialize(using = AttestationConveyancePreferenceJackson2Serializer.class)
class AttestationConveyancePreferenceJackson2Mixin {
}
@@ -0,0 +1,50 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.AttestationConveyancePreference;
/**
* Jackson serializer for {@link AttestationConveyancePreference}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AttestationConveyancePreferenceSerializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class AttestationConveyancePreferenceJackson2Serializer extends StdSerializer<AttestationConveyancePreference> {
AttestationConveyancePreferenceJackson2Serializer() {
super(AttestationConveyancePreference.class);
}
@Override
public void serialize(AttestationConveyancePreference preference, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeString(preference.getValue());
}
}
@@ -16,7 +16,7 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.AttestationConveyancePreference;
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.AttestationConveyancePreference;
@@ -38,8 +37,8 @@ class AttestationConveyancePreferenceSerializer extends StdSerializer<Attestatio
}
@Override
public void serialize(AttestationConveyancePreference preference, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(AttestationConveyancePreference preference, JsonGenerator jgen, SerializationContext ctxt)
throws JacksonException {
jgen.writeString(preference.getValue());
}
@@ -0,0 +1,37 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
/**
* Jackson mixin for {@link AuthenticationExtensionsClientInputs}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticationExtensionsClientInputMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonSerialize(using = AuthenticationExtensionsClientInputJackson2Serializer.class)
class AuthenticationExtensionsClientInputJackson2Mixin {
}
@@ -0,0 +1,53 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInput;
/**
* Provides Jackson serialization of {@link AuthenticationExtensionsClientInput}.
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticationExtensionsClientInputSerializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class AuthenticationExtensionsClientInputJackson2Serializer extends StdSerializer<AuthenticationExtensionsClientInput> {
/**
* Creates a new instance.
*/
AuthenticationExtensionsClientInputJackson2Serializer() {
super(AuthenticationExtensionsClientInput.class);
}
@Override
public void serialize(AuthenticationExtensionsClientInput input, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeObjectField(input.getExtensionId(), input.getInput());
}
}
@@ -16,7 +16,7 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInput;
@@ -41,9 +40,9 @@ class AuthenticationExtensionsClientInputSerializer extends StdSerializer<Authen
}
@Override
public void serialize(AuthenticationExtensionsClientInput input, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeObjectField(input.getExtensionId(), input.getInput());
public void serialize(AuthenticationExtensionsClientInput input, JsonGenerator jgen, SerializationContext ctxt)
throws JacksonException {
jgen.writePOJOProperty(input.getExtensionId(), input.getInput());
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
/**
* Jackson mixin for {@link AuthenticationExtensionsClientInputs}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticationExtensionsClientInputsMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonSerialize(using = AuthenticationExtensionsClientInputsJackson2Serializer.class)
class AuthenticationExtensionsClientInputsJackson2Mixin {
}
@@ -0,0 +1,59 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInput;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
/**
* Provides Jackson serialization of {@link AuthenticationExtensionsClientInputs}.
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticationExtensionsClientInputsSerializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class AuthenticationExtensionsClientInputsJackson2Serializer
extends StdSerializer<AuthenticationExtensionsClientInputs> {
/**
* Creates a new instance.
*/
AuthenticationExtensionsClientInputsJackson2Serializer() {
super(AuthenticationExtensionsClientInputs.class);
}
@Override
public void serialize(AuthenticationExtensionsClientInputs inputs, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStartObject();
for (AuthenticationExtensionsClientInput input : inputs.getInputs()) {
jgen.writeObject(input);
}
jgen.writeEndObject();
}
}
@@ -16,7 +16,7 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInput;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
@@ -42,11 +41,11 @@ class AuthenticationExtensionsClientInputsSerializer extends StdSerializer<Authe
}
@Override
public void serialize(AuthenticationExtensionsClientInputs inputs, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(AuthenticationExtensionsClientInputs inputs, JsonGenerator jgen, SerializationContext ctxt)
throws JacksonException {
jgen.writeStartObject();
for (AuthenticationExtensionsClientInput input : inputs.getInputs()) {
jgen.writeObject(input);
jgen.writePOJO(input);
}
jgen.writeEndObject();
}
@@ -16,17 +16,16 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonParser;
import tools.jackson.core.JsonToken;
import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.deser.std.StdDeserializer;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutput;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
@@ -53,9 +52,9 @@ class AuthenticationExtensionsClientOutputsDeserializer extends StdDeserializer<
@Override
public AuthenticationExtensionsClientOutputs deserialize(JsonParser parser, DeserializationContext ctxt)
throws IOException, JacksonException {
throws JacksonException {
List<AuthenticationExtensionsClientOutput<?>> outputs = new ArrayList<>();
for (String key = parser.nextFieldName(); key != null; key = parser.nextFieldName()) {
for (String key = parser.nextName(); key != null; key = parser.nextName()) {
JsonToken startObject = parser.nextValue();
if (startObject != JsonToken.START_OBJECT) {
break;
@@ -0,0 +1,84 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutput;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
import org.springframework.security.web.webauthn.api.CredentialPropertiesOutput;
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientOutputs;
/**
* Provides Jackson deserialization of {@link AuthenticationExtensionsClientOutputs}.
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticationExtensionsClientOutputsDeserializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class AuthenticationExtensionsClientOutputsJackson2Deserializer
extends StdDeserializer<AuthenticationExtensionsClientOutputs> {
private static final Log logger = LogFactory
.getLog(AuthenticationExtensionsClientOutputsJackson2Deserializer.class);
/**
* Creates a new instance.
*/
AuthenticationExtensionsClientOutputsJackson2Deserializer() {
super(AuthenticationExtensionsClientOutputs.class);
}
@Override
public AuthenticationExtensionsClientOutputs deserialize(JsonParser parser, DeserializationContext ctxt)
throws IOException, JacksonException {
List<AuthenticationExtensionsClientOutput<?>> outputs = new ArrayList<>();
for (String key = parser.nextFieldName(); key != null; key = parser.nextFieldName()) {
JsonToken startObject = parser.nextValue();
if (startObject != JsonToken.START_OBJECT) {
break;
}
if (CredentialPropertiesOutput.EXTENSION_ID.equals(key)) {
CredentialPropertiesOutput output = parser.readValueAs(CredentialPropertiesOutput.class);
outputs.add(output);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping unknown extension with id " + key);
}
parser.nextValue();
}
}
return new ImmutableAuthenticationExtensionsClientOutputs(outputs);
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
/**
* Jackson mixin for {@link AuthenticationExtensionsClientOutputs}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticationExtensionsClientOutputsMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonDeserialize(using = AuthenticationExtensionsClientOutputsJackson2Deserializer.class)
class AuthenticationExtensionsClientOutputsJackson2Mixin {
}
@@ -16,7 +16,7 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import tools.jackson.databind.annotation.JsonDeserialize;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
@@ -0,0 +1,42 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
/**
* Jackson mixin for {@link AuthenticatorAssertionResponse}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticatorAssertionResponseMixin}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@JsonDeserialize(builder = AuthenticatorAssertionResponse.AuthenticatorAssertionResponseBuilder.class)
class AuthenticatorAssertionResponseJackson2Mixin {
@JsonPOJOBuilder(withPrefix = "")
abstract class AuthenticatorAssertionResponseBuilderMixin {
}
}
@@ -16,8 +16,8 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import tools.jackson.databind.annotation.JsonDeserialize;
import tools.jackson.databind.annotation.JsonPOJOBuilder;
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
@@ -0,0 +1,58 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.jspecify.annotations.Nullable;
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
/**
* Jackson deserializer for {@link AuthenticatorAttachment}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticatorAttachmentDeserializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class AuthenticatorAttachmentJackson2Deserializer extends StdDeserializer<AuthenticatorAttachment> {
AuthenticatorAttachmentJackson2Deserializer() {
super(AuthenticatorAttachment.class);
}
@Override
public @Nullable AuthenticatorAttachment deserialize(JsonParser parser, DeserializationContext ctxt)
throws IOException, JacksonException {
String type = parser.readValueAs(String.class);
for (AuthenticatorAttachment publicKeyCredentialType : AuthenticatorAttachment.values()) {
if (publicKeyCredentialType.getValue().equals(type)) {
return publicKeyCredentialType;
}
}
return null;
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
/**
* Jackson mixin for {@link AuthenticatorAttachment}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticatorAttachmentMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonDeserialize(using = AuthenticatorAttachmentJackson2Deserializer.class)
@JsonSerialize(using = AuthenticatorAttachmentJackson2Serializer.class)
class AuthenticatorAttachmentJackson2Mixin {
}
@@ -0,0 +1,50 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
/**
* Jackson serializer for {@link AuthenticatorAttachment}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticatorAttachmentSerializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class AuthenticatorAttachmentJackson2Serializer extends StdSerializer<AuthenticatorAttachment> {
AuthenticatorAttachmentJackson2Serializer() {
super(AuthenticatorAttachment.class);
}
@Override
public void serialize(AuthenticatorAttachment attachment, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeString(attachment.getValue());
}
}
@@ -16,8 +16,8 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonDeserialize;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
@@ -38,8 +37,8 @@ class AuthenticatorAttachmentSerializer extends StdSerializer<AuthenticatorAttac
}
@Override
public void serialize(AuthenticatorAttachment attachment, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(AuthenticatorAttachment attachment, JsonGenerator jgen, SerializationContext ctxt)
throws JacksonException {
jgen.writeString(attachment.getValue());
}
@@ -0,0 +1,52 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
/**
* Jackson mixin for {@link AuthenticatorAttestationResponse}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticatorAttestationResponseMixin}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@JsonDeserialize(builder = AuthenticatorAttestationResponse.AuthenticatorAttestationResponseBuilder.class)
class AuthenticatorAttestationResponseJackson2Mixin {
@JsonPOJOBuilder(withPrefix = "")
@JsonIgnoreProperties(ignoreUnknown = true)
abstract class AuthenticatorAttestationResponseBuilderMixin {
@JsonSetter
abstract AuthenticatorAttestationResponse.AuthenticatorAttestationResponseBuilder transports(
List<AuthenticatorTransport> transports);
}
}
@@ -20,8 +20,8 @@ import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import tools.jackson.databind.annotation.JsonDeserialize;
import tools.jackson.databind.annotation.JsonPOJOBuilder;
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
@@ -0,0 +1,58 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.jspecify.annotations.Nullable;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
/**
* Jackson deserializer for {@link AuthenticatorTransport}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticatorTransportDeserializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class AuthenticatorTransportJackson2Deserializer extends StdDeserializer<AuthenticatorTransport> {
AuthenticatorTransportJackson2Deserializer() {
super(AuthenticatorTransport.class);
}
@Override
public @Nullable AuthenticatorTransport deserialize(JsonParser parser, DeserializationContext ctxt)
throws IOException, JacksonException {
String transportValue = parser.readValueAs(String.class);
for (AuthenticatorTransport transport : AuthenticatorTransport.values()) {
if (transport.getValue().equals(transportValue)) {
return transport;
}
}
return null;
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
/**
* Jackson mixin for {@link AuthenticatorTransport}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticatorTransportMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonDeserialize(using = AuthenticatorTransportJackson2Deserializer.class)
@JsonSerialize(using = AuthenticatorTransportJackson2Serializer.class)
class AuthenticatorTransportJackson2Mixin {
}
@@ -0,0 +1,45 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
/**
* Jackson serializer for {@link AuthenticatorTransport}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.AuthenticatorTransportSerializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
class AuthenticatorTransportJackson2Serializer extends JsonSerializer<AuthenticatorTransport> {
@Override
public void serialize(AuthenticatorTransport transport, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeString(transport.getValue());
}
}
@@ -16,8 +16,8 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonDeserialize;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ValueSerializer;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
@@ -30,11 +29,11 @@ import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
* @author Rob Winch
* @since 6.4
*/
class AuthenticatorTransportSerializer extends JsonSerializer<AuthenticatorTransport> {
class AuthenticatorTransportSerializer extends ValueSerializer<AuthenticatorTransport> {
@Override
public void serialize(AuthenticatorTransport transport, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(AuthenticatorTransport transport, JsonGenerator jgen, SerializationContext ctxt)
throws JacksonException {
jgen.writeString(transport.getValue());
}
@@ -0,0 +1,45 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.Bytes;
/**
* Jackson mixin for {@link Bytes}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.BytesMixin} based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonSerialize(using = BytesJackson2Serializer.class)
final class BytesJackson2Mixin {
@JsonCreator
static Bytes fromBase64(String value) {
return Bytes.fromBase64(value);
}
private BytesJackson2Mixin() {
}
}
@@ -0,0 +1,52 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.Bytes;
/**
* Jackson serializer for {@link Bytes}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.BytesSerializer} based on
* Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class BytesJackson2Serializer extends StdSerializer<Bytes> {
/**
* Creates a new instance.
*/
BytesJackson2Serializer() {
super(Bytes.class);
}
@Override
public void serialize(Bytes bytes, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeString(bytes.toBase64UrlString());
}
}
@@ -17,7 +17,7 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.Bytes;
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.Bytes;
@@ -41,7 +40,7 @@ class BytesSerializer extends StdSerializer<Bytes> {
}
@Override
public void serialize(Bytes bytes, JsonGenerator jgen, SerializerProvider provider) throws IOException {
public void serialize(Bytes bytes, JsonGenerator jgen, SerializationContext provider) throws JacksonException {
jgen.writeString(bytes.toBase64UrlString());
}
@@ -0,0 +1,58 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.jspecify.annotations.Nullable;
import org.springframework.security.web.webauthn.api.COSEAlgorithmIdentifier;
/**
* Jackson serializer for {@link COSEAlgorithmIdentifier}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.COSEAlgorithmIdentifierDeserializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class COSEAlgorithmIdentifierJackson2Deserializer extends StdDeserializer<COSEAlgorithmIdentifier> {
COSEAlgorithmIdentifierJackson2Deserializer() {
super(COSEAlgorithmIdentifier.class);
}
@Override
public @Nullable COSEAlgorithmIdentifier deserialize(JsonParser parser, DeserializationContext ctxt)
throws IOException, JacksonException {
Long transportValue = parser.readValueAs(Long.class);
for (COSEAlgorithmIdentifier identifier : COSEAlgorithmIdentifier.values()) {
if (identifier.getValue() == transportValue.longValue()) {
return identifier;
}
}
return null;
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.COSEAlgorithmIdentifier;
/**
* Jackson mixin for {@link COSEAlgorithmIdentifier}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.COSEAlgorithmIdentifierMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonSerialize(using = COSEAlgorithmIdentifierJackson2Serializer.class)
@JsonDeserialize(using = COSEAlgorithmIdentifierJackson2Deserializer.class)
abstract class COSEAlgorithmIdentifierJackson2Mixin {
}
@@ -0,0 +1,50 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.COSEAlgorithmIdentifier;
/**
* Jackson serializer for {@link COSEAlgorithmIdentifier}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.COSEAlgorithmIdentifierSerializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class COSEAlgorithmIdentifierJackson2Serializer extends StdSerializer<COSEAlgorithmIdentifier> {
COSEAlgorithmIdentifierJackson2Serializer() {
super(COSEAlgorithmIdentifier.class);
}
@Override
public void serialize(COSEAlgorithmIdentifier identifier, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeNumber(identifier.getValue());
}
}
@@ -16,8 +16,8 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonDeserialize;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.COSEAlgorithmIdentifier;
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.COSEAlgorithmIdentifier;
@@ -38,8 +37,8 @@ class COSEAlgorithmIdentifierSerializer extends StdSerializer<COSEAlgorithmIdent
}
@Override
public void serialize(COSEAlgorithmIdentifier identifier, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(COSEAlgorithmIdentifier identifier, JsonGenerator jgen, SerializationContext ctxt)
throws JacksonException {
jgen.writeNumber(identifier.getValue());
}
@@ -0,0 +1,31 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
/**
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.CredProtectAuthenticationExtensionsClientInputMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonSerialize(using = CredProtectAuthenticationExtensionsClientInputJackson2Serializer.class)
class CredProtectAuthenticationExtensionsClientInputJackson2Mixin {
}
@@ -0,0 +1,68 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput;
/**
* Serializes <a href=
* "https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html#sctn-credProtect-extension">credProtect
* extension</a>.
*
* @author Rob Winch
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.CredProtectAuthenticationExtensionsClientInputSerializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class CredProtectAuthenticationExtensionsClientInputJackson2Serializer
extends StdSerializer<CredProtectAuthenticationExtensionsClientInput> {
protected CredProtectAuthenticationExtensionsClientInputJackson2Serializer() {
super(CredProtectAuthenticationExtensionsClientInput.class);
}
@Override
public void serialize(CredProtectAuthenticationExtensionsClientInput input, JsonGenerator jgen,
SerializerProvider provider) throws IOException {
CredProtectAuthenticationExtensionsClientInput.CredProtect credProtect = input.getInput();
String policy = toString(credProtect.getCredProtectionPolicy());
jgen.writeObjectField("credentialProtectionPolicy", policy);
jgen.writeObjectField("enforceCredentialProtectionPolicy", credProtect.isEnforceCredentialProtectionPolicy());
}
private static String toString(CredProtectAuthenticationExtensionsClientInput.CredProtect.ProtectionPolicy policy) {
switch (policy) {
case USER_VERIFICATION_OPTIONAL:
return "userVerificationOptional";
case USER_VERIFICATION_OPTIONAL_WITH_CREDENTIAL_ID_LIST:
return "userVerificationOptionalWithCredentialIdList";
case USER_VERIFICATION_REQUIRED:
return "userVerificationRequired";
default:
throw new IllegalArgumentException("Unsupported ProtectionPolicy " + policy);
}
}
}
@@ -16,7 +16,7 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonSerialize;
@JsonSerialize(using = CredProtectAuthenticationExtensionsClientInputSerializer.class)
class CredProtectAuthenticationExtensionsClientInputMixin {
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput;
@@ -41,11 +40,11 @@ class CredProtectAuthenticationExtensionsClientInputSerializer
@Override
public void serialize(CredProtectAuthenticationExtensionsClientInput input, JsonGenerator jgen,
SerializerProvider provider) throws IOException {
SerializationContext ctxt) throws JacksonException {
CredProtectAuthenticationExtensionsClientInput.CredProtect credProtect = input.getInput();
String policy = toString(credProtect.getCredProtectionPolicy());
jgen.writeObjectField("credentialProtectionPolicy", policy);
jgen.writeObjectField("enforceCredentialProtectionPolicy", credProtect.isEnforceCredentialProtectionPolicy());
jgen.writePOJOProperty("credentialProtectionPolicy", policy);
jgen.writePOJOProperty("enforceCredentialProtectionPolicy", credProtect.isEnforceCredentialProtectionPolicy());
}
private static String toString(CredProtectAuthenticationExtensionsClientInput.CredProtect.ProtectionPolicy policy) {
@@ -0,0 +1,40 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.security.web.webauthn.api.CredentialPropertiesOutput;
/**
* Jackson mixin for {@link CredentialPropertiesOutput}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.CredentialPropertiesOutputMixin}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@JsonIgnoreProperties(ignoreUnknown = true)
abstract class CredentialPropertiesOutputJackson2Mixin {
CredentialPropertiesOutputJackson2Mixin(@JsonProperty("rk") boolean rk) {
}
}
@@ -0,0 +1,51 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import java.time.Duration;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
/**
* Jackson serializer for {@link Duration}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.DurationSerializer} based on
* Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class DurationJackson2Serializer extends StdSerializer<Duration> {
/**
* Creates an instance.
*/
DurationJackson2Serializer() {
super(Duration.class);
}
@Override
public void serialize(Duration duration, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeNumber(duration.toMillis());
}
}
@@ -16,12 +16,12 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import java.time.Duration;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
/**
* Jackson serializer for {@link Duration}
@@ -40,7 +40,7 @@ class DurationSerializer extends StdSerializer<Duration> {
}
@Override
public void serialize(Duration duration, JsonGenerator jgen, SerializerProvider provider) throws IOException {
public void serialize(Duration duration, JsonGenerator jgen, SerializationContext ctxt) throws JacksonException {
jgen.writeNumber(duration.toMillis());
}
@@ -0,0 +1,44 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.time.Duration;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.jspecify.annotations.Nullable;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
/**
* Jackson mixin for {@link PublicKeyCredentialCreationOptions}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.PublicKeyCredentialCreationOptionsMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
abstract class PublicKeyCredentialCreationOptionsJackson2Mixin {
@JsonSerialize(using = DurationJackson2Serializer.class)
private @Nullable Duration timeout;
}
@@ -19,8 +19,8 @@ package org.springframework.security.web.webauthn.jackson;
import java.time.Duration;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.jspecify.annotations.Nullable;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
@@ -0,0 +1,42 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
/**
* Jackson mixin for {@link PublicKeyCredential}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.PublicKeyCredentialMixin}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@JsonDeserialize(builder = PublicKeyCredential.PublicKeyCredentialBuilder.class)
class PublicKeyCredentialJackson2Mixin {
@JsonPOJOBuilder(withPrefix = "")
static class PublicKeyCredentialBuilderMixin {
}
}
@@ -16,8 +16,8 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import tools.jackson.databind.annotation.JsonDeserialize;
import tools.jackson.databind.annotation.JsonPOJOBuilder;
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
@@ -0,0 +1,44 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.time.Duration;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.jspecify.annotations.Nullable;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
/**
* Jackson mixin for {@link PublicKeyCredentialRequestOptions}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.PublicKeyCredentialRequestOptionsMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonInclude(content = JsonInclude.Include.NON_NULL)
class PublicKeyCredentialRequestOptionsJackson2Mixin {
@JsonSerialize(using = DurationJackson2Serializer.class)
private final @Nullable Duration timeout = null;
}
@@ -19,8 +19,8 @@ package org.springframework.security.web.webauthn.jackson;
import java.time.Duration;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.jspecify.annotations.Nullable;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
@@ -16,12 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonParser;
import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.deser.std.StdDeserializer;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
@@ -42,8 +40,7 @@ class PublicKeyCredentialTypeDeserializer extends StdDeserializer<PublicKeyCrede
}
@Override
public PublicKeyCredentialType deserialize(JsonParser parser, DeserializationContext ctxt)
throws IOException, JacksonException {
public PublicKeyCredentialType deserialize(JsonParser parser, DeserializationContext ctxt) throws JacksonException {
String type = parser.readValueAs(String.class);
return PublicKeyCredentialType.valueOf(type);
}
@@ -0,0 +1,55 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
/**
* Jackson deserializer for {@link PublicKeyCredentialType}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.PublicKeyCredentialTypeDeserializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class PublicKeyCredentialTypeJackson2Deserializer extends StdDeserializer<PublicKeyCredentialType> {
/**
* Creates a new instance.
*/
PublicKeyCredentialTypeJackson2Deserializer() {
super(PublicKeyCredentialType.class);
}
@Override
public PublicKeyCredentialType deserialize(JsonParser parser, DeserializationContext ctxt)
throws IOException, JacksonException {
String type = parser.readValueAs(String.class);
return PublicKeyCredentialType.valueOf(type);
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
/**
* Jackson mixin for {@link PublicKeyCredentialType}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.PublicKeyCredentialTypeMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonSerialize(using = PublicKeyCredentialTypeJackson2Serializer.class)
@JsonDeserialize(using = PublicKeyCredentialTypeJackson2Deserializer.class)
abstract class PublicKeyCredentialTypeJackson2Mixin {
}
@@ -0,0 +1,53 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
/**
* Jackson serializer for {@link PublicKeyCredentialType}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.PublicKeyCredentialTypeSerializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class PublicKeyCredentialTypeJackson2Serializer extends StdSerializer<PublicKeyCredentialType> {
/**
* Creates a new instance.
*/
PublicKeyCredentialTypeJackson2Serializer() {
super(PublicKeyCredentialType.class);
}
@Override
public void serialize(PublicKeyCredentialType type, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeString(type.getValue());
}
}
@@ -16,8 +16,8 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonDeserialize;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
@@ -41,8 +40,8 @@ class PublicKeyCredentialTypeSerializer extends StdSerializer<PublicKeyCredentia
}
@Override
public void serialize(PublicKeyCredentialType type, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(PublicKeyCredentialType type, JsonGenerator jgen, SerializationContext ctxt)
throws JacksonException {
jgen.writeString(type.getValue());
}
@@ -0,0 +1,42 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse;
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
import org.springframework.security.web.webauthn.management.RelyingPartyPublicKey;
/**
* Jackson mixin for {@link RelyingPartyPublicKey}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.RelyingPartyPublicKeyMixin}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
abstract class RelyingPartyPublicKeyJackson2Mixin {
RelyingPartyPublicKeyJackson2Mixin(
@JsonProperty("credential") PublicKeyCredential<AuthenticatorAttestationResponse> credential,
@JsonProperty("label") String label) {
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.ResidentKeyRequirement;
/**
* Jackson mixin for {@link ResidentKeyRequirement}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.ResidentKeyRequirementMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonSerialize(using = ResidentKeyRequirementJackson2Serializer.class)
abstract class ResidentKeyRequirementJackson2Mixin {
}
@@ -0,0 +1,53 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.ResidentKeyRequirement;
/**
* Jackson serializer for {@link ResidentKeyRequirement}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.ResidentKeyRequirementSerializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class ResidentKeyRequirementJackson2Serializer extends StdSerializer<ResidentKeyRequirement> {
/**
* Creates a new instance.
*/
ResidentKeyRequirementJackson2Serializer() {
super(ResidentKeyRequirement.class);
}
@Override
public void serialize(ResidentKeyRequirement requirement, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeString(requirement.getValue());
}
}
@@ -16,7 +16,7 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.ResidentKeyRequirement;
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.ResidentKeyRequirement;
@@ -41,8 +40,8 @@ class ResidentKeyRequirementSerializer extends StdSerializer<ResidentKeyRequirem
}
@Override
public void serialize(ResidentKeyRequirement requirement, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(ResidentKeyRequirement requirement, JsonGenerator jgen, SerializationContext ctxt)
throws JacksonException {
jgen.writeString(requirement.getValue());
}
@@ -0,0 +1,37 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.UserVerificationRequirement;
/**
* Jackson mixin for {@link UserVerificationRequirement}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.UserVerificationRequirementMixin}
* based on Jackson 3
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
@JsonSerialize(using = UserVerificationRequirementJackson2Serializer.class)
abstract class UserVerificationRequirementJackson2Mixin {
}
@@ -0,0 +1,53 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.UserVerificationRequirement;
/**
* Jackson serializer for {@link UserVerificationRequirement}
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.UserVerificationRequirementSerializer}
* based on Jackson 3
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("serial")
class UserVerificationRequirementJackson2Serializer extends StdSerializer<UserVerificationRequirement> {
/**
* Creates a new instance.
*/
UserVerificationRequirementJackson2Serializer() {
super(UserVerificationRequirement.class);
}
@Override
public void serialize(UserVerificationRequirement requirement, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeString(requirement.getValue());
}
}
@@ -16,7 +16,7 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import tools.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.web.webauthn.api.UserVerificationRequirement;
@@ -16,11 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.web.webauthn.api.UserVerificationRequirement;
@@ -41,8 +40,8 @@ class UserVerificationRequirementSerializer extends StdSerializer<UserVerificati
}
@Override
public void serialize(UserVerificationRequirement requirement, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(UserVerificationRequirement requirement, JsonGenerator jgen, SerializationContext ctxt)
throws JacksonException {
jgen.writeString(requirement.getValue());
}
@@ -46,8 +46,12 @@ import org.springframework.security.web.webauthn.management.RelyingPartyPublicKe
*
* @author Rob Winch
* @since 6.4
* @deprecated as of 7.0 in favor of
* {@link org.springframework.security.web.webauthn.jackson.WebauthnJacksonModule} based
* on Jackson 3
*/
@SuppressWarnings("serial")
@Deprecated(forRemoval = true)
@SuppressWarnings({ "serial", "removal" })
public class WebauthnJackson2Module extends SimpleModule {
/**
@@ -59,39 +63,41 @@ public class WebauthnJackson2Module extends SimpleModule {
@Override
public void setupModule(SetupContext context) {
context.setMixInAnnotations(Bytes.class, BytesMixin.class);
context.setMixInAnnotations(AttestationConveyancePreference.class, AttestationConveyancePreferenceMixin.class);
context.setMixInAnnotations(Bytes.class, BytesJackson2Mixin.class);
context.setMixInAnnotations(AttestationConveyancePreference.class,
AttestationConveyancePreferenceJackson2Mixin.class);
context.setMixInAnnotations(AuthenticationExtensionsClientInput.class,
AuthenticationExtensionsClientInputMixin.class);
AuthenticationExtensionsClientInputJackson2Mixin.class);
context.setMixInAnnotations(AuthenticationExtensionsClientInputs.class,
AuthenticationExtensionsClientInputsMixin.class);
AuthenticationExtensionsClientInputsJackson2Mixin.class);
context.setMixInAnnotations(AuthenticationExtensionsClientOutputs.class,
AuthenticationExtensionsClientOutputsMixin.class);
AuthenticationExtensionsClientOutputsJackson2Mixin.class);
context.setMixInAnnotations(AuthenticatorAssertionResponse.AuthenticatorAssertionResponseBuilder.class,
AuthenticatorAssertionResponseMixin.AuthenticatorAssertionResponseBuilderMixin.class);
context.setMixInAnnotations(AuthenticatorAssertionResponse.class, AuthenticatorAssertionResponseMixin.class);
context.setMixInAnnotations(AuthenticatorAttachment.class, AuthenticatorAttachmentMixin.class);
AuthenticatorAssertionResponseJackson2Mixin.AuthenticatorAssertionResponseBuilderMixin.class);
context.setMixInAnnotations(AuthenticatorAssertionResponse.class,
AuthenticatorAssertionResponseJackson2Mixin.class);
context.setMixInAnnotations(AuthenticatorAttachment.class, AuthenticatorAttachmentJackson2Mixin.class);
context.setMixInAnnotations(AuthenticatorAttestationResponse.class,
AuthenticatorAttestationResponseMixin.class);
AuthenticatorAttestationResponseJackson2Mixin.class);
context.setMixInAnnotations(AuthenticatorAttestationResponse.AuthenticatorAttestationResponseBuilder.class,
AuthenticatorAttestationResponseMixin.AuthenticatorAttestationResponseBuilderMixin.class);
AuthenticatorAttestationResponseJackson2Mixin.AuthenticatorAttestationResponseBuilderMixin.class);
context.setMixInAnnotations(AuthenticatorSelectionCriteria.class, AuthenticatorSelectionCriteriaMixin.class);
context.setMixInAnnotations(AuthenticatorTransport.class, AuthenticatorTransportMixin.class);
context.setMixInAnnotations(COSEAlgorithmIdentifier.class, COSEAlgorithmIdentifierMixin.class);
context.setMixInAnnotations(CredentialPropertiesOutput.class, CredentialPropertiesOutputMixin.class);
context.setMixInAnnotations(AuthenticatorTransport.class, AuthenticatorTransportJackson2Mixin.class);
context.setMixInAnnotations(COSEAlgorithmIdentifier.class, COSEAlgorithmIdentifierJackson2Mixin.class);
context.setMixInAnnotations(CredentialPropertiesOutput.class, CredentialPropertiesOutputJackson2Mixin.class);
context.setMixInAnnotations(CredProtectAuthenticationExtensionsClientInput.class,
CredProtectAuthenticationExtensionsClientInputMixin.class);
CredProtectAuthenticationExtensionsClientInputJackson2Mixin.class);
context.setMixInAnnotations(PublicKeyCredential.PublicKeyCredentialBuilder.class,
PublicKeyCredentialMixin.PublicKeyCredentialBuilderMixin.class);
context.setMixInAnnotations(PublicKeyCredential.class, PublicKeyCredentialMixin.class);
PublicKeyCredentialJackson2Mixin.PublicKeyCredentialBuilderMixin.class);
context.setMixInAnnotations(PublicKeyCredential.class, PublicKeyCredentialJackson2Mixin.class);
context.setMixInAnnotations(PublicKeyCredentialCreationOptions.class,
PublicKeyCredentialCreationOptionsMixin.class);
PublicKeyCredentialCreationOptionsJackson2Mixin.class);
context.setMixInAnnotations(PublicKeyCredentialRequestOptions.class,
PublicKeyCredentialRequestOptionsMixin.class);
context.setMixInAnnotations(PublicKeyCredentialType.class, PublicKeyCredentialTypeMixin.class);
context.setMixInAnnotations(RelyingPartyPublicKey.class, RelyingPartyPublicKeyMixin.class);
context.setMixInAnnotations(ResidentKeyRequirement.class, ResidentKeyRequirementMixin.class);
context.setMixInAnnotations(UserVerificationRequirement.class, UserVerificationRequirementMixin.class);
PublicKeyCredentialRequestOptionsJackson2Mixin.class);
context.setMixInAnnotations(PublicKeyCredentialType.class, PublicKeyCredentialTypeJackson2Mixin.class);
context.setMixInAnnotations(RelyingPartyPublicKey.class, RelyingPartyPublicKeyJackson2Mixin.class);
context.setMixInAnnotations(ResidentKeyRequirement.class, ResidentKeyRequirementJackson2Mixin.class);
context.setMixInAnnotations(UserVerificationRequirement.class, UserVerificationRequirementJackson2Mixin.class);
}
}
@@ -0,0 +1,97 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import tools.jackson.core.Version;
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import org.springframework.security.jackson.SecurityJacksonModule;
import org.springframework.security.web.webauthn.api.AttestationConveyancePreference;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInput;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse;
import org.springframework.security.web.webauthn.api.AuthenticatorSelectionCriteria;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
import org.springframework.security.web.webauthn.api.Bytes;
import org.springframework.security.web.webauthn.api.COSEAlgorithmIdentifier;
import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput;
import org.springframework.security.web.webauthn.api.CredentialPropertiesOutput;
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
import org.springframework.security.web.webauthn.api.ResidentKeyRequirement;
import org.springframework.security.web.webauthn.api.UserVerificationRequirement;
import org.springframework.security.web.webauthn.management.RelyingPartyPublicKey;
/**
* Adds Jackson support for Spring Security WebAuthn. It is automatically registered when
* using Jackson's SPI support.
*
* @author Sebastien Deleuze
* @author Rob Winch
* @since 7.0
*/
@SuppressWarnings("serial")
public class WebauthnJacksonModule extends SecurityJacksonModule {
/**
* Creates a new instance.
*/
public WebauthnJacksonModule() {
super(WebauthnJacksonModule.class.getName(), new Version(1, 0, 0, null, null, null));
}
@Override
public void configurePolymorphicTypeValidator(BasicPolymorphicTypeValidator.Builder builder) {
}
@Override
public void setupModule(SetupContext context) {
context.setMixIn(Bytes.class, BytesMixin.class);
context.setMixIn(AttestationConveyancePreference.class, AttestationConveyancePreferenceMixin.class);
context.setMixIn(AuthenticationExtensionsClientInput.class, AuthenticationExtensionsClientInputMixin.class);
context.setMixIn(AuthenticationExtensionsClientInputs.class, AuthenticationExtensionsClientInputsMixin.class);
context.setMixIn(AuthenticationExtensionsClientOutputs.class, AuthenticationExtensionsClientOutputsMixin.class);
context.setMixIn(AuthenticatorAssertionResponse.AuthenticatorAssertionResponseBuilder.class,
AuthenticatorAssertionResponseMixin.AuthenticatorAssertionResponseBuilderMixin.class);
context.setMixIn(AuthenticatorAssertionResponse.class, AuthenticatorAssertionResponseMixin.class);
context.setMixIn(AuthenticatorAttachment.class, AuthenticatorAttachmentMixin.class);
context.setMixIn(AuthenticatorAttestationResponse.class, AuthenticatorAttestationResponseMixin.class);
context.setMixIn(AuthenticatorAttestationResponse.AuthenticatorAttestationResponseBuilder.class,
AuthenticatorAttestationResponseMixin.AuthenticatorAttestationResponseBuilderMixin.class);
context.setMixIn(AuthenticatorSelectionCriteria.class, AuthenticatorSelectionCriteriaMixin.class);
context.setMixIn(AuthenticatorTransport.class, AuthenticatorTransportMixin.class);
context.setMixIn(COSEAlgorithmIdentifier.class, COSEAlgorithmIdentifierMixin.class);
context.setMixIn(CredentialPropertiesOutput.class, CredentialPropertiesOutputMixin.class);
context.setMixIn(CredProtectAuthenticationExtensionsClientInput.class,
CredProtectAuthenticationExtensionsClientInputMixin.class);
context.setMixIn(PublicKeyCredential.PublicKeyCredentialBuilder.class,
PublicKeyCredentialMixin.PublicKeyCredentialBuilderMixin.class);
context.setMixIn(PublicKeyCredential.class, PublicKeyCredentialMixin.class);
context.setMixIn(PublicKeyCredentialCreationOptions.class, PublicKeyCredentialCreationOptionsMixin.class);
context.setMixIn(PublicKeyCredentialRequestOptions.class, PublicKeyCredentialRequestOptionsMixin.class);
context.setMixIn(PublicKeyCredentialType.class, PublicKeyCredentialTypeMixin.class);
context.setMixIn(RelyingPartyPublicKey.class, RelyingPartyPublicKeyMixin.class);
context.setMixIn(ResidentKeyRequirement.class, ResidentKeyRequirementMixin.class);
context.setMixIn(UserVerificationRequirement.class, UserVerificationRequirementMixin.class);
}
}
@@ -23,13 +23,13 @@ import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
import org.springframework.security.authorization.AuthorizationManager;
@@ -41,7 +41,7 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
import org.springframework.security.web.webauthn.jackson.WebauthnJackson2Module;
import org.springframework.security.web.webauthn.jackson.WebauthnJacksonModule;
import org.springframework.security.web.webauthn.management.ImmutablePublicKeyCredentialCreationOptionsRequest;
import org.springframework.security.web.webauthn.management.WebAuthnRelyingPartyOperations;
import org.springframework.util.Assert;
@@ -69,8 +69,8 @@ public class PublicKeyCredentialCreationOptionsFilter extends OncePerRequestFilt
private final WebAuthnRelyingPartyOperations rpOperations;
private HttpMessageConverter<Object> converter = new MappingJackson2HttpMessageConverter(
Jackson2ObjectMapperBuilder.json().modules(new WebauthnJackson2Module()).build());
private HttpMessageConverter<Object> converter = new JacksonJsonHttpMessageConverter(
JsonMapper.builder().addModule(new WebauthnJacksonModule()).build());
/**
* Creates a new instance.
@@ -131,7 +131,7 @@ public class PublicKeyCredentialCreationOptionsFilter extends OncePerRequestFilt
/**
* Set the {@link HttpMessageConverter} to read the
* {@link WebAuthnRegistrationFilter.WebAuthnRegistrationRequest} and write the
* response. The default is {@link MappingJackson2HttpMessageConverter}.
* response. The default is {@link JacksonJsonHttpMessageConverter}.
* @param converter the {@link HttpMessageConverter} to use. Cannot be null.
*/
public void setConverter(HttpMessageConverter<Object> converter) {
@@ -18,7 +18,6 @@ package org.springframework.security.web.webauthn.registration;
import java.io.IOException;
import com.fasterxml.jackson.databind.json.JsonMapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@@ -26,13 +25,14 @@ import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
@@ -40,7 +40,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.webauthn.api.Bytes;
import org.springframework.security.web.webauthn.api.CredentialRecord;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
import org.springframework.security.web.webauthn.jackson.WebauthnJackson2Module;
import org.springframework.security.web.webauthn.jackson.WebauthnJacksonModule;
import org.springframework.security.web.webauthn.management.ImmutableRelyingPartyRegistrationRequest;
import org.springframework.security.web.webauthn.management.RelyingPartyPublicKey;
import org.springframework.security.web.webauthn.management.UserCredentialRepository;
@@ -88,8 +88,8 @@ public class WebAuthnRegistrationFilter extends OncePerRequestFilter {
private final UserCredentialRepository userCredentials;
private HttpMessageConverter<Object> converter = new MappingJackson2HttpMessageConverter(
JsonMapper.builder().addModule(new WebauthnJackson2Module()).build());
private HttpMessageConverter<Object> converter = new JacksonJsonHttpMessageConverter(
JsonMapper.builder().addModule(new WebauthnJacksonModule()).build());
private PublicKeyCredentialCreationOptionsRepository creationOptionsRepository = new HttpSessionPublicKeyCredentialCreationOptionsRepository();
@@ -152,7 +152,7 @@ public class WebAuthnRegistrationFilter extends OncePerRequestFilter {
/**
* Set the {@link HttpMessageConverter} to read the
* {@link WebAuthnRegistrationRequest} and write the response. The default is
* {@link MappingJackson2HttpMessageConverter}.
* {@link JacksonJsonHttpMessageConverter}.
* @param converter the {@link HttpMessageConverter} to use. Cannot be null.
*/
public void setConverter(HttpMessageConverter<Object> converter) {
@@ -27,7 +27,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.SmartHttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
@@ -79,7 +79,7 @@ class WebAuthnAuthenticationFilterTests {
""";
@Mock
private GenericHttpMessageConverter<Object> converter;
private SmartHttpMessageConverter<Object> converter;
@Mock
private PublicKeyCredentialRequestOptionsRepository requestOptionsRepository;
@@ -0,0 +1,153 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput;
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInputs;
/**
* Test Jackson serialization of CredProtectAuthenticationExtensionsClientInput
*
* @author Rob Winch
*/
class CredProtectAuthenticationExtensionsClientInputJackson2Tests {
private ObjectMapper mapper;
@BeforeEach
void setup() {
this.mapper = new ObjectMapper();
this.mapper.registerModule(new WebauthnJackson2Module());
}
@Test
void writeAuthenticationExtensionsClientInputsWhenCredProtectUserVerificationOptional() throws Exception {
String expected = """
{
"credentialProtectionPolicy": "userVerificationOptional",
"enforceCredentialProtectionPolicy": true
}
""";
CredProtectAuthenticationExtensionsClientInput.CredProtect credProtect = new CredProtectAuthenticationExtensionsClientInput.CredProtect(
CredProtectAuthenticationExtensionsClientInput.CredProtect.ProtectionPolicy.USER_VERIFICATION_OPTIONAL,
true);
CredProtectAuthenticationExtensionsClientInput credProtectInput = new CredProtectAuthenticationExtensionsClientInput(
credProtect);
ImmutableAuthenticationExtensionsClientInputs clientInputs = new ImmutableAuthenticationExtensionsClientInputs(
credProtectInput);
String actual = this.mapper.writeValueAsString(clientInputs);
JSONAssert.assertEquals(expected, actual, false);
}
@Test
void writeAuthenticationExtensionsClientInputsWhenCredProtectUserVerificationOptionalWithCredentialIdList()
throws Exception {
String expected = """
{
"credentialProtectionPolicy": "userVerificationOptionalWithCredentialIdList",
"enforceCredentialProtectionPolicy": true
}
""";
CredProtectAuthenticationExtensionsClientInput.CredProtect credProtect = new CredProtectAuthenticationExtensionsClientInput.CredProtect(
CredProtectAuthenticationExtensionsClientInput.CredProtect.ProtectionPolicy.USER_VERIFICATION_OPTIONAL_WITH_CREDENTIAL_ID_LIST,
true);
CredProtectAuthenticationExtensionsClientInput credProtectInput = new CredProtectAuthenticationExtensionsClientInput(
credProtect);
ImmutableAuthenticationExtensionsClientInputs clientInputs = new ImmutableAuthenticationExtensionsClientInputs(
credProtectInput);
String actual = this.mapper.writeValueAsString(clientInputs);
JSONAssert.assertEquals(expected, actual, false);
}
@Test
void writeAuthenticationExtensionsClientInputsWhenCredProtectUserVerificationRequired() throws Exception {
String expected = """
{
"credentialProtectionPolicy": "userVerificationRequired",
"enforceCredentialProtectionPolicy": true
}
""";
CredProtectAuthenticationExtensionsClientInput.CredProtect credProtect = new CredProtectAuthenticationExtensionsClientInput.CredProtect(
CredProtectAuthenticationExtensionsClientInput.CredProtect.ProtectionPolicy.USER_VERIFICATION_REQUIRED,
true);
CredProtectAuthenticationExtensionsClientInput credProtectInput = new CredProtectAuthenticationExtensionsClientInput(
credProtect);
ImmutableAuthenticationExtensionsClientInputs clientInputs = new ImmutableAuthenticationExtensionsClientInputs(
credProtectInput);
String actual = this.mapper.writeValueAsString(clientInputs);
JSONAssert.assertEquals(expected, actual, false);
}
@Test
void writeAuthenticationExtensionsClientInputsWhenEnforceCredentialProtectionPolicyTrue() throws Exception {
String expected = """
{
"credentialProtectionPolicy": "userVerificationOptional",
"enforceCredentialProtectionPolicy": true
}
""";
CredProtectAuthenticationExtensionsClientInput.CredProtect credProtect = new CredProtectAuthenticationExtensionsClientInput.CredProtect(
CredProtectAuthenticationExtensionsClientInput.CredProtect.ProtectionPolicy.USER_VERIFICATION_OPTIONAL,
true);
CredProtectAuthenticationExtensionsClientInput credProtectInput = new CredProtectAuthenticationExtensionsClientInput(
credProtect);
ImmutableAuthenticationExtensionsClientInputs clientInputs = new ImmutableAuthenticationExtensionsClientInputs(
credProtectInput);
String actual = this.mapper.writeValueAsString(clientInputs);
JSONAssert.assertEquals(expected, actual, false);
}
@Test
void writeAuthenticationExtensionsClientInputsWhenEnforceCredentialProtectionPolicyFalse() throws Exception {
String expected = """
{
"credentialProtectionPolicy": "userVerificationOptional",
"enforceCredentialProtectionPolicy": false
}
""";
CredProtectAuthenticationExtensionsClientInput.CredProtect credProtect = new CredProtectAuthenticationExtensionsClientInput.CredProtect(
CredProtectAuthenticationExtensionsClientInput.CredProtect.ProtectionPolicy.USER_VERIFICATION_OPTIONAL,
false);
CredProtectAuthenticationExtensionsClientInput credProtectInput = new CredProtectAuthenticationExtensionsClientInput(
credProtect);
ImmutableAuthenticationExtensionsClientInputs clientInputs = new ImmutableAuthenticationExtensionsClientInputs(
credProtectInput);
String actual = this.mapper.writeValueAsString(clientInputs);
JSONAssert.assertEquals(expected, actual, false);
}
}
@@ -16,10 +16,10 @@
package org.springframework.security.web.webauthn.jackson;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput;
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInputs;
@@ -31,12 +31,11 @@ import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExte
*/
class CredProtectAuthenticationExtensionsClientInputJacksonTests {
private ObjectMapper mapper;
private JsonMapper mapper;
@BeforeEach
void setup() {
this.mapper = new ObjectMapper();
this.mapper.registerModule(new WebauthnJackson2Module());
this.mapper = JsonMapper.builder().addModule(new WebauthnJacksonModule()).build();
}
@Test
@@ -0,0 +1,363 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.webauthn.jackson;
import java.time.Duration;
import java.util.Arrays;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
import org.springframework.security.web.webauthn.api.Bytes;
import org.springframework.security.web.webauthn.api.CredentialPropertiesOutput;
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInput;
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInputs;
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientOutputs;
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialCreationOptions;
import org.springframework.security.web.webauthn.api.UserVerificationRequirement;
import static org.assertj.core.api.Assertions.assertThat;
class Jackson2Tests {
private ObjectMapper mapper;
@BeforeEach
void setup() {
this.mapper = new ObjectMapper();
this.mapper.registerModule(new WebauthnJackson2Module());
}
@Test
void readAuthenticatorTransport() throws Exception {
AuthenticatorTransport transport = this.mapper.readValue("\"hybrid\"", AuthenticatorTransport.class);
assertThat(transport).isEqualTo(AuthenticatorTransport.HYBRID);
}
@Test
void readAuthenticatorAttachment() throws Exception {
AuthenticatorAttachment value = this.mapper.readValue("\"cross-platform\"", AuthenticatorAttachment.class);
assertThat(value).isEqualTo(AuthenticatorAttachment.CROSS_PLATFORM);
}
@Test
void writeAuthenticatorAttachment() throws Exception {
String value = this.mapper.writeValueAsString(AuthenticatorAttachment.CROSS_PLATFORM);
assertThat(value).isEqualTo("\"cross-platform\"");
}
@Test
void readAuthenticationExtensionsClientOutputs() throws Exception {
String json = """
{
"credProps": {
"rk": false
}
}
""";
ImmutableAuthenticationExtensionsClientOutputs clientExtensionResults = new ImmutableAuthenticationExtensionsClientOutputs(
new CredentialPropertiesOutput(false));
AuthenticationExtensionsClientOutputs outputs = this.mapper.readValue(json,
AuthenticationExtensionsClientOutputs.class);
assertThat(outputs).usingRecursiveComparison().isEqualTo(clientExtensionResults);
}
@Test
void readAuthenticationExtensionsClientOutputsWhenAuthenticatorDisplayName() throws Exception {
String json = """
{
"credProps": {
"rk": false,
"authenticatorDisplayName": "1Password"
}
}
""";
ImmutableAuthenticationExtensionsClientOutputs clientExtensionResults = new ImmutableAuthenticationExtensionsClientOutputs(
new CredentialPropertiesOutput(false));
AuthenticationExtensionsClientOutputs outputs = this.mapper.readValue(json,
AuthenticationExtensionsClientOutputs.class);
assertThat(outputs).usingRecursiveComparison().isEqualTo(clientExtensionResults);
}
@Test
void readCredPropsWhenAuthenticatorDisplayName() throws Exception {
String json = """
{
"rk": false,
"authenticatorDisplayName": "1Password"
}
""";
CredentialPropertiesOutput credProps = new CredentialPropertiesOutput(false);
CredentialPropertiesOutput outputs = this.mapper.readValue(json, CredentialPropertiesOutput.class);
assertThat(outputs).usingRecursiveComparison().isEqualTo(credProps);
}
@Test
void readAuthenticationExtensionsClientOutputsWhenFieldAfter() throws Exception {
String json = """
{
"clientOutputs": {
"credProps": {
"rk": false
}
},
"label": "Cell Phone"
}
""";
ImmutableAuthenticationExtensionsClientOutputs clientExtensionResults = new ImmutableAuthenticationExtensionsClientOutputs(
new CredentialPropertiesOutput(false));
ClassWithOutputsAndAnotherField expected = new ClassWithOutputsAndAnotherField();
expected.setClientOutputs(clientExtensionResults);
expected.setLabel("Cell Phone");
ClassWithOutputsAndAnotherField actual = this.mapper.readValue(json, ClassWithOutputsAndAnotherField.class);
assertThat(actual).usingRecursiveComparison().isEqualTo(expected);
}
@Test
void writePublicKeyCredentialCreationOptions() throws Exception {
String expected = """
{
"attestation": "none",
"authenticatorSelection": {
"residentKey": "required"
},
"challenge": "q7lCdd3SVQxdC-v8pnRAGEn1B2M-t7ZECWPwCAmhWvc",
"excludeCredentials": [],
"extensions": {
"credProps": true
},
"pubKeyCredParams": [
{
"alg": -7,
"type": "public-key"
},{
"alg": -8,
"type": "public-key"
},
{
"alg": -257,
"type": "public-key"
}
],
"rp": {
"id": "example.localhost",
"name": "SimpleWebAuthn Example"
},
"timeout": 300000,
"user": {
"displayName": "user@example.localhost",
"id": "oWJtkJ6vJ_m5b84LB4_K7QKTCTEwLIjCh4tFMCGHO4w",
"name": "user@example.localhost"
}
}
""";
PublicKeyCredentialCreationOptions options = TestPublicKeyCredentialCreationOptions
.createPublicKeyCredentialCreationOptions()
.build();
String string = this.mapper.writeValueAsString(options);
JSONAssert.assertEquals(expected, string, false);
}
@Test
void readPublicKeyCredentialAuthenticatorAttestationResponse() throws Exception {
PublicKeyCredential<AuthenticatorAttestationResponse> publicKeyCredential = this.mapper.readValue(
PublicKeyCredentialJson.PUBLIC_KEY_JSON,
new TypeReference<PublicKeyCredential<AuthenticatorAttestationResponse>>() {
});
ImmutableAuthenticationExtensionsClientOutputs clientExtensionResults = new ImmutableAuthenticationExtensionsClientOutputs(
new CredentialPropertiesOutput(false));
PublicKeyCredential<AuthenticatorAttestationResponse> expected = PublicKeyCredential.builder()
.id("AX6nVVERrH6opMafUGn3Z9EyNEy6cftfBKV_2YxYl1jdW8CSJxMKGXFV3bnrKTiMSJeInkG7C6B2lPt8E5i3KaM")
.rawId(Bytes
.fromBase64("AX6nVVERrH6opMafUGn3Z9EyNEy6cftfBKV_2YxYl1jdW8CSJxMKGXFV3bnrKTiMSJeInkG7C6B2lPt8E5i3KaM"))
.response(AuthenticatorAttestationResponse.builder()
.attestationObject(Bytes.fromBase64(
"o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFSZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQF-p1VREax-qKTGn1Bp92fRMjRMunH7XwSlf9mMWJdY3VvAkicTChlxVd256yk4jEiXiJ5BuwugdpT7fBOYtymjpQECAyYgASFYIJK-2epPEw0ujHN-gvVp2Hp3ef8CzU3zqwO5ylx8L2OsIlggK5x5OlTGEPxLS-85TAABum4aqVK4CSWJ7LYDdkjuBLk"))
.clientDataJSON(Bytes.fromBase64(
"eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiSUJRbnVZMVowSzFIcUJvRldDcDJ4bEpsOC1vcV9hRklYenlUX0YwLTBHVSIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIsImNyb3NzT3JpZ2luIjpmYWxzZX0"))
.transports(AuthenticatorTransport.HYBRID, AuthenticatorTransport.INTERNAL)
.build())
.type(PublicKeyCredentialType.PUBLIC_KEY)
.clientExtensionResults(clientExtensionResults)
.authenticatorAttachment(AuthenticatorAttachment.CROSS_PLATFORM)
.build();
assertThat(publicKeyCredential).usingRecursiveComparison().isEqualTo(expected);
}
@Test
void readPublicKeyCredentialAuthenticatorAttestationResponseWhenExtraFields() throws Exception {
final String json = """
{
"attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFSZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQF-p1VREax-qKTGn1Bp92fRMjRMunH7XwSlf9mMWJdY3VvAkicTChlxVd256yk4jEiXiJ5BuwugdpT7fBOYtymjpQECAyYgASFYIJK-2epPEw0ujHN-gvVp2Hp3ef8CzU3zqwO5ylx8L2OsIlggK5x5OlTGEPxLS-85TAABum4aqVK4CSWJ7LYDdkjuBLk",
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiSUJRbnVZMVowSzFIcUJvRldDcDJ4bEpsOC1vcV9hRklYenlUX0YwLTBHVSIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIsImNyb3NzT3JpZ2luIjpmYWxzZX0",
"transports": [
"hybrid",
"internal"
],
"publicKeyAlgorithm": -7,
"publicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkr7Z6k8TDS6Mc36C9WnYend5_wLNTfOrA7nKXHwvY6wrnHk6VMYQ_EtL7zlMAAG6bhqpUrgJJYnstgN2SO4EuQ",
"authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQF-p1VREax-qKTGn1Bp92fRMjRMunH7XwSlf9mMWJdY3VvAkicTChlxVd256yk4jEiXiJ5BuwugdpT7fBOYtymjpQECAyYgASFYIJK-2epPEw0ujHN-gvVp2Hp3ef8CzU3zqwO5ylx8L2OsIlggK5x5OlTGEPxLS-85TAABum4aqVK4CSWJ7LYDdkjuBLk"
}
""";
AuthenticatorAttestationResponse response = this.mapper.readValue(json, AuthenticatorAttestationResponse.class);
ImmutableAuthenticationExtensionsClientOutputs clientExtensionResults = new ImmutableAuthenticationExtensionsClientOutputs(
new CredentialPropertiesOutput(false));
AuthenticatorAttestationResponse expected = AuthenticatorAttestationResponse.builder()
.attestationObject(Bytes.fromBase64(
"o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFSZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQF-p1VREax-qKTGn1Bp92fRMjRMunH7XwSlf9mMWJdY3VvAkicTChlxVd256yk4jEiXiJ5BuwugdpT7fBOYtymjpQECAyYgASFYIJK-2epPEw0ujHN-gvVp2Hp3ef8CzU3zqwO5ylx8L2OsIlggK5x5OlTGEPxLS-85TAABum4aqVK4CSWJ7LYDdkjuBLk"))
.clientDataJSON(Bytes.fromBase64(
"eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiSUJRbnVZMVowSzFIcUJvRldDcDJ4bEpsOC1vcV9hRklYenlUX0YwLTBHVSIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIsImNyb3NzT3JpZ2luIjpmYWxzZX0"))
.transports(AuthenticatorTransport.HYBRID, AuthenticatorTransport.INTERNAL)
.build();
assertThat(response).usingRecursiveComparison().isEqualTo(expected);
}
@Test
void writeAuthenticationOptions() throws Exception {
PublicKeyCredentialRequestOptions credentialRequestOptions = PublicKeyCredentialRequestOptions.builder()
.allowCredentials(Arrays.asList())
.challenge(Bytes.fromBase64("I69THX904Q8ONhCgUgOu2PCQCcEjTDiNmokdbgsAsYU"))
.rpId("example.localhost")
.timeout(Duration.ofMinutes(5))
.userVerification(UserVerificationRequirement.REQUIRED)
.build();
String actual = this.mapper.writeValueAsString(credentialRequestOptions);
String expected = """
{
"challenge": "I69THX904Q8ONhCgUgOu2PCQCcEjTDiNmokdbgsAsYU",
"allowCredentials": [],
"timeout": 300000,
"userVerification": "required",
"rpId": "example.localhost"
}
""";
JSONAssert.assertEquals(expected, actual, false);
}
@Test
void readPublicKeyCredentialAuthenticatorAssertionResponse() throws Exception {
String json = """
{
"id": "IquGb208Fffq2cROa1ZxMg",
"rawId": "IquGb208Fffq2cROa1ZxMg",
"response": {
"authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MdAAAAAA",
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiaDB2Z3dHUWpvQ3pBekRVc216UHBrLUpWSUpSUmduMEw0S1ZTWU5SY0VaYyIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIsImNyb3NzT3JpZ2luIjpmYWxzZX0",
"signature": "MEUCIAdfzPAn3voyXynwa0IXk1S0envMY5KP3NEe9aj4B2BuAiEAm_KJhQoWXdvfhbzwACU3NM4ltQe7_Il46qFUwtpuTdg",
"userHandle": "oWJtkJ6vJ_m5b84LB4_K7QKTCTEwLIjCh4tFMCGHO4w"
},
"type": "public-key",
"clientExtensionResults": {},
"authenticatorAttachment": "cross-platform"
}
""";
PublicKeyCredential<AuthenticatorAssertionResponse> publicKeyCredential = this.mapper.readValue(json,
new TypeReference<PublicKeyCredential<AuthenticatorAssertionResponse>>() {
});
ImmutableAuthenticationExtensionsClientOutputs clientExtensionResults = new ImmutableAuthenticationExtensionsClientOutputs();
PublicKeyCredential<AuthenticatorAssertionResponse> expected = PublicKeyCredential.builder()
.id("IquGb208Fffq2cROa1ZxMg")
.rawId(Bytes.fromBase64("IquGb208Fffq2cROa1ZxMg"))
.response(AuthenticatorAssertionResponse.builder()
.authenticatorData(Bytes.fromBase64("SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MdAAAAAA"))
.clientDataJSON(Bytes.fromBase64(
"eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiaDB2Z3dHUWpvQ3pBekRVc216UHBrLUpWSUpSUmduMEw0S1ZTWU5SY0VaYyIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIsImNyb3NzT3JpZ2luIjpmYWxzZX0"))
.signature(Bytes.fromBase64(
"MEUCIAdfzPAn3voyXynwa0IXk1S0envMY5KP3NEe9aj4B2BuAiEAm_KJhQoWXdvfhbzwACU3NM4ltQe7_Il46qFUwtpuTdg"))
.userHandle(Bytes.fromBase64("oWJtkJ6vJ_m5b84LB4_K7QKTCTEwLIjCh4tFMCGHO4w"))
.build())
.type(PublicKeyCredentialType.PUBLIC_KEY)
.clientExtensionResults(clientExtensionResults)
.authenticatorAttachment(AuthenticatorAttachment.CROSS_PLATFORM)
.build();
assertThat(publicKeyCredential).usingRecursiveComparison().isEqualTo(expected);
}
@Test
void writeAuthenticationExtensionsClientInputsWhenCredPropsTrue() throws Exception {
String expected = """
{
"credProps": true
}
""";
ImmutableAuthenticationExtensionsClientInputs clientInputs = new ImmutableAuthenticationExtensionsClientInputs(
ImmutableAuthenticationExtensionsClientInput.credProps);
String actual = this.mapper.writeValueAsString(clientInputs);
JSONAssert.assertEquals(expected, actual, false);
}
public static class ClassWithOutputsAndAnotherField {
private String label;
private AuthenticationExtensionsClientOutputs clientOutputs;
public String getLabel() {
return this.label;
}
public void setLabel(String label) {
this.label = label;
}
public AuthenticationExtensionsClientOutputs getClientOutputs() {
return this.clientOutputs;
}
public void setClientOutputs(AuthenticationExtensionsClientOutputs clientOutputs) {
this.clientOutputs = clientOutputs;
}
}
}
@@ -19,11 +19,11 @@ package org.springframework.security.web.webauthn.jackson;
import java.time.Duration;
import java.util.Arrays;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
@@ -46,12 +46,11 @@ import static org.assertj.core.api.Assertions.assertThat;
class JacksonTests {
private ObjectMapper mapper;
private JsonMapper mapper;
@BeforeEach
void setup() {
this.mapper = new ObjectMapper();
this.mapper.registerModule(new WebauthnJackson2Module());
this.mapper = JsonMapper.builder().addModule(new WebauthnJacksonModule()).build();
}
@Test
@@ -16,9 +16,9 @@
package org.springframework.security.web.webauthn.registration;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse;
@@ -29,7 +29,7 @@ import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExte
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
import org.springframework.security.web.webauthn.jackson.PublicKeyCredentialJson;
import org.springframework.security.web.webauthn.jackson.WebauthnJackson2Module;
import org.springframework.security.web.webauthn.jackson.WebauthnJacksonModule;
import org.springframework.security.web.webauthn.management.RelyingPartyPublicKey;
import static org.assertj.core.api.Assertions.assertThat;
@@ -40,12 +40,11 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
class WebAuthnRegistrationRequestJacksonTests {
private ObjectMapper mapper;
private JsonMapper mapper;
@BeforeEach
void setup() {
this.mapper = new ObjectMapper();
this.mapper.registerModule(new WebauthnJackson2Module());
this.mapper = JsonMapper.builder().addModule(new WebauthnJacksonModule()).build();
}
@Test