diff --git a/core/pom.xml b/core/pom.xml
index bcf90b8b..9d7ccebd 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -44,13 +44,6 @@
true
-
-
- joda-time
- joda-time
- 2.10.6
-
-
org.apache.commons
diff --git a/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java b/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java
index 03932b2f..ec3b0abf 100644
--- a/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java
+++ b/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java
@@ -3,6 +3,8 @@
import java.io.IOException;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
@@ -16,8 +18,6 @@
import com.onelogin.saml2.model.hsm.HSM;
import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTime;
-import org.joda.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
@@ -297,10 +297,10 @@ public boolean isValid(String requestId) {
}
// Check the session Expiration
- DateTime sessionExpiration = this.getSessionNotOnOrAfter();
+ Instant sessionExpiration = this.getSessionNotOnOrAfter();
if (sessionExpiration != null) {
- sessionExpiration = sessionExpiration.plus(Constants.ALOWED_CLOCK_DRIFT * 1000);
- if (sessionExpiration.isEqualNow() || sessionExpiration.isBeforeNow()) {
+ sessionExpiration = ChronoUnit.SECONDS.addTo(sessionExpiration, Constants.ALOWED_CLOCK_DRIFT);
+ if (Util.isEqualNow(sessionExpiration) || Util.isBeforeNow(sessionExpiration)) {
throw new ValidationError("The attributes have expired, based on the SessionNotOnOrAfter of the AttributeStatement of this Response", ValidationError.SESSION_EXPIRED);
}
}
@@ -401,18 +401,18 @@ private void validateSubjectConfirmation(String responseInResponseTo) throws XPa
continue;
}
- DateTime noa = Util.parseDateTime(notOnOrAfter.getNodeValue());
- noa = noa.plus(Constants.ALOWED_CLOCK_DRIFT * 1000);
- if (noa.isEqualNow() || noa.isBeforeNow()) {
+ Instant noa = Util.parseDateTime(notOnOrAfter.getNodeValue());
+ noa = ChronoUnit.SECONDS.addTo(noa, Constants.ALOWED_CLOCK_DRIFT);
+ if (Util.isEqualNow(noa) || Util.isBeforeNow(noa)) {
validationIssues.add(new SubjectConfirmationIssue(i, "SubjectConfirmationData is no longer valid"));
continue;
}
Node notBefore = subjectConfirmationDataNodes.item(c).getAttributes().getNamedItem("NotBefore");
if (notBefore != null) {
- DateTime nb = Util.parseDateTime(notBefore.getNodeValue());
- nb = nb.minus(Constants.ALOWED_CLOCK_DRIFT * 1000);
- if (nb.isAfterNow()) {
+ Instant nb = Util.parseDateTime(notBefore.getNodeValue());
+ nb = ChronoUnit.SECONDS.addTo(nb, Constants.ALOWED_CLOCK_DRIFT * -1);
+ if (Util.isAfterNow(nb)) {
validationIssues.add(new SubjectConfirmationIssue(i, "SubjectConfirmationData is not yet valid"));
continue;
}
@@ -829,7 +829,7 @@ public List getIssuers() throws XPathExpressionException, ValidationErro
*
* @throws XPathExpressionException
*/
- public DateTime getSessionNotOnOrAfter() throws XPathExpressionException {
+ public Instant getSessionNotOnOrAfter() throws XPathExpressionException {
String notOnOrAfter = null;
NodeList entries = this.queryAssertion("/saml:AuthnStatement[@SessionNotOnOrAfter]");
if (entries.getLength() > 0) {
@@ -889,7 +889,7 @@ public List getAssertionNotOnOrAfter() throws XPathExpressionException
for (int i = 0; i < notOnOrAfterNodes.getLength(); i++) {
final Node notOnOrAfterAttribute = notOnOrAfterNodes.item(i).getAttributes().getNamedItem("NotOnOrAfter");
if (notOnOrAfterAttribute != null) {
- notOnOrAfters.add(new Instant(notOnOrAfterAttribute.getNodeValue()));
+ notOnOrAfters.add(Instant.parse(notOnOrAfterAttribute.getNodeValue()));
}}
return notOnOrAfters;
}
@@ -1053,17 +1053,17 @@ public boolean validateTimestamps() throws ValidationError {
Node naAttribute = attrName.getNamedItem("NotOnOrAfter");
// validate NotOnOrAfter
if (naAttribute != null) {
- DateTime notOnOrAfterDate = Util.parseDateTime(naAttribute.getNodeValue());
- notOnOrAfterDate = notOnOrAfterDate.plus(Constants.ALOWED_CLOCK_DRIFT * 1000);
- if (notOnOrAfterDate.isEqualNow() || notOnOrAfterDate.isBeforeNow()) {
+ Instant notOnOrAfterDate = Util.parseDateTime(naAttribute.getNodeValue());
+ notOnOrAfterDate = ChronoUnit.SECONDS.addTo(notOnOrAfterDate, Constants.ALOWED_CLOCK_DRIFT);
+ if (Util.isEqualNow(notOnOrAfterDate) || Util.isBeforeNow(notOnOrAfterDate)) {
throw new ValidationError("Could not validate timestamp: expired. Check system clock.", ValidationError.ASSERTION_EXPIRED);
}
}
// validate NotBefore
if (nbAttribute != null) {
- DateTime notBeforeDate = Util.parseDateTime(nbAttribute.getNodeValue());
- notBeforeDate = notBeforeDate.minus(Constants.ALOWED_CLOCK_DRIFT * 1000);
- if (notBeforeDate.isAfterNow()) {
+ Instant notBeforeDate = Util.parseDateTime(nbAttribute.getNodeValue());
+ notBeforeDate = ChronoUnit.SECONDS.addTo(notBeforeDate, Constants.ALOWED_CLOCK_DRIFT * -1);
+ if (Util.isAfterNow(notBeforeDate)) {
throw new ValidationError("Could not validate timestamp: not yet valid. Check system clock.", ValidationError.ASSERTION_TOO_EARLY);
}
}
@@ -1341,7 +1341,7 @@ public Calendar getResponseIssueInstant() throws ValidationError {
return null;
final Calendar result = Calendar.getInstance();
try {
- result.setTimeInMillis(Util.parseDateTime(issueInstantString).getMillis());
+ result.setTimeInMillis(Util.parseDateTime(issueInstantString).toEpochMilli());
} catch (final IllegalArgumentException e) {
throw new ValidationError(
"The Response IssueInstant attribute is not in the expected UTC form of ISO-8601 format",
diff --git a/core/src/main/java/com/onelogin/saml2/logout/LogoutRequest.java b/core/src/main/java/com/onelogin/saml2/logout/LogoutRequest.java
index 954ae9e9..83d51767 100644
--- a/core/src/main/java/com/onelogin/saml2/logout/LogoutRequest.java
+++ b/core/src/main/java/com/onelogin/saml2/logout/LogoutRequest.java
@@ -4,6 +4,7 @@
import java.net.URL;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
@@ -13,7 +14,6 @@
import javax.xml.xpath.XPathExpressionException;
import org.apache.commons.lang3.text.StrSubstitutor;
-import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
@@ -446,8 +446,8 @@ public Boolean isValid() {
// Check NotOnOrAfter
if (rootElement.hasAttribute("NotOnOrAfter")) {
String notOnOrAfter = rootElement.getAttribute("NotOnOrAfter");
- DateTime notOnOrAfterDate = Util.parseDateTime(notOnOrAfter);
- if (notOnOrAfterDate.isEqualNow() || notOnOrAfterDate.isBeforeNow()) {
+ Instant notOnOrAfterDate = Util.parseDateTime(notOnOrAfter);
+ if (Util.isEqualNow(notOnOrAfterDate) || Util.isBeforeNow(notOnOrAfterDate)) {
throw new ValidationError("Could not validate timestamp: expired. Check system clock.", ValidationError.RESPONSE_EXPIRED);
}
}
@@ -571,7 +571,7 @@ public static Calendar getIssueInstant(Document samlLogoutRequestDocument) {
if(issueInstantString == null)
return null;
issueInstant = Calendar.getInstance();
- issueInstant.setTimeInMillis(Util.parseDateTime(issueInstantString).getMillis());
+ issueInstant.setTimeInMillis(Util.parseDateTime(issueInstantString).toEpochMilli());
} catch (Exception e) {}
return issueInstant;
}
diff --git a/core/src/main/java/com/onelogin/saml2/logout/LogoutResponse.java b/core/src/main/java/com/onelogin/saml2/logout/LogoutResponse.java
index 8fc1bc65..c8427caf 100644
--- a/core/src/main/java/com/onelogin/saml2/logout/LogoutResponse.java
+++ b/core/src/main/java/com/onelogin/saml2/logout/LogoutResponse.java
@@ -611,7 +611,7 @@ public Calendar getIssueInstant() throws ValidationError {
return null;
final Calendar result = Calendar.getInstance();
try {
- result.setTimeInMillis(Util.parseDateTime(issueInstantString).getMillis());
+ result.setTimeInMillis(Util.parseDateTime(issueInstantString).toEpochMilli());
} catch (final IllegalArgumentException e) {
throw new ValidationError(
"The Response IssueInstant attribute is not in the expected UTC form of ISO-8601 format",
diff --git a/core/src/main/java/com/onelogin/saml2/util/Util.java b/core/src/main/java/com/onelogin/saml2/util/Util.java
index 8aa2cbe4..28034c34 100644
--- a/core/src/main/java/com/onelogin/saml2/util/Util.java
+++ b/core/src/main/java/com/onelogin/saml2/util/Util.java
@@ -27,13 +27,22 @@
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
+import java.time.Clock;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.Period;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalAmount;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
@@ -75,13 +84,6 @@
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.utils.XMLUtils;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-import org.joda.time.Period;
-import org.joda.time.format.DateTimeFormatter;
-import org.joda.time.format.ISODateTimeFormat;
-import org.joda.time.format.ISOPeriodFormat;
-import org.joda.time.format.PeriodFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Attr;
@@ -110,8 +112,7 @@ public final class Util {
*/
private static final Logger LOGGER = LoggerFactory.getLogger(Util.class);
- private static final DateTimeFormatter DATE_TIME_FORMAT = ISODateTimeFormat.dateTimeNoMillis().withZoneUTC();
- private static final DateTimeFormatter DATE_TIME_FORMAT_MILLS = ISODateTimeFormat.dateTime().withZoneUTC();
+ private static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneOffset.UTC);
public static final String UNIQUE_ID_PREFIX = "ONELOGIN_";
public static final String RESPONSE_SIGNATURE_XPATH = "/samlp:Response/ds:Signature";
public static final String ASSERTION_SIGNATURE_XPATH = "/samlp:Response/saml:Assertion/ds:Signature";
@@ -1826,10 +1827,10 @@ public static String generateUniqueID() {
*
* @return int The new timestamp, after the duration is applied.
*
- * @throws IllegalArgumentException
+ * @throws DateTimeParseException
*/
- public static long parseDuration(String duration) throws IllegalArgumentException {
- TimeZone timeZone = DateTimeZone.UTC.toTimeZone();
+ public static long parseDuration(String duration) throws DateTimeParseException {
+ TimeZone timeZone = TimeZone.getTimeZone(ZoneOffset.UTC);
return parseDuration(duration, Calendar.getInstance(timeZone).getTimeInMillis() / 1000);
}
@@ -1843,9 +1844,9 @@ public static long parseDuration(String duration) throws IllegalArgumentExceptio
*
* @return the new timestamp, after the duration is applied In Seconds.
*
- * @throws IllegalArgumentException
+ * @throws DateTimeParseException
*/
- public static long parseDuration(String durationString, long timestamp) throws IllegalArgumentException {
+ public static long parseDuration(String durationString, long timestamp) throws DateTimeParseException {
boolean haveMinus = false;
if (durationString.startsWith("-")) {
@@ -1853,26 +1854,30 @@ public static long parseDuration(String durationString, long timestamp) throws I
haveMinus = true;
}
- PeriodFormatter periodFormatter = ISOPeriodFormat.standard().withLocale(new Locale("UTC"));
- Period period = periodFormatter.parsePeriod(durationString);
+ TemporalAmount amount;
+ if (durationString.startsWith("PT")) {
+ amount = Duration.parse(durationString);
+ } else {
+ amount = Period.parse(durationString);
+ }
- DateTime dt = new DateTime(timestamp * 1000, DateTimeZone.UTC);
+ ZonedDateTime dt = Instant.ofEpochSecond(timestamp).atZone(ZoneOffset.UTC);
- DateTime result = null;
+ ZonedDateTime result;
if (haveMinus) {
- result = dt.minus(period);
+ result = dt.minus(amount);
} else {
- result = dt.plus(period);
+ result = dt.plus(amount);
}
- return result.getMillis() / 1000;
+ return result.toEpochSecond();
}
/**
* @return the unix timestamp that matches the current time.
*/
public static Long getCurrentTimeStamp() {
- DateTime currentDate = new DateTime(DateTimeZone.UTC);
- return currentDate.getMillis() / 1000;
+ ZonedDateTime currentDate = ZonedDateTime.now(clock);
+ return currentDate.toEpochSecond();
}
/**
@@ -1893,8 +1898,8 @@ public static long getExpireTime(String cacheDuration, String validUntil) {
}
if (validUntil != null && !StringUtils.isEmpty(validUntil)) {
- DateTime dt = Util.parseDateTime(validUntil);
- long validUntilTimeInt = dt.getMillis() / 1000;
+ Instant dt = Util.parseDateTime(validUntil);
+ long validUntilTimeInt = dt.toEpochMilli() / 1000;
if (expireTime == 0 || expireTime > validUntilTimeInt) {
expireTime = validUntilTimeInt;
}
@@ -1940,25 +1945,7 @@ public static long getExpireTime(String cacheDuration, long validUntil) {
* @return string with format yyyy-MM-ddTHH:mm:ssZ
*/
public static String formatDateTime(long timeInMillis) {
- return DATE_TIME_FORMAT.print(timeInMillis);
- }
-
- /**
- * Create string form time In Millis with format yyyy-MM-ddTHH:mm:ssZ
- *
- * @param time
- * The time
- * @param millis
- * Defines if the time is in Millis
- *
- * @return string with format yyyy-MM-ddTHH:mm:ssZ
- */
- public static String formatDateTime(long time, boolean millis) {
- if (millis) {
- return DATE_TIME_FORMAT_MILLS.print(time);
- } else {
- return formatDateTime(time);
- }
+ return DATE_TIME_FORMAT.format(Instant.ofEpochMilli(timeInMillis));
}
/**
@@ -1969,15 +1956,9 @@ public static String formatDateTime(long time, boolean millis) {
*
* @return datetime
*/
- public static DateTime parseDateTime(String dateTime) {
-
- DateTime parsedData = null;
- try {
- parsedData = DATE_TIME_FORMAT.parseDateTime(dateTime);
- } catch(Exception e) {
- return DATE_TIME_FORMAT_MILLS.parseDateTime(dateTime);
- }
- return parsedData;
+ public static Instant parseDateTime(String dateTime) {
+ TemporalAccessor parsedData = DATE_TIME_FORMAT.parse(dateTime);
+ return Instant.from(parsedData);
}
/**
@@ -2007,5 +1988,53 @@ private static byte[] toBytesUtf8(String str) {
}
}
+ private static Clock clock = Clock.systemUTC();
+
+ /**
+ * Get current timestamp milliseconds.
+ *
+ * @return current timestamp
+ */
+ public static long getCurrentTimeMillis() {
+ return clock.millis();
+ }
+
+ static void setFixedClock(Clock fixClock) {
+ clock = fixClock;
+ }
+
+ static void setSystemClock() {
+ clock = Clock.systemUTC();
+ }
+
+ /**
+ * Checks if specified instant is equal to now.
+ *
+ * @param instant the instant to compare to
+ * @return true if instant is equal to now
+ */
+ public static boolean isEqualNow(Instant instant) {
+ return instant.equals(Instant.now(clock));
+ }
+
+ /**
+ * Checks if specified instant is before now.
+ *
+ * @param instant the instant to compare to
+ * @return true if instant is before now
+ */
+ public static boolean isBeforeNow(Instant instant) {
+ return instant.isBefore(Instant.now(clock));
+ }
+
+ /**
+ * Checks if specified instant is after now.
+ *
+ * @param instant the instant to compare to
+ * @return true if instant is before now
+ */
+ public static boolean isAfterNow(Instant instant) {
+ return instant.isAfter(Instant.now(clock));
+ }
}
diff --git a/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java b/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java
index 3d960ca7..7cec9efa 100644
--- a/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java
+++ b/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java
@@ -10,13 +10,10 @@
import com.onelogin.saml2.settings.Saml2Settings;
import com.onelogin.saml2.settings.SettingsBuilder;
import com.onelogin.saml2.util.Constants;
+import com.onelogin.saml2.util.DateTimeTestUtils;
import com.onelogin.saml2.util.Util;
import org.hamcrest.Matchers;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeUtils;
-import org.joda.time.Instant;
-import org.joda.time.format.ISODateTimeFormat;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -28,6 +25,7 @@
import org.xml.sax.SAXException;
import java.io.IOException;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -61,13 +59,13 @@ public class AuthnResponseTest {
@Before
public void setDateTime() {
- //All calls to Joda time check will use this timestamp as "now" value :
- setDateTime("2020-06-01T00:00:00Z");
+ //All calls to time check will use this timestamp as "now" value :
+ DateTimeTestUtils.setFixedDateTime("2020-06-01T00:00:00Z");
}
@After
public void goBackToNormal() {
- DateTimeUtils.setCurrentMillisSystem();
+ DateTimeTestUtils.setCurrentMillisSystem();
}
/**
@@ -1157,7 +1155,7 @@ public void testGetAssertionDetails() throws IOException, Error, XPathExpression
final List notOnOrAfters = samlResponse.getAssertionNotOnOrAfter();
assertEquals("pfxa46574df-b3b0-a06a-23c8-636413198772", samlResponse.getAssertionId());
- assertThat(notOnOrAfters, contains(new Instant("2010-11-18T22:02:37Z")));
+ assertThat(notOnOrAfters, contains(Instant.parse("2010-11-18T22:02:37Z")));
}
@@ -1170,7 +1168,7 @@ public void testGetAssertionDetails_encrypted() throws IOException, Error, XPath
final List notOnOrAfters = samlResponse.getAssertionNotOnOrAfter();
assertEquals("_519c2712648ee09a06d1f9a08e9e835715fea60267", samlResponse.getAssertionId());
- assertThat(notOnOrAfters, contains(new Instant("2055-06-07T20:17:08Z")));
+ assertThat(notOnOrAfters, contains(Instant.parse("2055-06-07T20:17:08Z")));
}
@@ -1187,7 +1185,7 @@ public void testGetAssertionDetails_multiple() throws Exception {
final List notOnOrAfters = samlResponse.getAssertionNotOnOrAfter();
assertEquals("pfx7841991c-c73f-4035-e2ee-c170c0e1d3e4", samlResponse.getAssertionId());
- assertThat(notOnOrAfters, contains(new Instant("2120-06-17T14:53:44Z"), new Instant("2010-06-17T14:53:44Z")));
+ assertThat(notOnOrAfters, contains(Instant.parse("2120-06-17T14:53:44Z"), Instant.parse("2010-06-17T14:53:44Z")));
}
/**
@@ -1449,7 +1447,7 @@ public void testGetSessionNotOnOrAfter() throws IOException, Error, XPathExpress
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
- assertEquals(1290203857000L, samlResponse.getSessionNotOnOrAfter().getMillis());
+ assertEquals(1290203857000L, samlResponse.getSessionNotOnOrAfter().toEpochMilli());
samlResponseEncoded = Util.getFileAsString("data/responses/response2.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
@@ -1457,7 +1455,7 @@ public void testGetSessionNotOnOrAfter() throws IOException, Error, XPathExpress
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
- assertEquals(2696012228000L, samlResponse.getSessionNotOnOrAfter().getMillis());
+ assertEquals(2696012228000L, samlResponse.getSessionNotOnOrAfter().toEpochMilli());
}
/**
@@ -2310,17 +2308,17 @@ public void testParseAzureB2CTimestamp() throws IOException, Error, XPathExpress
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setStrict(true);
- setDateTime("2020-07-16T07:57:00Z");
+ DateTimeTestUtils.setFixedDateTime("2020-07-16T07:57:00Z");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("A valid SubjectConfirmation was not found on this Response: SubjectConfirmationData doesn't match a valid Recipient", samlResponse.getError());
- setDateTime("2020-07-01T00:00:00Z");
+ DateTimeTestUtils.setFixedDateTime("2020-07-01T00:00:00Z");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Could not validate timestamp: not yet valid. Check system clock.", samlResponse.getError());
- setDateTime("2020-08-01T00:00:00Z");
+ DateTimeTestUtils.setFixedDateTime("2020-08-01T00:00:00Z");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Could not validate timestamp: expired. Check system clock.", samlResponse.getError());
@@ -3333,9 +3331,5 @@ private static HttpRequest newHttpRequest(String requestURL, String samlResponse
return new HttpRequest(requestURL, (String)null).addParameter("SAMLResponse", samlResponseEncoded);
}
- private void setDateTime(String ISOTimeStamp) {
- DateTime dateTime = ISODateTimeFormat.dateTimeNoMillis().withZoneUTC().parseDateTime(ISOTimeStamp);
- DateTimeUtils.setCurrentMillisFixed(dateTime.toDate().getTime());
- }
}
diff --git a/core/src/test/java/com/onelogin/saml2/test/util/UtilsTest.java b/core/src/test/java/com/onelogin/saml2/test/util/UtilsTest.java
index 2b047bc1..13012543 100644
--- a/core/src/test/java/com/onelogin/saml2/test/util/UtilsTest.java
+++ b/core/src/test/java/com/onelogin/saml2/test/util/UtilsTest.java
@@ -31,6 +31,8 @@
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
+import java.time.Instant;
+import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -41,7 +43,6 @@
import org.apache.commons.codec.binary.Base64;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.signature.XMLSignatureException;
-import org.joda.time.DateTime;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -1947,7 +1948,7 @@ public void testGenerateUniqueID_usesDefaultOnEmpty() {
*
* @see com.onelogin.saml2.util.Util#parseDuration
*/
- @Test(expected=IllegalArgumentException.class)
+ @Test(expected=DateTimeParseException.class)
public void testParseDurationException() throws Exception {
long timestamp = 1393876825L;// 2014-03-03 21:00:25
long parsedDuration = Util.parseDuration("aaa", timestamp);
@@ -1982,8 +1983,8 @@ public void testParseDuration() throws Exception {
try {
String invalidDuration = "PT1Y";
Util.parseDuration(invalidDuration);
- } catch (IllegalArgumentException anIllegalArgumentException) {
- assertThat(anIllegalArgumentException.getMessage(), is("Invalid format: \"PT1Y\" is malformed at \"1Y\""));
+ } catch (DateTimeParseException anDateTimeParseException) {
+ assertThat(anDateTimeParseException.getMessage(), is("Text cannot be parsed to a Duration"));
}
}
@@ -2057,13 +2058,13 @@ public void testFormatDateTime() {
public void testParseDateTime() {
long time = 1386650371L;
String datetime = "2013-12-10T04:39:31Z";
- DateTime parsedTime = Util.parseDateTime(datetime);
- assertEquals(time, parsedTime.getMillis() / 1000);
+ Instant parsedTime = Util.parseDateTime(datetime);
+ assertEquals(time, parsedTime.toEpochMilli() / 1000);
// Now test if toolkit supports miliseconds
String datetime2 = "2013-12-10T04:39:31.120Z";
- DateTime parsedTime2 = Util.parseDateTime(datetime2);
- assertEquals(time, parsedTime2.getMillis() / 1000);
+ Instant parsedTime2 = Util.parseDateTime(datetime2);
+ assertEquals(time, parsedTime2.toEpochMilli() / 1000);
}
/**
diff --git a/core/src/test/java/com/onelogin/saml2/util/DateTimeTestUtils.java b/core/src/test/java/com/onelogin/saml2/util/DateTimeTestUtils.java
new file mode 100644
index 00000000..0321fb3e
--- /dev/null
+++ b/core/src/test/java/com/onelogin/saml2/util/DateTimeTestUtils.java
@@ -0,0 +1,24 @@
+package com.onelogin.saml2.util;
+
+import java.time.Clock;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+public class DateTimeTestUtils {
+
+ /**
+ * Use system clock as "now".
+ */
+ public static void setCurrentMillisSystem() {
+ Util.setSystemClock();
+ }
+
+ /**
+ * Use provided dateTime as "now".
+ *
+ * @param dateTime the timestamp
+ */
+ public static void setFixedDateTime(String dateTime) {
+ Util.setFixedClock(Clock.fixed(ZonedDateTime.parse(dateTime).toInstant(), ZoneOffset.UTC));
+ }
+}
diff --git a/toolkit/pom.xml b/toolkit/pom.xml
index 37d2f787..3cb2ab03 100644
--- a/toolkit/pom.xml
+++ b/toolkit/pom.xml
@@ -65,13 +65,6 @@
provided
-
-
- joda-time
- joda-time
- 2.10.6
-
-
org.apache.commons
diff --git a/toolkit/src/main/java/com/onelogin/saml2/Auth.java b/toolkit/src/main/java/com/onelogin/saml2/Auth.java
index 6d035df9..9d8f29cb 100644
--- a/toolkit/src/main/java/com/onelogin/saml2/Auth.java
+++ b/toolkit/src/main/java/com/onelogin/saml2/Auth.java
@@ -5,6 +5,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SignatureException;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
@@ -17,8 +18,6 @@
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTime;
-import org.joda.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -100,7 +99,7 @@ public class Auth {
/**
* SessionNotOnOrAfter. When the user is logged, this stored it from the AuthnStatement of the SAML Response
*/
- private DateTime sessionExpiration;
+ private Instant sessionExpiration;
/**
* The ID of the last message processed
@@ -1453,7 +1452,7 @@ public final String getSessionIndex() {
/**
* @return the SessionNotOnOrAfter of the assertion
*/
- public final DateTime getSessionExpiration() {
+ public final Instant getSessionExpiration() {
return sessionExpiration;
}
diff --git a/toolkit/src/test/java/com/onelogin/saml2/test/AuthTest.java b/toolkit/src/test/java/com/onelogin/saml2/test/AuthTest.java
index cd45125f..53c82ef5 100644
--- a/toolkit/src/test/java/com/onelogin/saml2/test/AuthTest.java
+++ b/toolkit/src/test/java/com/onelogin/saml2/test/AuthTest.java
@@ -30,6 +30,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -40,7 +41,6 @@
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-import org.joda.time.Instant;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -1244,7 +1244,7 @@ public void testGetAssertionDetails() throws Exception {
auth.processResponse();
assertThat(auth.getLastAssertionId(), is("pfxb26bb203-4e9d-8e74-a46e-def275ff4c7b"));
- assertThat(auth.getLastAssertionNotOnOrAfter(), contains(new Instant("2053-08-23T06:57:01Z")));
+ assertThat(auth.getLastAssertionNotOnOrAfter(), contains(Instant.parse("2053-08-23T06:57:01Z")));
}
/**
@@ -1275,7 +1275,7 @@ public void testGetSessionExpiration() throws Exception {
assertNull(auth2.getSessionExpiration());
auth2.processResponse();
assertTrue(auth2.isAuthenticated());
- assertEquals(2639545021000L, auth2.getSessionExpiration().getMillis());
+ assertEquals(2639545021000L, auth2.getSessionExpiration().toEpochMilli());
}
/**