Skip to content

Commit f5a9c21

Browse files
author
Corentin Groix
committed
Add precise timestamp support
Azure Active Directory B2C issue saml response with sub millisecond timestamps, which could not be parsed. This commit change the parser using pitbulk tip #263 and a test using an almost real life response.
1 parent f81b6d7 commit f5a9c21

3 files changed

Lines changed: 32 additions & 4 deletions

File tree

core/src/main/java/com/onelogin/saml2/util/Util.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@
6767
import org.joda.time.DateTime;
6868
import org.joda.time.DateTimeZone;
6969
import org.joda.time.Period;
70-
import org.joda.time.format.DateTimeFormat;
7170
import org.joda.time.format.DateTimeFormatter;
71+
import org.joda.time.format.ISODateTimeFormat;
7272
import org.joda.time.format.ISOPeriodFormat;
7373
import org.joda.time.format.PeriodFormatter;
7474
import org.slf4j.Logger;
@@ -95,9 +95,9 @@ public final class Util {
9595
* Private property to construct a logger for this class.
9696
*/
9797
private static final Logger LOGGER = LoggerFactory.getLogger(Util.class);
98-
99-
private static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'").withZone(DateTimeZone.UTC);
100-
private static final DateTimeFormatter DATE_TIME_FORMAT_MILLS = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(DateTimeZone.UTC);
98+
99+
private static final DateTimeFormatter DATE_TIME_FORMAT = ISODateTimeFormat.dateTimeNoMillis().withZoneUTC();
100+
private static final DateTimeFormatter DATE_TIME_FORMAT_MILLS = ISODateTimeFormat.dateTime().withZoneUTC();
101101
public static final String UNIQUE_ID_PREFIX = "ONELOGIN_";
102102
public static final String RESPONSE_SIGNATURE_XPATH = "/samlp:Response/ds:Signature";
103103
public static final String ASSERTION_SIGNATURE_XPATH = "/samlp:Response/saml:Assertion/ds:Signature";

core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,6 +1866,33 @@ public void testDatetimeWithMiliseconds() throws IOException, Error, XPathExpres
18661866
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
18671867
}
18681868

