Skip to content

Commit 54e2b57

Browse files
fix(unit test): fix idPMetadataParserTest
* seems that `try.onelogin.com` is replaced by `try-demo.onelogin.com` feat(metadata): make validUntil and cacheDuration optional * follow XSD and don't add xml attribute when value is not set Relates to [#106](#106) format using tabs
1 parent 54afc56 commit 54e2b57

File tree

3 files changed

+438
-417
lines changed

3 files changed

+438
-417
lines changed

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

Lines changed: 98 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -28,52 +28,47 @@
2828

2929
/**
3030
* Metadata class of OneLogin's Java Toolkit.
31-
*
31+
* <p>
3232
* A class that contains methods related to the metadata of the SP
3333
*/
3434
public class Metadata {
3535
/**
36-
* Private property to construct a logger for this class.
37-
*/
36+
* Private property to construct a logger for this class.
37+
*/
3838
private static final Logger LOGGER = LoggerFactory.getLogger(Metadata.class);
39-
39+
4040
// Constants
4141
private static final int N_DAYS_VALID_UNTIL = 2;
4242
private static final int SECONDS_CACHED = 604800; // 1 week
4343

4444
/**
45-
* AttributeConsumingService
46-
*/
45+
* AttributeConsumingService
46+
*/
4747
private AttributeConsumingService attributeConsumingService = null;
48-
48+
4949
/**
50-
* Generated metadata in string format
51-
*/
50+
* Generated metadata in string format
51+
*/
5252
private final String metadataString;
5353

5454
/**
55-
* validUntilTime of the metadata. How long the metadata is valid
56-
*/
55+
* validUntilTime of the metadata. How long the metadata is valid
56+
*/
5757
private final Calendar validUntilTime;
5858

5959
/**
60-
* cacheDuration of the metadata. Duration of the cache in seconds
61-
*/
60+
* cacheDuration of the metadata. Duration of the cache in seconds
61+
*/
6262
private final Integer cacheDuration;
6363

6464
/**
6565
* Constructs the Metadata object.
66-
*
67-
* @param settings
68-
* Saml2Settings object. Setting data
69-
* @param validUntilTime
70-
* Metadata's valid time
71-
* @param cacheDuration
72-
* Duration of the cache in seconds
73-
* @param attributeConsumingService
74-
* AttributeConsumingService of service provider
75-
*
76-
* @throws CertificateEncodingException
66+
*
67+
* @param settings Saml2Settings object. Setting data
68+
* @param validUntilTime Metadata's valid time
69+
* @param cacheDuration Duration of the cache in seconds
70+
* @param attributeConsumingService AttributeConsumingService of service provider
71+
* @throws CertificateEncodingException
7772
*/
7873
public Metadata(Saml2Settings settings, Calendar validUntilTime, Integer cacheDuration, AttributeConsumingService attributeConsumingService) throws CertificateEncodingException {
7974
if (validUntilTime == null) {
@@ -82,7 +77,7 @@ public Metadata(Saml2Settings settings, Calendar validUntilTime, Integer cacheDu
8277
} else {
8378
this.validUntilTime = validUntilTime;
8479
}
85-
80+
8681
this.attributeConsumingService = attributeConsumingService;
8782

8883
if (cacheDuration == null) {
@@ -92,53 +87,45 @@ public Metadata(Saml2Settings settings, Calendar validUntilTime, Integer cacheDu
9287
}
9388

9489
StrSubstitutor substitutor = generateSubstitutor(settings);
95-
String unsignedMetadataString = substitutor.replace(getMetadataTemplate());
90+
String unsignedMetadataString = substitutor.replace(getMetadataTemplate(validUntilTime, cacheDuration));
9691

97-
LOGGER.debug("metadata --> " + unsignedMetadataString);
98-
metadataString = unsignedMetadataString;
92+
LOGGER.debug("metadata --> " + unsignedMetadataString);
93+
metadataString = unsignedMetadataString;
9994
}
10095

10196
/**
10297
* Constructs the Metadata object.
103-
*
104-
* @param settings
105-
* Saml2Settings object. Setting data
106-
* @param validUntilTime
107-
* Metadata's valid time
108-
* @param cacheDuration
109-
* Duration of the cache in seconds
110-
*
111-
* @throws CertificateEncodingException
98+
*
99+
* @param settings Saml2Settings object. Setting data
100+
* @param validUntilTime Metadata's valid time
101+
* @param cacheDuration Duration of the cache in seconds
102+
* @throws CertificateEncodingException
112103
*/
113104
public Metadata(Saml2Settings settings, Calendar validUntilTime, Integer cacheDuration) throws CertificateEncodingException {
114105
this(settings, validUntilTime, cacheDuration, null);
115106
}
116-
107+
117108
/**
118109
* Constructs the Metadata object.
119110
*
120-
* @param settings
121-
* Saml2Settings object. Setting data
122-
*
123-
* @throws CertificateEncodingException
111+
* @param settings Saml2Settings object. Setting data
112+
* @throws CertificateEncodingException
124113
*/
125114
public Metadata(Saml2Settings settings) throws CertificateEncodingException {
126115
this(settings, null, null);
127116
}
128-
117+
129118
/**
130119
* Substitutes metadata variables within a string by values.
131120
*
132-
* @param settings
133-
* Saml2Settings object. Setting data
134-
*
135-
* @return the StrSubstitutor object of the metadata
136-
*/
121+
* @param settings Saml2Settings object. Setting data
122+
* @return the StrSubstitutor object of the metadata
123+
*/
137124
private StrSubstitutor generateSubstitutor(Saml2Settings settings) throws CertificateEncodingException {
138125

139126
Map<String, String> valueMap = new HashMap<String, String>();
140-
Boolean wantsEncrypted = settings.getWantAssertionsEncrypted() || settings.getWantNameIdEncrypted();
141-
127+
Boolean wantsEncrypted = settings.getWantAssertionsEncrypted() || settings.getWantNameIdEncrypted();
128+
142129
valueMap.put("id", Util.generateUniqueID(settings.getUniqueIDPrefix()));
143130
valueMap.put("validUntilTime", Util.formatDateTime(validUntilTime.getTimeInMillis()));
144131
valueMap.put("cacheDuration", String.valueOf(cacheDuration));
@@ -151,7 +138,7 @@ private StrSubstitutor generateSubstitutor(Saml2Settings settings) throws Certif
151138
valueMap.put("sls", toSLSXml(settings.getSpSingleLogoutServiceUrl(), settings.getSpSingleLogoutServiceBinding()));
152139

153140
valueMap.put("strAttributeConsumingService", getAttributeConsumingServiceXml());
154-
141+
155142
valueMap.put("strKeyDescriptor", toX509KeyDescriptorsXML(settings.getSPcert(), wantsEncrypted));
156143
valueMap.put("strContacts", toContactsXml(settings.getContacts()));
157144
valueMap.put("strOrganization", toOrganizationXml(settings.getOrganization()));
@@ -160,15 +147,21 @@ private StrSubstitutor generateSubstitutor(Saml2Settings settings) throws Certif
160147
}
161148

162149
/**
150+
* @param validUntil
151+
* @param cacheDuration
163152
* @return the metadata's template
164153
*/
165-
private static StringBuilder getMetadataTemplate() {
154+
private static StringBuilder getMetadataTemplate(Calendar validUntil, Integer cacheDuration) {
166155

167156
StringBuilder template = new StringBuilder();
168157
template.append("<?xml version=\"1.0\"?>");
169158
template.append("<md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\"");
170-
template.append(" validUntil=\"${validUntilTime}\"");
171-
template.append(" cacheDuration=\"PT${cacheDuration}S\"");
159+
if (validUntil != null) {
160+
template.append(" validUntil=\"${validUntilTime}\"");
161+
}
162+
if (cacheDuration != null) {
163+
template.append(" cacheDuration=\"PT${cacheDuration}S\"");
164+
}
172165
template.append(" entityID=\"${spEntityId}\"");
173166
template.append(" ID=\"${id}\">");
174167
template.append("<md:SPSSODescriptor AuthnRequestsSigned=\"${strAuthnsign}\" WantAssertionsSigned=\"${strWsign}\" protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\">");
@@ -187,7 +180,6 @@ private static StringBuilder getMetadataTemplate() {
187180
/**
188181
* Generates the AttributeConsumingService section of the metadata's template
189182
*
190-
*
191183
* @return the AttributeConsumingService section of the metadata's template
192184
*/
193185
private String getAttributeConsumingServiceXml() {
@@ -210,10 +202,10 @@ private String getAttributeConsumingServiceXml() {
210202
String friendlyName = requestedAttribute.getFriendlyName();
211203
String nameFormat = requestedAttribute.getNameFormat();
212204
Boolean isRequired = requestedAttribute.isRequired();
213-
List<String> attrValues = requestedAttribute.getAttributeValues() ;
205+
List<String> attrValues = requestedAttribute.getAttributeValues();
206+
207+
String contentStr = "<md:RequestedAttribute";
214208

215-
String contentStr = "<md:RequestedAttribute";
216-
217209
if (name != null && !name.isEmpty()) {
218210
contentStr += " Name=\"" + name + "\"";
219211
}
@@ -229,7 +221,7 @@ private String getAttributeConsumingServiceXml() {
229221
if (isRequired != null) {
230222
contentStr += " isRequired=\"" + isRequired.toString() + "\"";
231223
}
232-
224+
233225
if (attrValues != null && !attrValues.isEmpty()) {
234226
contentStr += ">";
235227
for (String attrValue : attrValues) {
@@ -243,16 +235,14 @@ private String getAttributeConsumingServiceXml() {
243235
}
244236
attributeConsumingServiceXML.append("</md:AttributeConsumingService>");
245237
}
246-
238+
247239
return attributeConsumingServiceXML.toString();
248240
}
249-
241+
250242
/**
251243
* Generates the contact section of the metadata's template
252244
*
253-
* @param contacts
254-
* List of contact objects
255-
*
245+
* @param contacts List of contact objects
256246
* @return the contact section of the metadata's template
257247
*/
258248
private String toContactsXml(List<Contact> contacts) {
@@ -271,9 +261,8 @@ private String toContactsXml(List<Contact> contacts) {
271261
/**
272262
* Generates the organization section of the metadata's template
273263
*
274-
* @param organization
275-
* organization object
276-
* @return the organization section of the metadata's template
264+
* @param organization organization object
265+
* @return the organization section of the metadata's template
277266
*/
278267
private String toOrganizationXml(Organization organization) {
279268
String orgXml = "";
@@ -290,12 +279,9 @@ private String toOrganizationXml(Organization organization) {
290279

291280
/**
292281
* Generates the KeyDescriptor section of the metadata's template
293-
*
294-
* @param cert
295-
* the public cert that will be used by the SP to sign and encrypt
296-
* @param wantsEncrypted
297-
* Whether to include the KeyDescriptor for encryption
298282
*
283+
* @param cert the public cert that will be used by the SP to sign and encrypt
284+
* @param wantsEncrypted Whether to include the KeyDescriptor for encryption
299285
* @return the KeyDescriptor section of the metadata's template
300286
*/
301287
private String toX509KeyDescriptorsXML(X509Certificate cert, Boolean wantsEncrypted) throws CertificateEncodingException {
@@ -309,7 +295,7 @@ private String toX509KeyDescriptorsXML(X509Certificate cert, Boolean wantsEncryp
309295
keyDescriptorXml.append("<md:KeyDescriptor use=\"signing\">");
310296
keyDescriptorXml.append("<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">");
311297
keyDescriptorXml.append("<ds:X509Data>");
312-
keyDescriptorXml.append("<ds:X509Certificate>"+certString+"</ds:X509Certificate>");
298+
keyDescriptorXml.append("<ds:X509Certificate>" + certString + "</ds:X509Certificate>");
313299
keyDescriptorXml.append("</ds:X509Data>");
314300
keyDescriptorXml.append("</ds:KeyInfo>");
315301
keyDescriptorXml.append("</md:KeyDescriptor>");
@@ -318,7 +304,7 @@ private String toX509KeyDescriptorsXML(X509Certificate cert, Boolean wantsEncryp
318304
keyDescriptorXml.append("<md:KeyDescriptor use=\"encryption\">");
319305
keyDescriptorXml.append("<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">");
320306
keyDescriptorXml.append("<ds:X509Data>");
321-
keyDescriptorXml.append("<ds:X509Certificate>"+certString+"</ds:X509Certificate>");
307+
keyDescriptorXml.append("<ds:X509Certificate>" + certString + "</ds:X509Certificate>");
322308
keyDescriptorXml.append("</ds:X509Data>");
323309
keyDescriptorXml.append("</ds:KeyInfo>");
324310
keyDescriptorXml.append("</md:KeyDescriptor>");
@@ -330,25 +316,23 @@ private String toX509KeyDescriptorsXML(X509Certificate cert, Boolean wantsEncryp
330316

331317
/**
332318
* Generates the KeyDescriptor section of the metadata's template
333-
*
334-
* @param cert
335-
* the public cert that will be used by the SP to sign and encrypt
336319
*
320+
* @param cert the public cert that will be used by the SP to sign and encrypt
337321
* @return the KeyDescriptor section of the metadata's template
338322
*/
339323
private String toX509KeyDescriptorsXML(X509Certificate cert) throws CertificateEncodingException {
340324
return toX509KeyDescriptorsXML(cert, true);
341325
}
342-
326+
343327
/**
344328
* @return the md:SingleLogoutService section of the metadata's template
345329
*/
346330
private String toSLSXml(URL spSingleLogoutServiceUrl, String spSingleLogoutServiceBinding) {
347331
StringBuilder slsXml = new StringBuilder();
348-
332+
349333
if (spSingleLogoutServiceUrl != null) {
350-
slsXml.append("<md:SingleLogoutService Binding=\""+spSingleLogoutServiceBinding+"\"");
351-
slsXml.append(" Location=\""+spSingleLogoutServiceUrl.toString()+"\"/>");
334+
slsXml.append("<md:SingleLogoutService Binding=\"" + spSingleLogoutServiceBinding + "\"");
335+
slsXml.append(" Location=\"" + spSingleLogoutServiceUrl.toString() + "\"/>");
352336
}
353337
return slsXml.toString();
354338
}
@@ -360,50 +344,37 @@ public final String getMetadataString() {
360344
return metadataString;
361345
}
362346

363-
/**
364-
* Signs the metadata with the key/cert provided
365-
*
366-
* @param metadata
367-
* SAML Metadata XML
368-
* @param key
369-
* Private Key
370-
* @param cert
371-
* x509 Public certificate
372-
* @param signAlgorithm
373-
* Signature Algorithm
374-
*
375-
* @return string Signed Metadata
376-
* @throws XMLSecurityException
377-
* @throws XPathExpressionException
378-
*/
379-
public static String signMetadata(String metadata, PrivateKey key, X509Certificate cert, String signAlgorithm) throws XPathExpressionException, XMLSecurityException
380-
{
381-
return signMetadata(metadata, key, cert, signAlgorithm, Constants.SHA1);
382-
}
383-
384-
/**
385-
* Signs the metadata with the key/cert provided
386-
*
387-
* @param metadata
388-
* SAML Metadata XML
389-
* @param key
390-
* Private Key
391-
* @param cert
392-
* x509 Public certificate
393-
* @param signAlgorithm
394-
* Signature Algorithm
395-
* @param digestAlgorithm
396-
* Digest Algorithm
397-
*
398-
* @return string Signed Metadata
399-
* @throws XMLSecurityException
400-
* @throws XPathExpressionException
401-
*/
402-
public static String signMetadata(String metadata, PrivateKey key, X509Certificate cert, String signAlgorithm, String digestAlgorithm) throws XPathExpressionException, XMLSecurityException
403-
{
404-
Document metadataDoc = Util.loadXML(metadata);
405-
String signedMetadata = Util.addSign(metadataDoc, key, cert, signAlgorithm, digestAlgorithm);
406-
LOGGER.debug("Signed metadata --> " + signedMetadata);
407-
return signedMetadata;
408-
}
347+
/**
348+
* Signs the metadata with the key/cert provided
349+
*
350+
* @param metadata SAML Metadata XML
351+
* @param key Private Key
352+
* @param cert x509 Public certificate
353+
* @param signAlgorithm Signature Algorithm
354+
* @return string Signed Metadata
355+
* @throws XMLSecurityException
356+
* @throws XPathExpressionException
357+
*/
358+
public static String signMetadata(String metadata, PrivateKey key, X509Certificate cert, String signAlgorithm) throws XPathExpressionException, XMLSecurityException {
359+
return signMetadata(metadata, key, cert, signAlgorithm, Constants.SHA1);
360+
}
361+
362+
/**
363+
* Signs the metadata with the key/cert provided
364+
*
365+
* @param metadata SAML Metadata XML
366+
* @param key Private Key
367+
* @param cert x509 Public certificate
368+
* @param signAlgorithm Signature Algorithm
369+
* @param digestAlgorithm Digest Algorithm
370+
* @return string Signed Metadata
371+
* @throws XMLSecurityException
372+
* @throws XPathExpressionException
373+
*/
374+
public static String signMetadata(String metadata, PrivateKey key, X509Certificate cert, String signAlgorithm, String digestAlgorithm) throws XPathExpressionException, XMLSecurityException {
375+
Document metadataDoc = Util.loadXML(metadata);
376+
String signedMetadata = Util.addSign(metadataDoc, key, cert, signAlgorithm, digestAlgorithm);
377+
LOGGER.debug("Signed metadata --> " + signedMetadata);
378+
return signedMetadata;
379+
}
409380
}

0 commit comments

Comments
 (0)