Skip to content

Commit cd19d4d

Browse files
author
mexmarv
committed
Fixed Deflated probelm and Added getAttributes, getAttribute methods.
Fixed deflated SAML request and added two methods for getting attributes.
1 parent 0a0beb1 commit cd19d4d

2 files changed

Lines changed: 138 additions & 97 deletions

File tree

com/onelogin/saml/AuthRequest.java

Lines changed: 79 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,121 @@
11
package com.onelogin.saml;
22

3+
import com.onelogin.AccountSettings;
4+
import com.onelogin.AppSettings;
35
import java.io.ByteArrayOutputStream;
4-
import java.nio.charset.Charset;
6+
import java.io.IOException;
57
import java.text.SimpleDateFormat;
68
import java.util.Date;
79
import java.util.UUID;
8-
10+
import java.util.zip.Deflater;
11+
import java.util.zip.DeflaterOutputStream;
912
import javax.xml.stream.XMLOutputFactory;
1013
import javax.xml.stream.XMLStreamException;
1114
import javax.xml.stream.XMLStreamWriter;
12-
1315
import org.apache.commons.codec.binary.Base64;
1416

15-
import com.onelogin.AccountSettings;
16-
import com.onelogin.AppSettings;
17-
1817
public class AuthRequest {
19-
20-
private String id;
21-
private String issueInstant;
22-
private AppSettings appSettings;
18+
19+
private final String id;
20+
private final String issueInstant;
21+
private final AppSettings appSettings;
2322
public static final int base64 = 1;
24-
25-
public AuthRequest(AppSettings appSettings, AccountSettings accountSettings){
26-
this.appSettings = appSettings;
27-
id="_"+UUID.randomUUID().toString();
23+
private Deflater deflater;
24+
25+
public AuthRequest(AppSettings appSettings, AccountSettings accountSettings){
26+
this.appSettings = appSettings;
27+
id="_"+UUID.randomUUID().toString();
2828
SimpleDateFormat simpleDf = new SimpleDateFormat("yyyy-MM-dd'T'H:mm:ss'Z'");
29-
issueInstant = simpleDf.format(new Date());
29+
issueInstant = simpleDf.format(new Date());
3030
}
31-
32-
public String getRequest(int format) throws XMLStreamException {
33-
ByteArrayOutputStream baos = new ByteArrayOutputStream();
31+
32+
public String getRequest(int format) throws XMLStreamException, IOException {
33+
String result = "";
34+
35+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
36+
3437
XMLOutputFactory factory = XMLOutputFactory.newInstance();
3538
XMLStreamWriter writer = factory.createXMLStreamWriter(baos);
36-
39+
3740
writer.writeStartElement("samlp", "AuthnRequest", "urn:oasis:names:tc:SAML:2.0:protocol");
3841
writer.writeNamespace("samlp","urn:oasis:names:tc:SAML:2.0:protocol");
39-
42+
4043
writer.writeAttribute("ID", id);
4144
writer.writeAttribute("Version", "2.0");
4245
writer.writeAttribute("IssueInstant", this.issueInstant);
4346
writer.writeAttribute("ProtocolBinding", "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
4447
writer.writeAttribute("AssertionConsumerServiceURL", this.appSettings.getAssertionConsumerServiceUrl());
45-
48+
4649
writer.writeStartElement("saml","Issuer","urn:oasis:names:tc:SAML:2.0:assertion");
4750
writer.writeNamespace("saml","urn:oasis:names:tc:SAML:2.0:assertion");
4851
writer.writeCharacters(this.appSettings.getIssuer());
4952
writer.writeEndElement();
50-
53+
5154
writer.writeStartElement("samlp", "NameIDPolicy", "urn:oasis:names:tc:SAML:2.0:protocol");
52-
55+
5356
writer.writeAttribute("Format", "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified");
5457
writer.writeAttribute("AllowCreate", "true");
5558
writer.writeEndElement();
56-
59+
5760
writer.writeStartElement("samlp","RequestedAuthnContext","urn:oasis:names:tc:SAML:2.0:protocol");
58-
61+
5962
writer.writeAttribute("Comparison", "exact");
60-
writer.writeEndElement();
61-
63+
6264
writer.writeStartElement("saml","AuthnContextClassRef","urn:oasis:names:tc:SAML:2.0:assertion");
6365
writer.writeNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion");
6466
writer.writeCharacters("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport");
6567
writer.writeEndElement();
66-
68+
6769
writer.writeEndElement();
68-
writer.flush();
69-
70-
if (format == base64) {
71-
byte [] encoded = Base64.encodeBase64Chunked(baos.toByteArray());
72-
String result = new String(encoded,Charset.forName("UTF-8"));
73-
74-
return result;
75-
}
76-
77-
return null;
70+
writer.writeEndElement();
71+
writer.flush();
72+
73+
result = encodeSAMLRequest(baos.toByteArray());
74+
return result;
7875
}
79-
80-
public static String getRidOfCRLF(String what) {
81-
String lf = "%0D";
82-
String cr = "%0A";
83-
String now = lf;
84-
85-
int index = what.indexOf(now);
86-
StringBuffer r = new StringBuffer();
87-
88-
while (index!=-1) {
89-
r.append(what.substring(0,index));
90-
what = what.substring(index+3,what.length());
91-
92-
if (now.equals(lf)) {
93-
now = cr;
94-
} else {
95-
now = lf;
96-
}
97-
98-
index = what.indexOf(now);
99-
}
100-
return r.toString();
101-
}
76+
77+
public static String getRidOfCRLF(String what) {
78+
String lf = "%0D";
79+
String cr = "%0A";
80+
String now = lf;
81+
82+
int index = what.indexOf(now);
83+
StringBuilder r = new StringBuilder();
84+
85+
while (index!=-1) {
86+
r.append(what.substring(0,index));
87+
what = what.substring(index+3,what.length());
88+
89+
if (now.equals(lf)) {
90+
now = cr;
91+
} else {
92+
now = lf;
93+
}
94+
95+
index = what.indexOf(now);
96+
}
97+
return r.toString();
98+
}
99+
100+
private String encodeSAMLRequest(byte[] pSAMLRequest) throws RuntimeException {
101+
102+
Base64 base64Encoder = new Base64();
103+
104+
try {
105+
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
106+
Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
107+
108+
DeflaterOutputStream def = new DeflaterOutputStream(byteArray, deflater);
109+
def.write(pSAMLRequest);
110+
def.close();
111+
byteArray.close();
112+
113+
String stream = new String(base64Encoder.encode(byteArray.toByteArray()));
114+
115+
return stream;
116+
} catch (Exception e) {
117+
throw new RuntimeException(e);
118+
}
119+
}
102120

103121
}

com/onelogin/saml/Response.java

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,58 @@
11
package com.onelogin.saml;
22

3+
import com.onelogin.AccountSettings;
34
import java.io.ByteArrayInputStream;
45
import java.io.IOException;
6+
import java.lang.reflect.Method;
57
import java.security.cert.CertificateException;
68
import java.security.cert.X509Certificate;
7-
9+
import java.util.ArrayList;
10+
import java.util.HashMap;
11+
import java.util.Iterator;
12+
import java.util.Map;
813
import javax.xml.XMLConstants;
914
import javax.xml.crypto.dsig.XMLSignature;
1015
import javax.xml.crypto.dsig.XMLSignatureFactory;
1116
import javax.xml.crypto.dsig.dom.DOMValidateContext;
1217
import javax.xml.parsers.DocumentBuilder;
1318
import javax.xml.parsers.DocumentBuilderFactory;
1419
import javax.xml.parsers.ParserConfigurationException;
15-
1620
import org.apache.commons.codec.binary.Base64;
1721
import org.w3c.dom.Document;
18-
import org.w3c.dom.NodeList;
19-
import org.xml.sax.SAXException;
20-
21-
import com.onelogin.AccountSettings;
22-
import java.lang.reflect.Method;
2322
import org.w3c.dom.Element;
23+
import org.w3c.dom.NamedNodeMap;
2424
import org.w3c.dom.Node;
25+
import org.w3c.dom.NodeList;
26+
import org.xml.sax.SAXException;
2527

2628
public class Response {
27-
29+
2830
private Document xmlDoc;
29-
private AccountSettings accountSettings;
30-
private Certificate certificate;
31-
31+
private final AccountSettings accountSettings;
32+
private final Certificate certificate;
33+
3234
public Response(AccountSettings accountSettings) throws CertificateException {
3335
this.accountSettings = accountSettings;
3436
certificate = new Certificate();
3537
certificate.loadCertificate(this.accountSettings.getCertificate());
3638
}
37-
39+
3840
public void loadXml(String xml) throws ParserConfigurationException, SAXException, IOException {
3941
DocumentBuilderFactory fty = DocumentBuilderFactory.newInstance();
4042
fty.setNamespaceAware(true);
4143
fty.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
4244
DocumentBuilder builder = fty.newDocumentBuilder();
4345
ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
44-
xmlDoc = builder.parse(bais);
46+
xmlDoc = builder.parse(bais);
4547
}
46-
47-
48+
4849
public void loadXmlFromBase64(String response) throws ParserConfigurationException, SAXException, IOException {
4950
Base64 base64 = new Base64();
50-
byte [] decodedB = base64.decode(response);
51-
String decodedS = new String(decodedB);
52-
loadXml(decodedS);
51+
byte [] decodedB = base64.decode(response);
52+
String decodedS = new String(decodedB);
53+
loadXml(decodedS);
5354
}
54-
55+
5556
public boolean isValid() throws Exception {
5657
NodeList nodes = xmlDoc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
5758

@@ -70,28 +71,45 @@ public boolean isValid() throws Exception {
7071

7172
return xmlSignature.validate(ctx);
7273
}
73-
74+
7475
public String getNameId() throws Exception {
75-
NodeList nodes = xmlDoc.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "NameID");
76+
NodeList nodes = xmlDoc.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "NameID");
7677

77-
if(nodes.getLength()==0){
78-
throw new Exception("No name id found in document");
79-
}
78+
if(nodes.getLength()==0){
79+
throw new Exception("No name id found in document");
80+
}
8081

81-
return nodes.item(0).getTextContent();
82-
}
82+
return nodes.item(0).getTextContent();
83+
}
8384

84-
private void tagIdAttributes(Document xmlDoc) {
85-
NodeList nodeList = xmlDoc.getElementsByTagName("*");
86-
for (int i = 0; i < nodeList.getLength(); i++) {
87-
Node node = nodeList.item(i);
88-
if (node.getNodeType() == Node.ELEMENT_NODE) {
89-
if (node.getAttributes().getNamedItem("ID") != null) {
90-
((Element) node).setIdAttribute("ID", true);
91-
}
92-
}
85+
public String getAttribute(String name) {
86+
HashMap attributes = getAttributes();
87+
if (!attributes.isEmpty()) {
88+
return attributes.get(name).toString();
9389
}
90+
return null;
9491
}
92+
93+
public HashMap getAttributes() {
94+
HashMap<String,ArrayList> attributes = new HashMap<>();
95+
NodeList nodes = xmlDoc.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Attribute");
96+
97+
if(nodes.getLength()!=0){
98+
for (int i = 0; i < nodes.getLength(); i++) {
99+
NamedNodeMap attrName = nodes.item(i).getAttributes();
100+
String attName = attrName.getNamedItem("Name").getNodeValue();
101+
NodeList children = nodes.item(i).getChildNodes();
102+
103+
ArrayList<String> attrValues = new ArrayList<String>();
104+
for (int j = 0; j < children.getLength(); j++) {
105+
attrValues.add(children.item(j).getTextContent());
106+
}
107+
attributes.put(attName, attrValues);
108+
}
109+
} else
110+
return null;
111+
return attributes;
112+
}
95113

96114
private boolean setIdAttributeExists() {
97115
for (Method method : Element.class.getDeclaredMethods()) {
@@ -102,5 +120,10 @@ private boolean setIdAttributeExists() {
102120
return false;
103121
}
104122

105-
123+
private void tagIdAttributes(Document xmlDoc) {
124+
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
125+
}
126+
127+
128+
106129
}

0 commit comments

Comments
 (0)