فهرست منبع

Add Jackson Support for Saml2AuthenticationException

Closes gh-11169
Ulrich Grave 3 سال پیش
والد
کامیت
c6038b1ea3

+ 47 - 0
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson2/Saml2AuthenticationExceptionMixin.java

@@ -0,0 +1,47 @@
+/*
+ * Copyright 2002-2022 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.saml2.jackson2;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+import org.springframework.security.saml2.core.Saml2Error;
+import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
+
+/**
+ * This mixin class is used to serialize/deserialize {@link Saml2AuthenticationException}.
+ *
+ * @author Ulrich Grave
+ * @since 5.7
+ * @see Saml2AuthenticationException
+ * @see Saml2Jackson2Module
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
+		isGetterVisibility = JsonAutoDetect.Visibility.NONE)
+@JsonIgnoreProperties(ignoreUnknown = true, value = { "cause", "stackTrace", "suppressedExceptions" })
+class Saml2AuthenticationExceptionMixin {
+
+	@JsonCreator
+	Saml2AuthenticationExceptionMixin(@JsonProperty("error") Saml2Error error,
+			@JsonProperty("detailMessage") String message) {
+	}
+
+}

+ 45 - 0
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson2/Saml2ErrorMixin.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2022 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.saml2.jackson2;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+import org.springframework.security.saml2.core.Saml2Error;
+
+/**
+ * This mixin class is used to serialize/deserialize {@link Saml2Error}.
+ *
+ * @author Ulrich Grave
+ * @since 5.7
+ * @see Saml2Error
+ * @see Saml2Jackson2Module
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
+		isGetterVisibility = JsonAutoDetect.Visibility.NONE)
+@JsonIgnoreProperties(ignoreUnknown = true)
+class Saml2ErrorMixin {
+
+	@JsonCreator
+	Saml2ErrorMixin(@JsonProperty("errorCode") String errorCode, @JsonProperty("description") String description) {
+	}
+
+}

+ 7 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson2/Saml2Jackson2Module.java

@@ -20,8 +20,10 @@ import com.fasterxml.jackson.core.Version;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 
 import org.springframework.security.jackson2.SecurityJackson2Modules;
+import org.springframework.security.saml2.core.Saml2Error;
 import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
 import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
+import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
 import org.springframework.security.saml2.provider.service.authentication.Saml2PostAuthenticationRequest;
 import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest;
 import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
@@ -29,8 +31,9 @@ import org.springframework.security.saml2.provider.service.authentication.logout
 /**
  * Jackson module for saml2-service-provider. This module register
  * {@link Saml2AuthenticationMixin}, {@link DefaultSaml2AuthenticatedPrincipalMixin},
- * {@link Saml2LogoutRequestMixin}, {@link Saml2RedirectAuthenticationRequestMixin} and
- * {@link Saml2PostAuthenticationRequestMixin}.
+ * {@link Saml2LogoutRequestMixin}, {@link Saml2RedirectAuthenticationRequestMixin},
+ * {@link Saml2PostAuthenticationRequestMixin}, {@link Saml2ErrorMixin} and
+ * {@link Saml2AuthenticationExceptionMixin}.
  *
  * @author Ulrich Grave
  * @since 5.7
@@ -51,6 +54,8 @@ public class Saml2Jackson2Module extends SimpleModule {
 		context.setMixInAnnotations(Saml2RedirectAuthenticationRequest.class,
 				Saml2RedirectAuthenticationRequestMixin.class);
 		context.setMixInAnnotations(Saml2PostAuthenticationRequest.class, Saml2PostAuthenticationRequestMixin.class);
+		context.setMixInAnnotations(Saml2Error.class, Saml2ErrorMixin.class);
+		context.setMixInAnnotations(Saml2AuthenticationException.class, Saml2AuthenticationExceptionMixin.class);
 	}
 
 }

+ 61 - 0
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/jackson2/Saml2AuthenticationExceptionMixinTest.java

@@ -0,0 +1,61 @@
+/*
+ * Copyright 2002-2022 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.saml2.jackson2;
+
+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.jackson2.SecurityJackson2Modules;
+import org.springframework.security.saml2.core.Saml2Error;
+import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class Saml2AuthenticationExceptionMixinTest {
+
+	private ObjectMapper mapper;
+
+	@BeforeEach
+	void setUp() {
+		this.mapper = new ObjectMapper();
+		ClassLoader loader = getClass().getClassLoader();
+		this.mapper.registerModules(SecurityJackson2Modules.getModules(loader));
+	}
+
+	@Test
+	void shouldSerialize() throws Exception {
+		Saml2AuthenticationException exception = TestSaml2JsonPayloads.createDefaultSaml2AuthenticationException();
+
+		String exceptionJson = this.mapper.writeValueAsString(exception);
+
+		JSONAssert.assertEquals(TestSaml2JsonPayloads.DEFAULT_SAML_AUTH_EXCEPTION_JSON, exceptionJson, true);
+	}
+
+	@Test
+	void shouldDeserialize() throws Exception {
+		Saml2AuthenticationException exception = this.mapper
+				.readValue(TestSaml2JsonPayloads.DEFAULT_SAML_AUTH_EXCEPTION_JSON, Saml2AuthenticationException.class);
+
+		assertThat(exception).isNotNull();
+		assertThat(exception.getMessage()).isEqualTo("exceptionMessage");
+		assertThat(exception.getSaml2Error()).extracting(Saml2Error::getErrorCode, Saml2Error::getDescription)
+				.contains("errorCode", "errorDescription");
+	}
+
+}

+ 18 - 0
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/jackson2/TestSaml2JsonPayloads.java

@@ -26,8 +26,10 @@ import java.util.Map;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.userdetails.User;
+import org.springframework.security.saml2.core.Saml2Error;
 import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
 import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
+import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
 import org.springframework.security.saml2.provider.service.authentication.Saml2PostAuthenticationRequest;
 import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest;
 import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
@@ -216,4 +218,20 @@ final class TestSaml2JsonPayloads {
 		return authentication;
 	}
 
+	// @formatter:off
+	static final String DEFAULT_SAML_AUTH_EXCEPTION_JSON = "{"
+			+ "  \"@class\": \"org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException\","
+			+ "  \"detailMessage\": \"exceptionMessage\","
+			+ "  \"error\": {"
+			+ "    \"@class\": \"org.springframework.security.saml2.core.Saml2Error\","
+			+ "    \"errorCode\": \"errorCode\","
+			+ "    \"description\": \"errorDescription\""
+			+ "  }"
+			+ "}";
+	// @formatter:on
+
+	static Saml2AuthenticationException createDefaultSaml2AuthenticationException() {
+		return new Saml2AuthenticationException(new Saml2Error("errorCode", "errorDescription"), "exceptionMessage");
+	}
+
 }