Browse Source

Preserve Encrypted Elements

Closes gh-16367
Josh Cummings 4 months ago
parent
commit
f8d417dc03
18 changed files with 134 additions and 178 deletions
  1. 1 11
      saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/internal/OpenSaml4Template.java
  2. 1 11
      saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml4Template.java
  3. 1 11
      saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSaml4Template.java
  4. 1 11
      saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/metadata/OpenSaml4Template.java
  5. 1 11
      saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/registration/OpenSaml4Template.java
  6. 1 11
      saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/web/OpenSaml4Template.java
  7. 1 11
      saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml4Template.java
  8. 1 11
      saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml4Template.java
  9. 59 1
      saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml4AuthenticationProviderTests.java
  10. 1 11
      saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/internal/OpenSaml5Template.java
  11. 1 11
      saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml5Template.java
  12. 1 11
      saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSaml5Template.java
  13. 1 11
      saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/metadata/OpenSaml5Template.java
  14. 1 11
      saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/registration/OpenSaml5Template.java
  15. 1 11
      saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/OpenSaml5Template.java
  16. 1 11
      saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml5Template.java
  17. 1 11
      saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml5Template.java
  18. 59 1
      saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml5AuthenticationProviderTests.java

+ 1 - 11
saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/internal/OpenSaml4Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml4Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSaml4Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/metadata/OpenSaml4Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/registration/OpenSaml4Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/web/OpenSaml4Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml4Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml4Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 59 - 1
saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml4AuthenticationProviderTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -386,6 +386,24 @@ public class OpenSaml4AuthenticationProviderTests {
 		this.provider.authenticate(token);
 	}
 