1869+
@Test
1870+
public void testParseAzureB2CTimestamp() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
1871+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
1872+
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/redacted_azure_b2c.xml.base64");
1873+
1874+
settings.setStrict(false);
1875+
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
1876+
assertFalse(samlResponse.isValid());
1877+
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
1878+
1879+
settings.setStrict(true);
1880+
setDateTime("2020-07-16T07:57:00Z");
1881+
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
1882+
assertFalse(samlResponse.isValid());
1883+
assertEquals("A valid SubjectConfirmation was not found on this Response: SubjectConfirmationData doesn't match a valid Recipient", samlResponse.getError());
1884+
1885+
setDateTime("2020-07-01T00:00:00Z");
1886+
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
1887+
assertFalse(samlResponse.isValid());
1888+
assertEquals("Could not validate timestamp: not yet valid. Check system clock.", samlResponse.getError());
1889+
1890+
setDateTime("2020-08-01T00:00:00Z");
1891+
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
1892+
assertFalse(samlResponse.isValid());
1893+
assertEquals("Could not validate timestamp: expired. Check system clock.", samlResponse.getError());
1894+
}
1895+
18691896
/**
18701897
* Tests the isValid method of SamlResponse
18711898
* Case: invalid requestId
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIElEPSJfNGQyMmRiOTItNzkzMS00OWU4LTkyMGQtNWUwMmYzMDQyNWEzIiBJblJlc3BvbnNlVG89Ik9ORUxPR0lOXzM0NTU0OGMwLWFhYmItNGY0Mi04ZDNjLThiY2YzNDRiYjE3NyIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMjAtMDctMTZUMDc6NTQ6NTAuMTA3NjkxMVoiIERlc3RpbmF0aW9uPSJodHRwOi8vbG9jYWxob3N0OjgwODAvamF2YS1zYW1sLWpzcHNhbXBsZS9hY3MuanNwIiB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIj48c2FtbDpJc3N1ZXIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDplbnRpdHkiPmh0dHA6Ly9pZHAuZXhhbXBsZS5jb20vPC9zYW1sOklzc3Vlcj48c2FtbHA6U3RhdHVzPjxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiIC8+PC9zYW1scDpTdGF0dXM+PHNhbWw6QXNzZXJ0aW9uIElEPSJfYjU2M2FmMTQtNTFjMC00YTA3LTlhYTYtNDk1MDkxNjBmODAwIiBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAyMC0wNy0xNlQwNzo1NDo1MC4wNzY0NDAzWiI+PHNhbWw6SXNzdWVyIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5odHRwOi8vaWRwLmV4YW1wbGUuY29tLzwvc2FtbDpJc3N1ZXI+PHNhbWw6U3ViamVjdD48c2FtbDpOYW1lSUQ+NDhkNGQ3YjgtODU5MC00ZjQ2LWJmN2MtNzYxNTIzMjdkZjE2PC9zYW1sOk5hbWVJRD48c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+PHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgTm90T25PckFmdGVyPSIyMDIwLTA3LTE2VDA3OjU5OjUwLjA3NjQ0MDNaIiBSZWNpcGllbnQ9Imh0dHBzOi8vWlpaLWZvb2Jhci5YWFguY29tLy9Mb2dpbi5odG1sIiBJblJlc3BvbnNlVG89Ik9ORUxPR0lOXzM0NTU0OGMwLWFhYmItNGY0Mi04ZDNjLThiY2YzNDRiYjE3NyIgLz48L3NhbWw6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWw6U3ViamVjdD48c2FtbDpDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAyMC0wNy0xNlQwNzo1NDo1MC4wNzY0NDAzWiIgTm90T25PckFmdGVyPSIyMDIwLTA3LTE2VDA3OjU5OjUwLjA3NjQ0MDNaIj48c2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjxzYW1sOkF1ZGllbmNlPmh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9qYXZhLXNhbWwtanNwc2FtcGxlL21ldGFkYXRhLmpzcDwvc2FtbDpBdWRpZW5jZT48L3NhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj48L3NhbWw6Q29uZGl0aW9ucz48c2FtbDpBdXRoblN0YXRlbWVudCBTZXNzaW9uSW5kZXg9ImM1MzczMDFmLTUxMmMtNDk3MS05NTIwLWFiNTNhNDA0MzA5NiIgQXV0aG5JbnN0YW50PSIyMDIwLTA3LTE2VDA3OjU0OjUwLjA3NjQ0MDNaIj48c2FtbDpBdXRobkNvbnRleHQ+PHNhbWw6QXV0aG5Db250ZXh0Q2xhc3NSZWY+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFjOmNsYXNzZXM6dW5zcGVjaWZpZWQ8L3NhbWw6QXV0aG5Db250ZXh0Q2xhc3NSZWY+PC9zYW1sOkF1dGhuQ29udGV4dD48L3NhbWw6QXV0aG5TdGF0ZW1lbnQ+PHNhbWw6QXR0cmlidXRlU3RhdGVtZW50IHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSI+PHNhbWw6QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2dpdmVubmFtZSIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiIEZyaWVuZGx5TmFtZT0iRmlyc3QgTmFtZSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+WVlZPC9zYW1sOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDpBdHRyaWJ1dGU+PHNhbWw6QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3N1cm5hbWUiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIiBGcmllbmRseU5hbWU9Ikxhc3QgTmFtZSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+WFhYPC9zYW1sOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDpBdHRyaWJ1dGU+PHNhbWw6QXR0cmlidXRlIE5hbWU9Imdyb3VwIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIiBGcmllbmRseU5hbWU9IlhYIEFjY2VzcyBHcm91cHMiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czphbnlUeXBlIj5kZWFsZXI8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0iRW1haWxhZGRyZXNzIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIiBGcmllbmRseU5hbWU9IlByaW1hcnkgRW1haWwgQWRkcmVzcyI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+WVlZLlhYWEBtYWlsaW5hdG9yLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL2lkZW50aXR5L2NsYWltcy9vYmplY3RpZGVudGlmaWVyIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSIgRnJpZW5kbHlOYW1lPSJVc2VyJ3MgT2JqZWN0IElEIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj40OGQ0ZDdiOC04NTkwLTRmNDYtYmY3Yy03NjE1MjMyN2RmMTY8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48L3NhbWw6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDpBc3NlcnRpb24+PC9zYW1scDpSZXNwb25zZT4=

0 commit comments

Comments
 (0)