Skip to content

Commit e71392d

Browse files
committed
Allow for extension classes to post-process generated XML
This change allows for any java-saml consumer to extend the standard classes used to generate SAML messages (AuthnRequest, LogoutRequest and LogoutResponse), as well as the metadata, and provide their own logic to post-process the default XML produced by java-saml. Any extension class will then be able to transform or enrich the generated XML as required, before the framework applies encoding, encryption or signing.
1 parent 3a81e0c commit e71392d

File tree

8 files changed

+155
-4
lines changed

8 files changed

+155
-4
lines changed

core/src/main/java/com/onelogin/saml2/authn/AuthnRequest.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public AuthnRequest(Saml2Settings settings, boolean forceAuthn, boolean isPassiv
101101
this.nameIdValueReq = nameIdValueReq;
102102

103103
StrSubstitutor substitutor = generateSubstitutor(settings);
104-
authnRequestString = substitutor.replace(getAuthnRequestTemplate());
104+
authnRequestString = postProcessXml(substitutor.replace(getAuthnRequestTemplate()));
105105
LOGGER.debug("AuthNRequest --> " + authnRequestString);
106106
}
107107

@@ -121,6 +121,24 @@ public AuthnRequest(Saml2Settings settings, boolean forceAuthn, boolean isPassiv
121121
this(settings, forceAuthn, isPassive, setNameIdPolicy, null);
122122
}
123123

124+
/**
125+
* Allows for an extension class to post-process the AuthnRequest XML generated
126+
* for this request, in order to customize the result.
127+
* <p>
128+
* This method is invoked at construction time, after all the other fields of
129+
* this class have already been initialised. Its default implementation simply
130+
* returns the input XML as-is, with no change.
131+
*
132+
* @param authRequestXml
133+
* the XML produced for this AuthnRequest by the standard
134+
* implementation provided by {@link AuthnRequest}
135+
* @return the post-processed XML for this AuthnRequest, which will then be
136+
* returned by any call to {@link #getAuthnRequestXml()}
137+
*/
138+
protected String postProcessXml(final String authRequestXml) {
139+
return authRequestXml;
140+
}
141+
124142
/**
125143
* @return the base64 encoded unsigned AuthnRequest (deflated or not)
126144
*

core/src/main/java/com/onelogin/saml2/logout/LogoutRequest.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public LogoutRequest(Saml2Settings settings, HttpRequest request, String nameId,
139139
this.sessionIndex = sessionIndex;
140140

141141
StrSubstitutor substitutor = generateSubstitutor(settings);
142-
logoutRequestString = substitutor.replace(getLogoutRequestTemplate());
142+
logoutRequestString = postProcessXml(substitutor.replace(getLogoutRequestTemplate()));
143143
} else {
144144
logoutRequestString = Util.base64decodedInflated(samlLogoutRequest);
145145
Document doc = Util.loadXML(logoutRequestString);
@@ -224,6 +224,26 @@ public LogoutRequest(Saml2Settings settings, HttpRequest request) {
224224
this(settings, request, null, null);
225225
}
226226

227+
/**
228+
* Allows for an extension class to post-process the LogoutRequest XML generated
229+
* for this request, in order to customize the result.
230+
* <p>
231+
* This method is invoked at construction time when no existing LogoutRequest
232+
* message is found in the HTTP request (and hence in the logout request sending
233+
* scenario only), after all the other fields of this class have already been
234+
* initialised. Its default implementation simply returns the input XML as-is,
235+
* with no change.
236+
*
237+
* @param logoutRequestXml
238+
* the XML produced for this LogoutRequest by the standard
239+
* implementation provided by {@link LogoutRequest}
240+
* @return the post-processed XML for this LogoutRequest, which will then be
241+
* returned by any call to {@link #getLogoutRequestXml()}
242+
*/
243+
protected String postProcessXml(final String logoutRequestXml) {
244+
return logoutRequestXml;
245+
}
246+
227247
/**
228248
* @return the base64 encoded unsigned Logout Request (deflated or not)
229249
*

core/src/main/java/com/onelogin/saml2/logout/LogoutResponse.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ public void build(String inResponseTo, String statusCode) {
364364
this.inResponseTo = inResponseTo;
365365

366366
StrSubstitutor substitutor = generateSubstitutor(settings, statusCode);
367-
this.logoutResponseString = substitutor.replace(getLogoutResponseTemplate());
367+
this.logoutResponseString = postProcessXml(substitutor.replace(getLogoutResponseTemplate()));
368368
}
369369

370370
/**
@@ -385,6 +385,24 @@ public void build() {
385385
build(null);
386386
}
387387

388+
/**
389+
* Allows for an extension class to post-process the LogoutResponse XML
390+
* generated for this response, in order to customize the result.
391+
* <p>
392+
* This method is invoked by {@link #build(String, String)} (and all of its
393+
* overloadings) and hence only in the logout response sending scenario. Its
394+
* default implementation simply returns the input XML as-is, with no change.
395+
*
396+
* @param logoutResponseXml
397+
* the XML produced for this LogoutResponse by the standard
398+
* implementation provided by {@link LogoutResponse}
399+
* @return the post-processed XML for this LogoutResponse, which will then be
400+
* returned by any call to {@link #getLogoutResponseXml()}
401+
*/
402+
protected String postProcessXml(final String logoutResponseXml) {
403+
return logoutResponseXml;
404+
}
405+
388406
/**
389407
* Substitutes LogoutResponse variables within a string by values.
390408
*

core/src/main/java/com/onelogin/saml2/settings/Metadata.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,29 @@ public Metadata(Saml2Settings settings) throws CertificateEncodingException {
109109
this.cacheDuration = SECONDS_CACHED;
110110

111111
StrSubstitutor substitutor = generateSubstitutor(settings);
112-
String unsignedMetadataString = substitutor.replace(getMetadataTemplate());
112+
String unsignedMetadataString = postProcessXml(substitutor.replace(getMetadataTemplate()));
113113

114114
LOGGER.debug("metadata --> " + unsignedMetadataString);
115115
metadataString = unsignedMetadataString;
116116
}
117+
118+
/**
119+
* Allows for an extension class to post-process the SAML metadata XML generated
120+
* for this metadata instance, in order to customize the result.
121+
* <p>
122+
* This method is invoked at construction time, after all the other fields of
123+
* this class have already been initialised. Its default implementation simply
124+
* returns the input XML as-is, with no change.
125+
*
126+
* @param metadataXml
127+
* the XML produced for this metadata instance by the standard
128+
* implementation provided by {@link Metadata}
129+
* @return the post-processed XML for this metadata instance, which will then be
130+
* returned by any call to {@link #getMetadataString()}
131+
*/
132+
protected String postProcessXml(final String metadataXml) {
133+
return metadataXml;
134+
}
117135