+	// gh-16367
+	@Test
+	public void authenticateWhenEncryptedAssertionWithSignatureThenEncryptedAssertionStillAvailable() {
+		Response response = response();
+		Assertion assertion = TestOpenSamlObjects.signed(assertion(),
+				TestSaml2X509Credentials.assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID);
+		EncryptedAssertion encryptedAssertion = TestOpenSamlObjects.encrypted(assertion,
+				TestSaml2X509Credentials.assertingPartyEncryptingCredential());
+		response.getEncryptedAssertions().add(encryptedAssertion);
+		Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
+		OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
+		provider.setResponseValidator((t) -> {
+			assertThat(t.getResponse().getEncryptedAssertions()).isNotEmpty();
+			return Saml2ResponseValidatorResult.success();
+		});
+		provider.authenticate(token);
+	}
+
 	@Test
 	public void authenticateWhenEncryptedAssertionWithResponseSignatureThenItSucceeds() {
 		Response response = response();
@@ -410,6 +428,26 @@ public class OpenSaml4AuthenticationProviderTests {
 		this.provider.authenticate(token);
 	}
 
+	// gh-16367
+	@Test
+	public void authenticateWhenEncryptedNameIdWithSignatureThenEncryptedNameIdStillAvailable() {
+		Response response = response();
+		Assertion assertion = assertion();
+		NameID nameId = assertion.getSubject().getNameID();
+		EncryptedID encryptedID = TestOpenSamlObjects.encrypted(nameId,
+				TestSaml2X509Credentials.assertingPartyEncryptingCredential());
+		assertion.getSubject().setNameID(null);
+		assertion.getSubject().setEncryptedID(encryptedID);
+		response.getAssertions().add(signed(assertion));
+		Saml2AuthenticationToken token = token(response, decrypting(verifying(registration())));
+		OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
+		provider.setAssertionValidator((t) -> {
+			assertThat(t.getAssertion().getSubject().getEncryptedID()).isNotNull();
+			return Saml2ResponseValidatorResult.success();
+		});
+		provider.authenticate(token);
+	}
+
 	@Test
 	public void authenticateWhenEncryptedAttributeThenDecrypts() {
 		Response response = response();
@@ -426,6 +464,26 @@ public class OpenSaml4AuthenticationProviderTests {
 		assertThat(principal.getAttribute("name")).containsExactly("value");
 	}
 
+	// gh-16367
+	@Test
+	public void authenticateWhenEncryptedAttributeThenEncryptedAttributesStillAvailable() {
+		Response response = response();
+		Assertion assertion = assertion();
+		EncryptedAttribute attribute = TestOpenSamlObjects.encrypted("name", "value",
+				TestSaml2X509Credentials.assertingPartyEncryptingCredential());
+		AttributeStatement statement = build(AttributeStatement.DEFAULT_ELEMENT_NAME);
+		statement.getEncryptedAttributes().add(attribute);
+		assertion.getAttributeStatements().add(statement);
+		response.getAssertions().add(assertion);
+		Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
+		OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
+		provider.setAssertionValidator((t) -> {
+			assertThat(t.getAssertion().getAttributeStatements().get(0).getEncryptedAttributes()).isNotEmpty();
+			return Saml2ResponseValidatorResult.success();
+		});
+		provider.authenticate(token);
+	}
+
 	@Test
 	public void authenticateWhenDecryptionKeysAreMissingThenThrowAuthenticationException() {
 		Response response = response();

+ 1 - 11
saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/internal/OpenSaml5Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml5Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSaml5Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/metadata/OpenSaml5Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/registration/OpenSaml5Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/OpenSaml5Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml5Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 1 - 11
saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml5Template.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptResponse(Response response) {
 			Collection<Assertion> decrypteds = new ArrayList<>();
-			Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
 
 			int count = 0;
 			int size = response.getEncryptedAssertions().size();
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				try {
 					Assertion decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 					count++;
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 				}
 			}
 
-			response.getEncryptedAssertions().removeAll(encrypteds);
 			response.getAssertions().addAll(decrypteds);
 
 			// Re-marshall the response so that any ID attributes within the decrypted
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
 								if (decrypted != null) {
 									d.setNameID(decrypted);
-									d.setEncryptedID(null);
 								}
 							}
 							catch (DecryptionException ex) {
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
 
 		private void decryptAttributes(AttributeStatement statement) {
 			Collection<Attribute> decrypteds = new ArrayList<>();
-			Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
 			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
 				try {
 					Attribute decrypted = this.decrypter.decrypt(encrypted);
 					if (decrypted != null) {
-						encrypteds.add(encrypted);
 						decrypteds.add(decrypted);
 					}
 				}
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					throw new Saml2Exception(ex);
 				}
 			}
-			statement.getEncryptedAttributes().removeAll(encrypteds);
 			statement.getAttributes().addAll(decrypteds);
 		}
 
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
 						if (decrypted != null) {
 							subject.setNameID(decrypted);
-							subject.setEncryptedID(null);
 						}
 					}
 					catch (final DecryptionException ex) {
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
 							if (decrypted != null) {
 								sc.setNameID(decrypted);
-								sc.setEncryptedID(null);
 							}
 						}
 						catch (final DecryptionException ex) {
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
 					NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
 					if (decrypted != null) {
 						request.setNameID(decrypted);
-						request.setEncryptedID(null);
 					}
 				}
 				catch (DecryptionException ex) {

+ 59 - 1
saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml5AuthenticationProviderTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -386,6 +386,24 @@ public class OpenSaml5AuthenticationProviderTests {
 		this.provider.authenticate(token);
 	}
 
+	// gh-16367
+	@Test
+	public void authenticateWhenEncryptedAssertionWithSignatureThenEncryptedAssertionStillAvailable() {
+		Response response = response();
+		Assertion assertion = TestOpenSamlObjects.signed(assertion(),
+				TestSaml2X509Credentials.assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID);
+		EncryptedAssertion encryptedAssertion = TestOpenSamlObjects.encrypted(assertion,
+				TestSaml2X509Credentials.assertingPartyEncryptingCredential());
+		response.getEncryptedAssertions().add(encryptedAssertion);
+		Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
+		OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
+		provider.setResponseValidator((t) -> {
+			assertThat(t.getResponse().getEncryptedAssertions()).isNotEmpty();
+			return Saml2ResponseValidatorResult.success();
+		});
+		provider.authenticate(token);
+	}
+
 	@Test
 	public void authenticateWhenEncryptedAssertionWithResponseSignatureThenItSucceeds() {
 		Response response = response();
@@ -410,6 +428,26 @@ public class OpenSaml5AuthenticationProviderTests {
 		this.provider.authenticate(token);
 	}
 
+	// gh-16367
+	@Test
+	public void authenticateWhenEncryptedNameIdWithSignatureThenEncryptedNameIdStillAvailable() {
+		Response response = response();
+		Assertion assertion = assertion();
+		NameID nameId = assertion.getSubject().getNameID();
+		EncryptedID encryptedID = TestOpenSamlObjects.encrypted(nameId,
+				TestSaml2X509Credentials.assertingPartyEncryptingCredential());
+		assertion.getSubject().setNameID(null);
+		assertion.getSubject().setEncryptedID(encryptedID);
+		response.getAssertions().add(signed(assertion));
+		Saml2AuthenticationToken token = token(response, decrypting(verifying(registration())));
+		OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
+		provider.setAssertionValidator((t) -> {
+			assertThat(t.getAssertion().getSubject().getEncryptedID()).isNotNull();
+			return Saml2ResponseValidatorResult.success();
+		});
+		provider.authenticate(token);
+	}
+
 	@Test
 	public void authenticateWhenEncryptedAttributeThenDecrypts() {
 		Response response = response();
@@ -426,6 +464,26 @@ public class OpenSaml5AuthenticationProviderTests {
 		assertThat(principal.getAttribute("name")).containsExactly("value");
 	}
 
+	// gh-16367
+	@Test
+	public void authenticateWhenEncryptedAttributeThenEncryptedAttributesStillAvailable() {
+		Response response = response();
+		Assertion assertion = assertion();
+		EncryptedAttribute attribute = TestOpenSamlObjects.encrypted("name", "value",
+				TestSaml2X509Credentials.assertingPartyEncryptingCredential());
+		AttributeStatement statement = build(AttributeStatement.DEFAULT_ELEMENT_NAME);
+		statement.getEncryptedAttributes().add(attribute);
+		assertion.getAttributeStatements().add(statement);
+		response.getAssertions().add(assertion);
+		Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
+		OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
+		provider.setAssertionValidator((t) -> {
+			assertThat(t.getAssertion().getAttributeStatements().get(0).getEncryptedAttributes()).isNotEmpty();
+			return Saml2ResponseValidatorResult.success();
+		});
+		provider.authenticate(token);
+	}
+
 	@Test
 	public void authenticateWhenDecryptionKeysAreMissingThenThrowAuthenticationException() {
 		Response response = response();