diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2Error.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2Error.java new file mode 100644 index 0000000000..94b0450276 --- /dev/null +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2Error.java @@ -0,0 +1,75 @@ +/* + * Copyright 2002-2020 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.core; + +import java.io.Serializable; + +import org.springframework.security.core.SpringSecurityCoreVersion; +import org.springframework.util.Assert; + +/** + * A representation of an SAML 2.0 Error. + * + *

+ * At a minimum, an error response will contain an error code. + * The commonly used error code are defined in this class + * or a new codes can be defined in the future as arbitrary strings. + *

+ * @since 5.2 + */ +public class Saml2Error implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + + private final String errorCode; + private final String description; + + /** + * Constructs a {@code Saml2Error} using the provided parameters. + * + * @param errorCode the error code + * @param description the error description + */ + public Saml2Error(String errorCode, String description) { + Assert.hasText(errorCode, "errorCode cannot be empty"); + this.errorCode = errorCode; + this.description = description; + } + + /** + * Returns the error code. + * + * @return the error code + */ + public final String getErrorCode() { + return this.errorCode; + } + + /** + * Returns the error description. + * + * @return the error description + */ + public final String getDescription() { + return this.description; + } + + @Override + public String toString() { + return "[" + this.getErrorCode() + "] " + + (this.getDescription() != null ? this.getDescription() : ""); + } +} diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2ErrorCodes.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2ErrorCodes.java new file mode 100644 index 0000000000..810c4338c7 --- /dev/null +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2ErrorCodes.java @@ -0,0 +1,101 @@ +/* + * Copyright 2002-2020 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.core; + +/** + * A list of SAML known 2 error codes used during SAML authentication. + * + * @since 5.2 + */ +public interface Saml2ErrorCodes { + /** + * SAML Data does not represent a SAML 2 Response object. + * A valid XML object was received, but that object was not a + * SAML 2 Response object of type {@code ResponseType} per specification + * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=46 + */ + String UNKNOWN_RESPONSE_CLASS = "unknown_response_class"; + /** + * The response data is malformed or incomplete. + * An invalid XML object was received, and XML unmarshalling failed. + */ + String MALFORMED_RESPONSE_DATA = "malformed_response_data"; + /** + * Response destination does not match the request URL. + * A SAML 2 response object was received at a URL that + * did not match the URL stored in the {code Destination} attribute + * in the Response object. + * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=38 + */ + String INVALID_DESTINATION = "invalid_destination"; + /** + * The assertion was not valid. + * The assertion used for authentication failed validation. + * Details around the failure will be present in the error description. + */ + String INVALID_ASSERTION = "invalid_assertion"; + /** + * The signature of response or assertion was invalid. + * Either the response or the assertion was missing a signature + * or the signature could not be verified using the system's + * configured credentials. Most commonly the IDP's + * X509 certificate. + */ + String INVALID_SIGNATURE = "invalid_signature"; + /** + * The assertion did not contain a subject element. + * The subject element, type SubjectType, contains + * a {@code NameID} or an {@code EncryptedID} that is used + * to assign the authenticated principal an identifier, + * typically a username. + * + * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=18 + */ + String SUBJECT_NOT_FOUND = "subject_not_found"; + /** + * The subject did not contain a user identifier + * The assertion contained a subject element, but the subject + * element did not have a {@code NameID} or {@code EncryptedID} + * element + * + * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=18 + */ + String USERNAME_NOT_FOUND = "username_not_found"; + /** + * The system failed to decrypt an assertion or a name identifier. + * This error code will be thrown if the decryption of either a + * {@code EncryptedAssertion} or {@code EncryptedID} fails. + * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=17 + */ + String DECRYPTION_ERROR = "decryption_error"; + /** + * An Issuer element contained a value that didn't + * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=15 + */ + String INVALID_ISSUER = "invalid_issuer"; + /** + * An error happened during validation. + * Used when internal, non classified, errors are caught during the + * authentication process. + */ + String INTERNAL_VALIDATION_ERROR = "internal_validation_error"; + /** + * The relying party registration was not found. + * The registration ID did not correspond to any relying party registration. + */ + String RELYING_PARTY_REGISTRATION_NOT_FOUND = "relying_party_registration_not_found"; +} diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java index ae497d1d44..8ed7bf0c94 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java @@ -98,6 +98,7 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; import org.springframework.security.saml2.Saml2Exception; +import org.springframework.security.saml2.core.Saml2Error; import org.springframework.security.saml2.credentials.Saml2X509Credential; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; @@ -110,15 +111,15 @@ import static org.opensaml.saml.saml2.assertion.SAML2AssertionValidationParamete import static org.opensaml.saml.saml2.assertion.SAML2AssertionValidationParameters.COND_VALID_AUDIENCES; import static org.opensaml.saml.saml2.assertion.SAML2AssertionValidationParameters.SC_VALID_RECIPIENTS; import static org.opensaml.saml.saml2.assertion.SAML2AssertionValidationParameters.SIGNATURE_REQUIRED; -import static org.springframework.security.saml2.provider.service.authentication.Saml2ErrorCodes.DECRYPTION_ERROR; -import static org.springframework.security.saml2.provider.service.authentication.Saml2ErrorCodes.INTERNAL_VALIDATION_ERROR; -import static org.springframework.security.saml2.provider.service.authentication.Saml2ErrorCodes.INVALID_ASSERTION; -import static org.springframework.security.saml2.provider.service.authentication.Saml2ErrorCodes.INVALID_DESTINATION; -import static org.springframework.security.saml2.provider.service.authentication.Saml2ErrorCodes.INVALID_ISSUER; -import static org.springframework.security.saml2.provider.service.authentication.Saml2ErrorCodes.INVALID_SIGNATURE; -import static org.springframework.security.saml2.provider.service.authentication.Saml2ErrorCodes.MALFORMED_RESPONSE_DATA; -import static org.springframework.security.saml2.provider.service.authentication.Saml2ErrorCodes.SUBJECT_NOT_FOUND; -import static org.springframework.security.saml2.provider.service.authentication.Saml2ErrorCodes.UNKNOWN_RESPONSE_CLASS; +import static org.springframework.security.saml2.core.Saml2ErrorCodes.DECRYPTION_ERROR; +import static org.springframework.security.saml2.core.Saml2ErrorCodes.INTERNAL_VALIDATION_ERROR; +import static org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_ASSERTION; +import static org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_DESTINATION; +import static org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_ISSUER; +import static org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_SIGNATURE; +import static org.springframework.security.saml2.core.Saml2ErrorCodes.MALFORMED_RESPONSE_DATA; +import static org.springframework.security.saml2.core.Saml2ErrorCodes.SUBJECT_NOT_FOUND; +import static org.springframework.security.saml2.core.Saml2ErrorCodes.UNKNOWN_RESPONSE_CLASS; import static org.springframework.util.Assert.notNull; /** diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationException.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationException.java index 86709cec1e..332762f002 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationException.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationException.java @@ -18,6 +18,7 @@ package org.springframework.security.saml2.provider.service.authentication; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.saml2.core.Saml2Error; import org.springframework.util.Assert; /** diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Error.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Error.java index 786ae0e011..e9cf3d3b98 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Error.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Error.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -16,11 +16,11 @@ package org.springframework.security.saml2.provider.service.authentication; +import java.io.Serializable; + import org.springframework.security.core.SpringSecurityCoreVersion; import org.springframework.util.Assert; -import java.io.Serializable; - /** * A representation of an SAML 2.0 Error. * @@ -30,7 +30,9 @@ import java.io.Serializable; * or a new codes can be defined in the future as arbitrary strings. *

* @since 5.2 + * @deprecated Use {@link org.springframework.security.saml2.core.Saml2Error} instead */ +@Deprecated public class Saml2Error implements Serializable { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2ErrorCodes.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2ErrorCodes.java index 203a1194a0..e0dcba514f 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2ErrorCodes.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2ErrorCodes.java @@ -20,7 +20,9 @@ package org.springframework.security.saml2.provider.service.authentication; * A list of SAML known 2 error codes used during SAML authentication. * * @since 5.2 + * @deprecated Use {@link org.springframework.security.saml2.core.Saml2ErrorCodes} instead */ +@Deprecated public interface Saml2ErrorCodes { /** * SAML Data does not represent a SAML 2 Response object. diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java index 028a07973a..e04456b004 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java @@ -24,7 +24,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationToken; -import org.springframework.security.saml2.provider.service.authentication.Saml2Error; +import org.springframework.security.saml2.core.Saml2Error; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; @@ -34,7 +34,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.springframework.security.saml2.provider.service.authentication.Saml2ErrorCodes.RELYING_PARTY_REGISTRATION_NOT_FOUND; +import static org.springframework.security.saml2.core.Saml2ErrorCodes.RELYING_PARTY_REGISTRATION_NOT_FOUND; import static org.springframework.util.StringUtils.hasText; /** diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProviderTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProviderTests.java index 64f5946dba..f710673dbe 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProviderTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProviderTests.java @@ -52,6 +52,7 @@ import org.w3c.dom.Element; import org.xml.sax.InputSource; import org.springframework.security.core.Authentication; +import org.springframework.security.saml2.core.Saml2ErrorCodes; import org.springframework.security.saml2.credentials.Saml2X509Credential; import static org.assertj.core.api.Assertions.assertThat;