diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java index 3aee2258bbf..a6f3f9d9c25 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java @@ -16,22 +16,22 @@ package org.springframework.security.saml2.provider.service.authentication; +import java.time.Clock; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.UUID; + import org.joda.time.DateTime; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.saml2.core.AuthnRequest; import org.opensaml.saml.saml2.core.Issuer; + import org.springframework.security.saml2.credentials.Saml2X509Credential; import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest.Builder; import org.springframework.util.Assert; -import java.time.Clock; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.UUID; - import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.Collections.emptyList; import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlDeflate; import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlEncode; @@ -46,7 +46,9 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication @Override @Deprecated public String createAuthenticationRequest(Saml2AuthenticationRequest request) { - return createAuthenticationRequest(request, request.getCredentials()); + AuthnRequest authnRequest = createAuthnRequest(request.getIssuer(), + request.getDestination(), request.getAssertionConsumerServiceUrl()); + return this.saml.serialize(authnRequest, request.getCredentials()); } /** @@ -54,11 +56,11 @@ public String createAuthenticationRequest(Saml2AuthenticationRequest request) { */ @Override public Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2AuthenticationRequestContext context) { - List signingCredentials = context.getRelyingPartyRegistration().getProviderDetails().isSignAuthNRequest() ? - context.getRelyingPartyRegistration().getSigningCredentials() : - emptyList(); + AuthnRequest authnRequest = createAuthnRequest(context); + String xml = context.getRelyingPartyRegistration().getProviderDetails().isSignAuthNRequest() ? + this.saml.serialize(authnRequest, context.getRelyingPartyRegistration().getSigningCredentials()) : + this.saml.serialize(authnRequest); - String xml = createAuthenticationRequest(context, signingCredentials); return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context) .samlRequest(samlEncode(xml.getBytes(UTF_8))) .build(); @@ -69,7 +71,8 @@ public Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2Authe */ @Override public Saml2RedirectAuthenticationRequest createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext context) { - String xml = createAuthenticationRequest(context, emptyList()); + AuthnRequest authnRequest = createAuthnRequest(context); + String xml = this.saml.serialize(authnRequest); Builder result = Saml2RedirectAuthenticationRequest.withAuthenticationRequestContext(context); String deflatedAndEncoded = samlEncode(samlDeflate(xml)); result.samlRequest(deflatedAndEncoded) @@ -91,27 +94,24 @@ public Saml2RedirectAuthenticationRequest createRedirectAuthenticationRequest(Sa return result.build(); } - private String createAuthenticationRequest(Saml2AuthenticationRequestContext request, List credentials) { - return createAuthenticationRequest(Saml2AuthenticationRequest.withAuthenticationRequestContext(request).build(), credentials); + private AuthnRequest createAuthnRequest(Saml2AuthenticationRequestContext context) { + return createAuthnRequest(context.getIssuer(), + context.getDestination(), context.getAssertionConsumerServiceUrl()); } - private String createAuthenticationRequest(Saml2AuthenticationRequest context, List credentials) { - AuthnRequest auth = this.saml.buildSAMLObject(AuthnRequest.class); + private AuthnRequest createAuthnRequest(String issuer, String destination, String assertionConsumerServiceUrl) { + AuthnRequest auth = this.saml.buildSamlObject(AuthnRequest.DEFAULT_ELEMENT_NAME); auth.setID("ARQ" + UUID.randomUUID().toString().substring(1)); auth.setIssueInstant(new DateTime(this.clock.millis())); auth.setForceAuthn(Boolean.FALSE); auth.setIsPassive(Boolean.FALSE); auth.setProtocolBinding(protocolBinding); - Issuer issuer = this.saml.buildSAMLObject(Issuer.class); - issuer.setValue(context.getIssuer()); - auth.setIssuer(issuer); - auth.setDestination(context.getDestination()); - auth.setAssertionConsumerServiceURL(context.getAssertionConsumerServiceUrl()); - return this.saml.toXml( - auth, - credentials, - context.getIssuer() - ); + Issuer iss = this.saml.buildSamlObject(Issuer.DEFAULT_ELEMENT_NAME); + iss.setValue(issuer); + auth.setIssuer(iss); + auth.setDestination(destination); + auth.setAssertionConsumerServiceURL(assertionConsumerServiceUrl); + return auth; } /** diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlImplementation.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlImplementation.java index a049fc7d9c3..25dd4388e4a 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlImplementation.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlImplementation.java @@ -16,6 +16,16 @@ package org.springframework.security.saml2.provider.service.authentication; +import java.io.ByteArrayInputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; + import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import net.shibboleth.utilities.java.support.xml.BasicParserPool; import net.shibboleth.utilities.java.support.xml.SerializeSupport; @@ -24,13 +34,14 @@ import org.opensaml.core.config.InitializationException; import org.opensaml.core.config.InitializationService; import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.XMLObjectBuilderFactory; import org.opensaml.core.xml.config.XMLObjectProviderRegistry; import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; import org.opensaml.core.xml.io.MarshallerFactory; import org.opensaml.core.xml.io.MarshallingException; import org.opensaml.core.xml.io.UnmarshallerFactory; import org.opensaml.core.xml.io.UnmarshallingException; -import org.opensaml.saml.common.SignableSAMLObject; +import org.opensaml.saml.saml2.core.AuthnRequest; import org.opensaml.saml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver; import org.opensaml.security.SecurityException; import org.opensaml.security.credential.BasicCredential; @@ -47,28 +58,17 @@ import org.opensaml.xmlsec.signature.support.SignatureConstants; import org.opensaml.xmlsec.signature.support.SignatureException; import org.opensaml.xmlsec.signature.support.SignatureSupport; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + import org.springframework.security.saml2.Saml2Exception; import org.springframework.security.saml2.credentials.Saml2X509Credential; -import org.springframework.security.saml2.provider.service.authentication.Saml2Utils; import org.springframework.util.Assert; import org.springframework.web.util.UriUtils; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.xml.XMLConstants; -import javax.xml.namespace.QName; -import java.io.ByteArrayInputStream; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static java.util.Arrays.asList; -import static org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport.getBuilderFactory; import static org.springframework.util.StringUtils.hasText; /** @@ -76,6 +76,8 @@ */ final class OpenSamlImplementation { private static OpenSamlImplementation instance = new OpenSamlImplementation(); + private static XMLObjectBuilderFactory xmlObjectBuilderFactory = + XMLObjectProviderRegistrySupport.getBuilderFactory(); private final BasicParserPool parserPool = new BasicParserPool(); private final EncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver( @@ -167,37 +169,31 @@ EncryptedKeyResolver getEncryptedKeyResolver() { return this.encryptedKeyResolver; } - T buildSAMLObject(final Class clazz) { - try { - QName defaultElementName = (QName) clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null); - return (T) getBuilderFactory().getBuilder(defaultElementName).buildObject(defaultElementName); - } - catch (NoSuchFieldException | IllegalAccessException e) { - throw new Saml2Exception("Could not create SAML object", e); - } + T buildSamlObject(QName qName) { + return (T) xmlObjectBuilderFactory.getBuilder(qName).buildObject(qName); } XMLObject resolve(String xml) { return resolve(xml.getBytes(StandardCharsets.UTF_8)); } - String toXml(XMLObject object, List signingCredentials, String localSpEntityId) { - if (object instanceof SignableSAMLObject && null != hasSigningCredential(signingCredentials)) { - signXmlObject( - (SignableSAMLObject) object, - signingCredentials, - localSpEntityId - ); - } + String serialize(XMLObject xmlObject) { final MarshallerFactory marshallerFactory = XMLObjectProviderRegistrySupport.getMarshallerFactory(); try { - Element element = marshallerFactory.getMarshaller(object).marshall(object); + Element element = marshallerFactory.getMarshaller(xmlObject).marshall(xmlObject); return SerializeSupport.nodeToString(element); } catch (MarshallingException e) { throw new Saml2Exception(e); } } + String serialize(AuthnRequest authnRequest, List signingCredentials) { + if (hasSigningCredential(signingCredentials) != null) { + signAuthnRequest(authnRequest, signingCredentials); + } + return serialize(authnRequest); + } + /** * Returns query parameter after creating a Query String signature * All return values are unencoded and will need to be encoded prior to sending @@ -306,15 +302,15 @@ private Credential getSigningCredential(List signingCredent return cred; } - private void signXmlObject(SignableSAMLObject object, List signingCredentials, String entityId) { + private void signAuthnRequest(AuthnRequest authnRequest, List signingCredentials) { SignatureSigningParameters parameters = new SignatureSigningParameters(); - Credential credential = getSigningCredential(signingCredentials, entityId); + Credential credential = getSigningCredential(signingCredentials, authnRequest.getIssuer().getValue()); parameters.setSigningCredential(credential); parameters.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); parameters.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256); parameters.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); try { - SignatureSupport.signObject(object, parameters); + SignatureSupport.signObject(authnRequest, parameters); } catch (MarshallingException | SignatureException | SecurityException e) { throw new Saml2Exception(e); } 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 387302323e6..f2be29b1e79 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 @@ -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. @@ -20,8 +20,6 @@ import java.io.IOException; import java.io.ObjectOutputStream; -import org.springframework.security.core.Authentication; - import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.joda.time.DateTime; @@ -37,12 +35,14 @@ import org.opensaml.saml.saml2.core.NameID; import org.opensaml.saml.saml2.core.Response; +import org.springframework.security.core.Authentication; + import static java.util.Collections.emptyList; -import static org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationObjects.assertion; -import static org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationObjects.response; import static org.springframework.security.saml2.provider.service.authentication.Saml2CryptoTestSupport.encryptAssertion; import static org.springframework.security.saml2.provider.service.authentication.Saml2CryptoTestSupport.encryptNameId; import static org.springframework.security.saml2.provider.service.authentication.Saml2CryptoTestSupport.signXmlObject; +import static org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationObjects.assertion; +import static org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationObjects.response; import static org.springframework.security.saml2.provider.service.authentication.TestSaml2X509Credentials.assertingPartyCredentials; import static org.springframework.security.saml2.provider.service.authentication.TestSaml2X509Credentials.relyingPartyCredentials; import static org.springframework.test.util.AssertionErrors.assertTrue; @@ -95,7 +95,7 @@ public void supportsWhenNotSaml2AuthenticationTokenThenReturnFalse() { @Test public void authenticateWhenUnknownDataClassThenThrowAuthenticationException() { Assertion assertion = defaultAssertion(); - token = responseXml(assertion, idpEntityId); + token = responseXml(assertion); exception.expect(authenticationMatcher(Saml2ErrorCodes.UNKNOWN_RESPONSE_CLASS)); provider.authenticate(token); } @@ -116,7 +116,7 @@ public void authenticateWhenXmlErrorThenThrowAuthenticationException() { @Test public void authenticateWhenInvalidDestinationThenThrowAuthenticationException() { Response response = response(recipientUri + "invalid", idpEntityId); - token = responseXml(response, idpEntityId); + token = responseXml(response); exception.expect(authenticationMatcher(Saml2ErrorCodes.INVALID_DESTINATION)); provider.authenticate(token); } @@ -124,7 +124,7 @@ public void authenticateWhenInvalidDestinationThenThrowAuthenticationException() @Test public void authenticateWhenNoAssertionsPresentThenThrowAuthenticationException() { Response response = response(recipientUri, idpEntityId); - token = responseXml(response, idpEntityId); + token = responseXml(response); exception.expect( authenticationMatcher( Saml2ErrorCodes.MALFORMED_RESPONSE_DATA, @@ -139,7 +139,7 @@ public void authenticateWhenInvalidSignatureOnAssertionThenThrowAuthenticationEx Response response = response(recipientUri, idpEntityId); Assertion assertion = defaultAssertion(); response.getAssertions().add(assertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); exception.expect( authenticationMatcher( Saml2ErrorCodes.INVALID_SIGNATURE @@ -164,7 +164,7 @@ public void authenticateWhenOpenSAMLValidationErrorThenThrowAuthenticationExcept recipientEntityId ); response.getAssertions().add(assertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); exception.expect( authenticationMatcher( @@ -185,7 +185,7 @@ public void authenticateWhenMissingSubjectThenThrowAuthenticationException() { recipientEntityId ); response.getAssertions().add(assertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); exception.expect( authenticationMatcher( @@ -209,7 +209,7 @@ public void authenticateWhenUsernameMissingThenThrowAuthenticationException() th recipientEntityId ); response.getAssertions().add(assertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); exception.expect( authenticationMatcher( @@ -232,7 +232,7 @@ public void authenticateWhenAssertionContainsValidationAddressThenItSucceeds() t recipientEntityId ); response.getAssertions().add(assertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); provider.authenticate(token); } @@ -242,7 +242,7 @@ public void authenticateWhenEncryptedAssertionWithoutSignatureThenItFails() thro Assertion assertion = defaultAssertion(); EncryptedAssertion encryptedAssertion = encryptAssertion(assertion, assertingPartyCredentials()); response.getEncryptedAssertions().add(encryptedAssertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); exception.expect( authenticationMatcher( Saml2ErrorCodes.INVALID_SIGNATURE @@ -262,7 +262,7 @@ public void authenticateWhenEncryptedAssertionWithSignatureThenItSucceeds() thro ); EncryptedAssertion encryptedAssertion = encryptAssertion(assertion, assertingPartyCredentials()); response.getEncryptedAssertions().add(encryptedAssertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); provider.authenticate(token); } @@ -277,7 +277,7 @@ public void authenticateWhenEncryptedAssertionWithResponseSignatureThenItSucceed assertingPartyCredentials(), recipientEntityId ); - token = responseXml(response, idpEntityId); + token = responseXml(response); provider.authenticate(token); } @@ -295,7 +295,7 @@ public void authenticateWhenEncryptedNameIdWithSignatureThenItSucceeds() throws recipientEntityId ); response.getAssertions().add(assertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); provider.authenticate(token); } @@ -306,7 +306,7 @@ public void authenticateWhenDecryptionKeysAreMissingThenThrowAuthenticationExcep Assertion assertion = defaultAssertion(); EncryptedAssertion encryptedAssertion = encryptAssertion(assertion, assertingPartyCredentials()); response.getEncryptedAssertions().add(encryptedAssertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); token = new Saml2AuthenticationToken( token.getSaml2Response(), @@ -331,7 +331,7 @@ public void authenticateWhenDecryptionKeysAreWrongThenThrowAuthenticationExcepti Assertion assertion = defaultAssertion(); EncryptedAssertion encryptedAssertion = encryptAssertion(assertion, assertingPartyCredentials()); response.getEncryptedAssertions().add(encryptedAssertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); token = new Saml2AuthenticationToken( token.getSaml2Response(), @@ -361,7 +361,7 @@ public void writeObjectWhenTypeIsSaml2AuthenticationThenNoException() throws IOE ); EncryptedAssertion encryptedAssertion = encryptAssertion(assertion, assertingPartyCredentials()); response.getEncryptedAssertions().add(encryptedAssertion); - token = responseXml(response, idpEntityId); + token = responseXml(response); Saml2Authentication authentication = (Saml2Authentication) provider.authenticate(token); @@ -381,11 +381,8 @@ private Assertion defaultAssertion() { ); } - private Saml2AuthenticationToken responseXml( - XMLObject object, - String issuerEntityId - ) { - String xml = saml.toXml(object, emptyList(), issuerEntityId); + private Saml2AuthenticationToken responseXml(XMLObject assertion) { + String xml = saml.serialize(assertion); return new Saml2AuthenticationToken( xml, recipientUri, diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestSaml2AuthenticationObjects.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestSaml2AuthenticationObjects.java index acc9d9f2abd..d0a2a4f5535 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestSaml2AuthenticationObjects.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestSaml2AuthenticationObjects.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,6 +16,8 @@ package org.springframework.security.saml2.provider.service.authentication; +import java.util.UUID; + import org.joda.time.DateTime; import org.joda.time.Duration; import org.opensaml.saml.common.SAMLVersion; @@ -28,13 +30,11 @@ import org.opensaml.saml.saml2.core.SubjectConfirmation; import org.opensaml.saml.saml2.core.SubjectConfirmationData; -import java.util.UUID; - final class TestSaml2AuthenticationObjects { private static OpenSamlImplementation saml = OpenSamlImplementation.getInstance(); static Response response(String destination, String issuerEntityId) { - Response response = saml.buildSAMLObject(Response.class); + Response response = saml.buildSamlObject(Response.DEFAULT_ELEMENT_NAME); response.setID("R"+UUID.randomUUID().toString()); response.setIssueInstant(DateTime.now()); response.setVersion(SAMLVersion.VERSION_20); @@ -49,7 +49,7 @@ static Assertion assertion( String recipientEntityId, String recipientUri ) { - Assertion assertion = saml.buildSAMLObject(Assertion.class); + Assertion assertion = saml.buildSamlObject(Assertion.DEFAULT_ELEMENT_NAME); assertion.setID("A"+ UUID.randomUUID().toString()); assertion.setIssueInstant(DateTime.now()); assertion.setVersion(SAMLVersion.VERSION_20); @@ -69,13 +69,13 @@ static Assertion assertion( static Issuer issuer(String entityId) { - Issuer issuer = saml.buildSAMLObject(Issuer.class); + Issuer issuer = saml.buildSamlObject(Issuer.DEFAULT_ELEMENT_NAME); issuer.setValue(entityId); return issuer; } static Subject subject(String principalName) { - Subject subject = saml.buildSAMLObject(Subject.class); + Subject subject = saml.buildSamlObject(Subject.DEFAULT_ELEMENT_NAME); if (principalName != null) { subject.setNameID(nameId(principalName)); @@ -85,17 +85,17 @@ static Subject subject(String principalName) { } static NameID nameId(String principalName) { - NameID nameId = saml.buildSAMLObject(NameID.class); + NameID nameId = saml.buildSamlObject(NameID.DEFAULT_ELEMENT_NAME); nameId.setValue(principalName); return nameId; } static SubjectConfirmation subjectConfirmation() { - return saml.buildSAMLObject(SubjectConfirmation.class); + return saml.buildSamlObject(SubjectConfirmation.DEFAULT_ELEMENT_NAME); } static SubjectConfirmationData subjectConfirmationData(String recipient) { - SubjectConfirmationData subject = saml.buildSAMLObject(SubjectConfirmationData.class); + SubjectConfirmationData subject = saml.buildSamlObject(SubjectConfirmationData.DEFAULT_ELEMENT_NAME); subject.setRecipient(recipient); subject.setNotBefore(DateTime.now().minus(Duration.millis(5 * 60 * 1000))); subject.setNotOnOrAfter(DateTime.now().plus(Duration.millis(5 * 60 * 1000))); @@ -103,7 +103,7 @@ static SubjectConfirmationData subjectConfirmationData(String recipient) { } static Conditions conditions() { - Conditions conditions = saml.buildSAMLObject(Conditions.class); + Conditions conditions = saml.buildSamlObject(Conditions.DEFAULT_ELEMENT_NAME); conditions.setNotBefore(DateTime.now().minus(Duration.millis(5 * 60 * 1000))); conditions.setNotOnOrAfter(DateTime.now().plus(Duration.millis(5 * 60 * 1000))); return conditions;