Skip to content

Commit b7747fc

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 523786b commit b7747fc

8 files changed

Lines changed: 155 additions & 4 deletions

File tree

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
@@ -141,7 +141,7 @@ public LogoutRequest(Saml2Settings settings, HttpRequest request, String nameId,
141141
this.sessionIndex = sessionIndex;
142142

143143
StrSubstitutor substitutor = generateSubstitutor(settings);
144-
logoutRequestString = substitutor.replace(getLogoutRequestTemplate());
144+
logoutRequestString = postProcessXml(substitutor.replace(getLogoutRequestTemplate()));
145145
} else {
146146
logoutRequestString = Util.base64decodedInflated(samlLogoutRequest);
147147
id = getId(logoutRequestString);
@@ -234,6 +234,26 @@ public LogoutRequest(Saml2Settings settings, HttpRequest request) throws XMLEnti
234234
this(settings, request, null, null);
235235
}
236236

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

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

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

365365
StrSubstitutor substitutor = generateSubstitutor(settings, statusCode);
366-
this.logoutResponseString = substitutor.replace(getLogoutResponseTemplate());
366+
this.logoutResponseString = postProcessXml(substitutor.replace(getLogoutResponseTemplate()));
367367
}
368368

369369
/**
@@ -384,6 +384,24 @@ public void build() {
384384
build(null);
385385
}
386386

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

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
@@ -352,4 +352,23 @@ public void testAuthNDestination() throws Exception {
352352
assertThat(authnRequestStr, containsString("<samlp:AuthnRequest"));
353353
assertThat(authnRequestStr, not(containsString("Destination=\"http://idp.example.com/simplesaml/saml2/idp/SSOService.php\"")));
354354
}
355+
356+
/**
357+
* Tests the postProcessXml method of AuthnRequest
358+
*
359+
* @throws Exception
360+
*
361+
* @see com.onelogin.saml2.authn.AuthnRequest#postProcessXml
362+
*/
363+
@Test
364+
public void testPostProcessXml() throws Exception {
365+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
366+
AuthnRequest authnRequest = new AuthnRequest(settings) {
367+
@Override
368+
protected String postProcessXml(String authRequestXml) {
369+
return "changed";
370+
}
371+
};
372+
assertEquals("changed", authnRequest.getAuthnRequestXml());
373+
}
355374
}

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
@@ -879,4 +879,23 @@ public void testGetError() throws Exception {
879879
private static HttpRequest newHttpRequest(String requestURL, String samlRequestEncoded) {
880880
return new HttpRequest(requestURL, (String)null).addParameter("SAMLRequest", samlRequestEncoded);
881881
}
882+
883+
/**
884+
* Tests the postProcessXml method of LogoutRequest
885+
*
886+
* @throws Exception
887+
*
888+
* @see com.onelogin.saml2.logout.LogoutRequest#postProcessXml
889+
*/
890+
@Test
891+
public void testPostProcessXml() throws Exception {
892+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
893+
LogoutRequest logoutRequest = new LogoutRequest(settings) {
894+
@Override
895+
protected String postProcessXml(String authRequestXml) {
896+
return "changed";
897+
}
898+
};
899+
assertEquals("changed", logoutRequest.getLogoutRequestXml());
900+
}
882901
}

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
@@ -646,4 +646,24 @@ public void testGetError() throws URISyntaxException, IOException, XMLEntityExce
646646
private static HttpRequest newHttpRequest(String requestURL, String samlResponseEncoded) {
647647
return new HttpRequest(requestURL, (String)null).addParameter("SAMLResponse", samlResponseEncoded);
648648
}
649+
650+
/**
651+
* Tests the postProcessXml method of LogoutResponse
652+
*
653+
* @throws Exception
654+
*
655+
* @see com.onelogin.saml2.logout.LogoutResponse#postProcessXml
656+
*/
657+
@Test
658+
public void testPostProcessXml() throws Exception {
659+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
660+
LogoutResponse logoutResponse = new LogoutResponse(settings, null) {
661+
@Override
662+
protected String postProcessXml(String authRequestXml) {
663+
return "changed";
664+
}
665+
};
666+
logoutResponse.build();
667+
assertEquals("changed", logoutResponse.getLogoutResponseXml());
668+
}
649669
}

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)