+
- org.apache.tomcat.maven
- tomcat7-maven-plugin
- 2.2
+ org.eclipse.jetty
+ jetty-maven-plugin
+ 9.4.53.v20231009
- 8080
- 8443
- ${project.basedir}/../misc/ssl-demo.pfx
- Test1234
- /oiosaml3-demo.java
+
+ /oiosaml3-demo.java
+
+ ${project.basedir}/src/main/jetty/jetty-https.xml
+
+
+ demo.keystore.path
+ ${project.basedir}/../misc/ssl-demo.pfx
+
+
+ demo.keystore.password
+ Test1234
+
+
@@ -46,7 +57,7 @@
javax.servlet
javax.servlet-api
- 3.0.1
+ 3.1.0
provided
diff --git a/demo/src/main/jetty/jetty-https.xml b/demo/src/main/jetty/jetty-https.xml
new file mode 100644
index 0000000..73d9f97
--- /dev/null
+++ b/demo/src/main/jetty/jetty-https.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+ https
+ 8443
+
+
+
+
+
+
+
+
+
+ PKCS12
+
+
+
+
+
+
+
+
+
+
+ -
+
+ http/1.1
+
+
+
+ -
+
+
+
+
+
+
+ 8443
+
+
+
+
+
diff --git a/oiosaml/pom.xml b/oiosaml/pom.xml
index 79cee13..abdad86 100644
--- a/oiosaml/pom.xml
+++ b/oiosaml/pom.xml
@@ -150,7 +150,7 @@
javax.servlet
javax.servlet-api
- 3.0.1
+ 3.1.0
provided
diff --git a/oiosaml/src/main/java/dk/gov/oio/saml/servlet/AssertionHandler.java b/oiosaml/src/main/java/dk/gov/oio/saml/servlet/AssertionHandler.java
index 2a31227..175f14c 100644
--- a/oiosaml/src/main/java/dk/gov/oio/saml/servlet/AssertionHandler.java
+++ b/oiosaml/src/main/java/dk/gov/oio/saml/servlet/AssertionHandler.java
@@ -142,6 +142,9 @@ public void handlePost(HttpServletRequest httpServletRequest, HttpServletRespons
AssertionWrapper assertionWrapper = new AssertionWrapper(assertion);
+ // The session is authenticated from here, so it must not keep the id it had before login
+ rotateSessionId(httpServletRequest, sessionHandler, authnRequest);
+
sessionHandler.storeAssertion(session, assertionWrapper);
OIOSAML3Service.getAuditService().auditLog(AuditRequestUtil
@@ -159,4 +162,17 @@ public void handlePost(HttpServletRequest httpServletRequest, HttpServletRespons
httpServletResponse.sendRedirect(url);
}
+
+ /**
+ * Give the session a new id now that it carries an authenticated user, so an id planted in the browser
+ * before login cannot be used afterwards.
+ *
+ * Session state is keyed on the container session id, so the in-flight AuthnRequest is stored again
+ * under the new id.
+ */
+ private void rotateSessionId(HttpServletRequest httpServletRequest, SessionHandler sessionHandler, AuthnRequestWrapper authnRequest) throws InternalException {
+ httpServletRequest.changeSessionId();
+
+ sessionHandler.storeAuthnRequest(httpServletRequest.getSession(), authnRequest);
+ }
}
diff --git a/oiosaml/src/test/java/dk/gov/oio/saml/servlet/AssertionHandlerTest.java b/oiosaml/src/test/java/dk/gov/oio/saml/servlet/AssertionHandlerTest.java
index 05f30c4..4b1041d 100644
--- a/oiosaml/src/test/java/dk/gov/oio/saml/servlet/AssertionHandlerTest.java
+++ b/oiosaml/src/test/java/dk/gov/oio/saml/servlet/AssertionHandlerTest.java
@@ -20,6 +20,7 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mockito;
import org.opensaml.core.xml.util.XMLObjectSupport;
import org.opensaml.messaging.context.MessageContext;
@@ -85,6 +86,47 @@ public void testPostWithValidAssertion() throws Exception {
Assertions.assertEquals(assertionWrapperArgumentCaptor.getValue().getNsisLevel(), NSISLevel.SUBSTANTIAL);
}
+ @DisplayName("Test that handler changes the session id when the assertion is accepted")
+ @Test
+ public void testPostWithValidAssertionChangesSessionId() throws Exception {
+ // Create MessageContext, Response and Assertion
+ String nameID = "https://data.gov.dk/model/core/eid/person/uuid/37a5a1aa-67ce-4f70-b7c0-b8e678d585f7";
+ String inResponseToId = UUID.randomUUID().toString();
+ MessageContext messageContext = IdpUtil.createMessageWithAssertion(true, true, true, nameID, TestConstants.SP_ENTITY_ID, TestConstants.SP_ASSERTION_CONSUMER_URL, inResponseToId);
+
+ Element marshalledMessage = XMLObjectSupport.marshall(messageContext.getMessage());
+ String base64EncodedMessage = Base64Support.encode(SerializeSupport.nodeToString(marshalledMessage).getBytes("UTF-8"), Base64Support.UNCHUNKED);
+
+ // Create AuthnRequest
+ AuthnRequestService authnRequestService = new AuthnRequestService();
+ MessageContext authnRequestMessageContext = authnRequestService.createMessageWithAuthnRequest(false, false, NSISLevel.SUBSTANTIAL, null, null);
+ AuthnRequest authnRequest = (AuthnRequest) authnRequestMessageContext.getMessage();
+ authnRequest.setID(inResponseToId);
+ AuthnRequestWrapper wrapper = new AuthnRequestWrapper(authnRequest, NSISLevel.SUBSTANTIAL, "");
+
+ SessionHandler sessionHandler = OIOSAML3Service.getSessionHandlerFactory().getHandler();
+ Mockito.when(sessionHandler.getAuthnRequest(session)).thenReturn(wrapper);
+
+ HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+ Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer(TestConstants.SP_ASSERTION_CONSUMER_URL));
+ Mockito.when(request.getSession()).thenReturn(session);
+ Mockito.when(request.getMethod()).thenReturn("POST");
+ Mockito.when(request.getParameter("RelayState")).thenReturn(null);
+ Mockito.when(request.getParameter("SAMLResponse")).thenReturn(base64EncodedMessage);
+
+ HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
+
+ new AssertionHandler().handlePost(request, response);
+
+ Mockito.verify(request).changeSessionId();
+
+ // Session state is keyed on the container session id, so the AuthnRequest follows the session
+ InOrder inOrder = Mockito.inOrder(request, sessionHandler);
+ inOrder.verify(request).changeSessionId();
+ inOrder.verify(sessionHandler).storeAuthnRequest(session, wrapper);
+ inOrder.verify(sessionHandler).storeAssertion(Mockito.eq(session), Mockito.any(AssertionWrapper.class));
+ }
+
@DisplayName("Test that handler will reject am invalid assertion")
@Test
public void testPostWithInvalidAssertion() throws Exception {
diff --git a/oiosaml/src/test/java/dk/gov/oio/saml/servlet/LogoutRequestHandlerTest.java b/oiosaml/src/test/java/dk/gov/oio/saml/servlet/LogoutRequestHandlerTest.java
index 3399499..ccac42f 100644
--- a/oiosaml/src/test/java/dk/gov/oio/saml/servlet/LogoutRequestHandlerTest.java
+++ b/oiosaml/src/test/java/dk/gov/oio/saml/servlet/LogoutRequestHandlerTest.java
@@ -7,6 +7,7 @@
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
+import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
@@ -196,6 +197,21 @@ public void testIdPSOAPLogoutRequestWhenLoggedIn() throws Exception {
public int read() throws IOException {
return inputStream.read();
}
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+ //Do nothing
+ }
});
// Mock DummyOutputStream
@@ -390,6 +406,21 @@ public void testSOAPLogoutRequestWhenNotLoggedIn() throws Exception {
public int read() throws IOException {
return inputStream.read();
}
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+ //Do nothing
+ }
});
// Mock DummyOutputStream
diff --git a/oiosaml/src/test/java/dk/gov/oio/saml/servlet/LogoutResponseHandlerTest.java b/oiosaml/src/test/java/dk/gov/oio/saml/servlet/LogoutResponseHandlerTest.java
index d5fca57..fa208f3 100644
--- a/oiosaml/src/test/java/dk/gov/oio/saml/servlet/LogoutResponseHandlerTest.java
+++ b/oiosaml/src/test/java/dk/gov/oio/saml/servlet/LogoutResponseHandlerTest.java
@@ -7,6 +7,7 @@
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@@ -110,5 +111,15 @@ private class DummyOutputStream extends ServletOutputStream {
public void write(int i) throws IOException {
//Do nothing
}
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener writeListener) {
+ //Do nothing
+ }
}
}
diff --git a/oiosaml/src/test/java/dk/gov/oio/saml/util/TestConstants.java b/oiosaml/src/test/java/dk/gov/oio/saml/util/TestConstants.java
index 0953299..8b3b369 100644
--- a/oiosaml/src/test/java/dk/gov/oio/saml/util/TestConstants.java
+++ b/oiosaml/src/test/java/dk/gov/oio/saml/util/TestConstants.java
@@ -151,8 +151,11 @@ public class TestConstants {
// Value of the specVersion attribute in the OIOSAML Web SSO profiles, see [OIO-ALG-01] chapter 6
public static final String SPEC_VERSION_OIOSAML_30 = "OIO-SAML-3.0";
public static final String SPEC_VERSION_OIOSAML_40 = "https://data.gov.dk/saml/profile/oio/4.0.0/";
-
- public static final String VALID_CERTIFICATE = "MIIGkzCCBMegAwIBAgIUdxCsIBOOtB5tqNtriG1TMHD9dqYwQQYJKoZIhvcNAQEKMDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEFAKIDAgEgMGsxLTArBgNVBAMMJERlbiBEYW5za2UgU3RhdCBPQ0VTIHVkc3RlZGVuZGUtQ0EgMTETMBEGA1UECwwKVGVzdCAtIGN0aTEYMBYGA1UECgwPRGVuIERhbnNrZSBTdGF0MQswCQYDVQQGEwJESzAeFw0yMzA4MTgxMDI2NThaFw0yNjA4MTcxMDI2NTdaMIGpMSUwIwYDVQQDDBxqYXZhLnJlZmVyZW5jZWltcGxlbWVudGVyaW5nMTcwNQYDVQQFEy5VSTpESy1POkc6MmRjZjc5MTktYjI4Mi00NGQxLWI5ODAtM2I3MzcwMGE3ZGQ0MSEwHwYDVQQKDBhEaWdpdGFsaXNlcmluZ3NzdHlyZWxzZW4xFzAVBgNVBGEMDk5UUkRLLTM0MDUxMTc4MQswCQYDVQQGEwJESzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKNAf9uAhuz3bEjPPFrBa39HCF6S64pSzGRr5yYm3lCBElYJvHzDr9lMKgbv8rKglIVgjWh+PzUjiwIlGjrqAbYa2Hg08Vw2H60GQSFP8rGsshgR+E5Ca2nb9kUcQXAQJl9ScG9squCPRNkdp8vSblRwv/3N0ksjxdZk1wdZ86bOqTsFEjpzhFdBXXSMl4tbhE7WOruKc0QqjUkzXJyp4qwyB2XA75+jsvtRHN/luOzCkUxLhEkFrbg+B6IWqjUuO132xC8d5+T8Y39K6rs4BYOIgQRJOg0OlA5844CC/WBLtAYgMiu1ucZ4mbVWOmm2F86WVRBdmwlN0CFORXihHiYNZfHpA0rPOSncDDMrrGZ7vuvvXxMfIiHlAniSw4eHaEqtaXqwDyNZbfcXgYkszQd7ZV7YMfAjkDo82Qn+Qz+Oc9qq0Syhd9pdUJ/Q26CjFDiaNSg+hDUUJTxowQAktX3AuwBcDeuMoc2yOGmg2xOf/3bIwJSNm8/b+y0wKfY2FwIDAQABo4IBhjCCAYIwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBR/KJ/ZcZlC4nXn1zV2Lk0IJW12XjB7BggrBgEFBQcBAQRvMG0wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYTEuY3RpLWdvdi5kay9vY2VzL2lzc3VpbmcvMS9jYWNlcnQvaXNzdWluZy5jZXIwJgYIKwYBBQUHMAGGGmh0dHA6Ly9jYTEuY3RpLWdvdi5kay9vY3NwMCEGA1UdIAQaMBgwCAYGBACPegEBMAwGCiqBUIEpAQEBAwcwOwYIKwYBBQUHAQMELzAtMCsGCCsGAQUFBwsCMB8GBwQAi+xJAQIwFIYSaHR0cHM6Ly91aWQuZ292LmRrMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jYTEuY3RpLWdvdi5kay9vY2VzL2lzc3VpbmcvMS9jcmwvaXNzdWluZy5jcmwwHQYDVR0OBBYEFNKFKxc70Coluez0ieqiVuK+a01oMA4GA1UdDwEB/wQEAwIFoDBBBgkqhkiG9w0BAQowNKAPMA0GCWCGSAFlAwQCAQUAoRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAQUAogMCASADggGBAIkUbY8meqO9xQQ2gyMS4rfmqW3bV52YGs07DqG0zuVew7W7RMAJWqDLUj5ltMWK7wULcCBS1tjtxOrvMBCoAE42oQfF/EzLRYKr7VgsMyOgUiTk2t6LvyF5A1OGHOUP3lxQKX3viDURXUeoI4QZ3mxbHUg4sQXdXg2hOEhQOarOhWLdV3MzUkA9ZkwjmycXkbLBVdTbr/fODUU0jeDDlaixKXsGI66qg8Ou86nDkyW7wCxQ9QVwJ5YGogy9ZSc6sLt8XSv3+wFlXD/81EzWfqe5BdWX8cukLtSzdzg3SzJifB4IJ6GIQ58+NVLPEMezwZCLODzVkvdJfyWRxJrDijSVCza515qNW52yfYPYkTb+vdvKcFmwO1gCeK0vT21udVkp1grhNzwb8Cj/tq3OZ+IamZXkjL1go9GzSQQ31IbXHEI/oaPLEeX6j9E8X69wVtSti8SWPw0WgoeOglJM5A6fmlJIGhCBPk2klhH3IIU3+tjuz7iyFHZg7gbPhNHdow==";
+
+ // The DevTest4 NemLog-in IdP signing certificate, taken from
+ // demo/src/main/resources/test-devtest4-idp-metadata.xml. The revocation tests validate against the
+ // live test CA, so this must be a certificate the CA still knows and has not expired.
+ public static final String VALID_CERTIFICATE = "MIIGjDCCBMCgAwIBAgIUaGLv8eOYx3cubJyI3ymai6tAXCowQQYJKoZIhvcNAQEKMDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEFAKIDAgEgMGsxLTArBgNVBAMMJERlbiBEYW5za2UgU3RhdCBPQ0VTIHVkc3RlZGVuZGUtQ0EgMTETMBEGA1UECwwKVGVzdCAtIGN0aTEYMBYGA1UECgwPRGVuIERhbnNrZSBTdGF0MQswCQYDVQQGEwJESzAeFw0yNTA4MjAxMzQxNDBaFw0yODA4MTkxMzQxMzlaMIGhMR0wGwYDVQQDDBROZW1Mb2ctaW4gSWRQIC0gVGVzdDE3MDUGA1UEBRMuVUk6REstTzpHOmEwNDBmZTI2LWNlNzgtNDMyOC1hYzBlLTI5ZWViMTJmNDZkZjEhMB8GA1UECgwYRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuMRcwFQYDVQRhDA5OVFJESy0zNDA1MTE3ODELMAkGA1UEBhMCREswggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCVUzcmIfK0NbJEmAQ7kFOTmXs1mkSHF0LAEFq7Ne8vpNz2H+0F5IyWCwsBi3SByPTAEIClbIT6rLFBoMmIwjfRmAXd68zW7NYwR0N8PcR/hvtoCR1tW2JuKhQlKbWlaYLRvvvS3r5giIjHgEXpmv42caB76eYE3J2qWPaACOIRMXky1vCmbQpEwqJr0S9+QDtMYh5ypVk1zX9rrY2TBbienruISBF1090uuzEQZtfiq9nZaBQAJZFlcYLftepSZXW4QgJjWH6BhMrd4nvcz17WeabG3AhhKHvOUDukJgKMzQd/OcS1tY13P7soMeT8D8h5bCnNDoCfqM/5mgxgxZZXnjJhzOCY+MdrXXBRST2uQLNg0gl/LgqmEKk0izQaMtNauR+5fFHSJMN23Ga6fAmHMlyEj+5JhGeScRvIBp9tPERPhRF0MdEjobbcweMRWqurJYsdo9cIHwrL8WIgQGhQRUrKBu9VPZQTtVs3dn3cxZIJ3axu53hWEKRwqw4UoasCAwEAAaOCAYcwggGDMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUfyif2XGZQuJ159c1di5NCCVtdl4wewYIKwYBBQUHAQEEbzBtMEMGCCsGAQUFBzAChjdodHRwOi8vY2ExLmN0aS1nb3YuZGsvb2Nlcy9pc3N1aW5nLzEvY2FjZXJ0L2lzc3VpbmcuY2VyMCYGCCsGAQUFBzABhhpodHRwOi8vY2ExLmN0aS1nb3YuZGsvb2NzcDAiBgNVHSAEGzAZMAgGBgQAj3oBATANBgsqgVCBKQEBAQMHATA7BggrBgEFBQcBAwQvMC0wKwYIKwYBBQUHCwIwHwYHBACL7EkBAjAUhhJodHRwczovL3VpZC5nb3YuZGswRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NhMS5jdGktZ292LmRrL29jZXMvaXNzdWluZy8xL2NybC9pc3N1aW5nLmNybDAdBgNVHQ4EFgQU9KSlGZd1HK7yFmo+zohr4oq6LLwwDgYDVR0PAQH/BAQDAgWgMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAYEAPt4QGIebeY3idMN6xPUQUBwYeiIjhtxqo2O9BHELEQ8Vp9fuBiExT286i1nNbd6TBgFFuUPh2kuwUqAj4YfaG7aSiCToJrTuaxBGlMI9nci2l5VDJ/1/lVVT/OkMLgR9xVXWSi8KFT8U9S+E1THE+G1YSNnt50yRDmqGNtG1XcaXQeu2Q4IcjMc2nf7NcGzGwidsKnBv0nNXwoYnh2ZLWPjQAgQzM3EYdZmEqaCrscYDFRbh4/T3TYjOo64N4rYZWTR+4/poz/29tyfVBWnr3rLuJH2q0kaiFVSXRHXoqOpCDUTVwsULShjmAHcPruQK7mRK1NQcwJtm0HQNWKUxizqc1pA38/9tU2vkQv+OxEEwHnCRK4XkLCJ8ZKCV5+c7AehhTLtDHqsA93+8afgrTLe+kWEO+xRgOJxKV9TnqkvnYiG8BtCOcb4+6yUMGAoOPULVKywIzutRsHYjZptCkuggBqNztSFU/DUd6SpSxf1MGfeh4SC4yPNvKQ+5fo7S";
public static final String REVOKED_CERTIFICATE = "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";
}