118136
/**
119137
* Substitutes metadata variables within a string by values.

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,23 @@ public void testAuthNDestination() throws Exception {
382382
assertThat(authnRequestStr, containsString("<samlp:AuthnRequest"));
383383
assertThat(authnRequestStr, not(containsString("Destination=\"http://idp.example.com/simplesaml/saml2/idp/SSOService.php\"")));
384384
}
385+
386+
/**
387+
* Tests the postProcessXml method of AuthnRequest
388+
*
389+
* @throws Exception
390+
*
391+
* @see com.onelogin.saml2.authn.AuthnRequest#postProcessXml
392+
*/
393+
@Test
394+
public void testPostProcessXml() throws Exception {
395+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
396+
AuthnRequest authnRequest = new AuthnRequest(settings) {
397+
@Override
398+
protected String postProcessXml(String authRequestXml) {
399+
return "changed";
400+
}
401+
};
402+
assertEquals("changed", authnRequest.getAuthnRequestXml());
403+
}
385404
}

core/src/test/java/com/onelogin/saml2/test/logout/LogoutRequestTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,4 +932,23 @@ public void testGetError() throws Exception {
932932
private static HttpRequest newHttpRequest(String requestURL, String samlRequestEncoded) {
933933
return new HttpRequest(requestURL, (String)null).addParameter("SAMLRequest", samlRequestEncoded);
934934
}
935+
936+
/**
937+
* Tests the postProcessXml method of LogoutRequest
938+
*
939+
* @throws Exception
940+
*
941+
* @see com.onelogin.saml2.logout.LogoutRequest#postProcessXml
942+
*/
943+
@Test
944+
public void testPostProcessXml() throws Exception {
945+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
946+
LogoutRequest logoutRequest = new LogoutRequest(settings) {
947+
@Override
948+
protected String postProcessXml(String authRequestXml) {
949+
return "changed";
950+
}
951+
};
952+
assertEquals("changed", logoutRequest.getLogoutRequestXml());
953+
}
935954
}

core/src/test/java/com/onelogin/saml2/test/logout/LogoutResponseTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,4 +691,24 @@ public void testGetError() throws URISyntaxException, IOException, XMLEntityExce
691691
private static HttpRequest newHttpRequest(String requestURL, String samlResponseEncoded) {
692692
return new HttpRequest(requestURL, (String)null).addParameter("SAMLResponse", samlResponseEncoded);
693693
}
694+
695+
/**
696+
* Tests the postProcessXml method of LogoutResponse
697+
*
698+
* @throws Exception
699+
*
700+
* @see com.onelogin.saml2.logout.LogoutResponse#postProcessXml
701+
*/
702+
@Test
703+
public void testPostProcessXml() throws Exception {
704+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
705+
LogoutResponse logoutResponse = new LogoutResponse(settings, null) {
706+
@Override
707+
protected String postProcessXml(String authRequestXml) {
708+
return "changed";
709+
}
710+
};
711+
logoutResponse.build();
712+
assertEquals("changed", logoutResponse.getLogoutResponseXml());
713+
}
694714
}

core/src/test/java/com/onelogin/saml2/test/settings/MetadataTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,4 +520,23 @@ public void shouldIgnoreCacheDuration() throws CertificateEncodingException, Err
520520
assertNull("should not set cache duration attribute", cacheDurationNode);
521521

522522
}
523+
524+
/**
525+
* Tests the postProcessXml method of Metadata
526+
*
527+
* @throws Exception
528+
*
529+
* @see com.onelogin.saml2.settings.Metadata#postProcessXml
530+
*/
531+
@Test
532+
public void testPostProcessXml() throws Exception {
533+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
534+
Metadata metadata = new Metadata(settings) {
535+
@Override
536+
protected String postProcessXml(String authRequestXml) {
537+
return "changed";
538+
}
539+
};
540+
assertEquals("changed", metadata.getMetadataString());
541+
}
523542
}

0 commit comments

Comments
 (0)