Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,14 @@ private void validateAssertion(Assertion assertion, AuthnRequestWrapper authnReq
}

private void validateAttributeStatement(Map<String, String> attributes, boolean isProfessional) throws AssertionValidationException {
// SpecVer
// SpecVer is mandatory in the OIOSAML attribute profiles, but its value identifies the profile
// version the assertion was issued under and changes between profile versions, so only the
// presence of the attribute is required here
String specVersion = attributes.get(Constants.SPEC_VER);
if (!Constants.SPEC_VER_VAL.equals(specVersion)) {
throw new AssertionValidationException("specVersion Was: " + specVersion + " Expected: " + Constants.SPEC_VER_VAL);
if (specVersion == null || specVersion.isEmpty()) {
throw new AssertionValidationException("Assertions MUST contain the specVersion attribute " + Constants.SPEC_VER);
}
log.debug("Assertion issued under OIOSAML profile version '{}'", specVersion);

// Professional
if (isProfessional) {
Expand Down
1 change: 0 additions & 1 deletion oiosaml/src/main/java/dk/gov/oio/saml/util/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ public class Constants {

// SAML Attributes constants
public static final String SPEC_VER = "https://data.gov.dk/model/core/specVersion";
public static final String SPEC_VER_VAL = "OIO-SAML-3.0";
public static final String PRIVILEGE_ATTRIBUTE = "https://data.gov.dk/model/core/eid/privilegesIntermediate";
public static final String LOA = "https://data.gov.dk/concept/core/nsis/loa";
public static final String CVR_NUMBER = "https://data.gov.dk/model/core/eid/professional/cvr";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,60 @@ public void testValidateCorrectAssertion() throws Exception {
validationService.validate(request, messageContext, response, assertion, new AuthnRequestWrapper(authnRequest, NSISLevel.SUBSTANTIAL, ""));
}

@DisplayName("Test that validator will pass an assertion issued under a newer OIOSAML profile version")
@Test
public void testValidateAssertionWithNewerSpecVersion() throws Exception {
AssertionValidationService validationService = new AssertionValidationService();

// Mock HttpServletRequest
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer(TestConstants.SP_ASSERTION_CONSUMER_URL));

// Create AuthnRequest
AuthnRequestService authnRequestService = AuthnRequestService.getInstance();
AuthnRequest authnRequest = getAuthnRequest(authnRequestService);
String inResponseToId = authnRequest.getID();

// Create MessageContext, Response and Assertion, with the specVersion value used by OIOSAML 4.0.0
String nameID = "https://data.gov.dk/model/core/eid/person/uuid/37a5a1aa-67ce-4f70-b7c0-b8e678d585f7";
MessageContext<SAMLObject> messageContext = IdpUtil.createMessageWithAssertion(true, true, true, nameID, TestConstants.SP_ENTITY_ID, TestConstants.SP_ASSERTION_CONSUMER_URL, inResponseToId, TestConstants.SPEC_VERSION_OIOSAML_40);
Response response = (Response) messageContext.getMessage();

AssertionService assertionService = new AssertionService();
Assertion assertion = assertionService.getAssertion(response);

// Validate
validationService.validate(request, messageContext, response, assertion, new AuthnRequestWrapper(authnRequest, NSISLevel.SUBSTANTIAL, ""));
}

@DisplayName("Test that validator will fail an assertion without a specVersion attribute")
@Test
public void testFailAssertionWithoutSpecVersion() throws Exception {
AssertionValidationService validationService = new AssertionValidationService();

// Mock HttpServletRequest
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer(TestConstants.SP_ASSERTION_CONSUMER_URL));

// Create AuthnRequest
AuthnRequestService authnRequestService = AuthnRequestService.getInstance();
AuthnRequest authnRequest = getAuthnRequest(authnRequestService);
String inResponseToId = authnRequest.getID();

// Create MessageContext, Response and Assertion, without the mandatory specVersion attribute
String nameID = "https://data.gov.dk/model/core/eid/person/uuid/37a5a1aa-67ce-4f70-b7c0-b8e678d585f7";
MessageContext<SAMLObject> messageContext = IdpUtil.createMessageWithAssertion(true, true, true, nameID, TestConstants.SP_ENTITY_ID, TestConstants.SP_ASSERTION_CONSUMER_URL, inResponseToId, null);
Response response = (Response) messageContext.getMessage();

AssertionService assertionService = new AssertionService();
Assertion assertion = assertionService.getAssertion(response);

// Validate, should fail, specVersion is mandatory
Assertions.assertThrows(AssertionValidationException.class, () -> {
validationService.validate(request, messageContext, response, assertion, new AuthnRequestWrapper(authnRequest, NSISLevel.SUBSTANTIAL, ""));
});
}

@DisplayName("Test that validator will fail an assertion with the wrong destination")
@Test
public void testFailAssertionWithWrongDestination() throws Exception {
Expand Down
34 changes: 30 additions & 4 deletions oiosaml/src/test/java/dk/gov/oio/saml/util/IdpUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,20 @@ public static MessageContext<SAMLObject> createMessageWithAssertion(
String recipientEntityId,
String assertionConsumerUrl,
String inResponseToId) throws Exception {
return createMessageWithAssertion(encrypted, validCert, validSignature, subjectNameID, recipientEntityId, assertionConsumerUrl, inResponseToId, TestConstants.SPEC_VERSION_OIOSAML_30);
}

public static MessageContext<SAMLObject> createMessageWithAssertion(
boolean encrypted,
boolean validCert,
boolean validSignature,
String subjectNameID,
String recipientEntityId,
String assertionConsumerUrl,
String inResponseToId,
String specVersion) throws Exception {
// Create proxy Response
Response response = createResponse(encrypted, validCert, validSignature, subjectNameID, recipientEntityId, assertionConsumerUrl, inResponseToId);
Response response = createResponse(encrypted, validCert, validSignature, subjectNameID, recipientEntityId, assertionConsumerUrl, inResponseToId, specVersion);

// Build Proxy MessageContext and add response
MessageContext<SAMLObject> messageContext = new MessageContext<>();
Expand Down Expand Up @@ -89,6 +101,18 @@ public static Response createResponse(
String recipientEntityId,
String assertionConsumerUrl,
String inResponseToId) throws Exception {
return createResponse(encrypted, validCert, validSignature, subjectNameID, recipientEntityId, assertionConsumerUrl, inResponseToId, TestConstants.SPEC_VERSION_OIOSAML_30);
}

public static Response createResponse(
boolean encrypted,
boolean validCert,
boolean validSignature,
String subjectNameID,
String recipientEntityId,
String assertionConsumerUrl,
String inResponseToId,
String specVersion) throws Exception {

DateTime issueInstant = new DateTime();

Expand All @@ -110,7 +134,7 @@ public static Response createResponse(
status.setStatusCode(statusCode);
response.setStatus(status);

Assertion assertion = createAssertion(issueInstant, subjectNameID, recipientEntityId, assertionConsumerUrl);
Assertion assertion = createAssertion(issueInstant, subjectNameID, recipientEntityId, assertionConsumerUrl, specVersion);
SignAssertion(assertion, validSignature);
if (encrypted) {
EncryptedAssertion encryptedAssertion = encryptAssertion(assertion, validCert);
Expand Down Expand Up @@ -282,7 +306,7 @@ private static void SignAssertion(Assertion assertion, boolean validSignature) t
Signer.signObject(signature);
}

private static Assertion createAssertion(DateTime issueInstant, String subjectNameID, String recipientEntityId, String assertionConsumerUrl) {
private static Assertion createAssertion(DateTime issueInstant, String subjectNameID, String recipientEntityId, String assertionConsumerUrl, String specVersion) {
RandomIdentifierGenerationStrategy secureRandomIdGenerator = new RandomIdentifierGenerationStrategy();
String id = secureRandomIdGenerator.generateIdentifier();

Expand Down Expand Up @@ -310,7 +334,9 @@ private static Assertion createAssertion(DateTime issueInstant, String subjectNa
AttributeStatement attributeStatement = buildSAMLObject(AttributeStatement.class);
List<Attribute> attributes = attributeStatement.getAttributes();

attributes.add(createSimpleAttribute("https://data.gov.dk/model/core/specVersion", "OIO-SAML-3.0"));
if (specVersion != null) {
attributes.add(createSimpleAttribute(Constants.SPEC_VER, specVersion));
}
attributes.add(createSimpleAttribute("https://data.gov.dk/concept/core/nsis/loa", NSISLevel.SUBSTANTIAL.getName()));
assertion.getAttributeStatements().add(attributeStatement);

Expand Down
4 changes: 4 additions & 0 deletions oiosaml/src/test/java/dk/gov/oio/saml/util/TestConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ public class TestConstants {
" </md:IDPSSODescriptor>\n" +
"</md:EntityDescriptor>";
public static final String BAD_SP_ASSERTION_CONSUMER_URL = "http://localhost:8080/sso";

// 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 = "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";

Expand Down