Skip to content

Commit db5faa4

Browse files
committed
Merge pull request #28 from iguanajazz/master
Add security to avoid XXE Injection, add support for relay state and refactoring. INT-274
2 parents 3195ae5 + 132cd91 commit db5faa4

12 files changed

Lines changed: 733 additions & 134 deletions

File tree

pom.xml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,38 @@
55
<artifactId>java-saml</artifactId>
66
<version>1.0-SNAPSHOT</version>
77
<name>java-saml</name>
8-
8+
9+
<properties>
10+
<slf4jVersion>1.7.12</slf4jVersion>
11+
<junitVersion>4.12</junitVersion>
12+
</properties>
13+
914
<dependencies>
15+
<dependency>
16+
<groupId>junit</groupId>
17+
<artifactId>junit</artifactId>
18+
<version>${junitVersion}</version>
19+
<scope>test</scope>
20+
</dependency>
1021
<dependency>
1122
<groupId>commons-codec</groupId>
1223
<artifactId>commons-codec</artifactId>
1324
<version>1.9</version>
1425
</dependency>
26+
<dependency>
27+
<groupId>org.slf4j</groupId>
28+
<artifactId>slf4j-api</artifactId>
29+
<version>${slf4jVersion}</version>
30+
</dependency>
31+
<dependency>
32+
<groupId>org.slf4j</groupId>
33+
<artifactId>slf4j-simple</artifactId>
34+
<version>${slf4jVersion}</version>
35+
</dependency>
1536
</dependencies>
1637

1738
<build>
18-
<finalName>java-saml</finalName>
39+
<finalName>java-saml-toolkit</finalName>
1940
<plugins>
2041
<plugin>
2142
<groupId>org.apache.maven.plugins</groupId>

sample/src/main/webapp/consume.jsp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626
accountSettings.setCertificate(certificateS);
2727
2828
Response samlResponse = new Response(accountSettings);
29+
request.getSession().setAttribute("mySAMLResponse", request.getParameter("SAMLResponse"));
2930
samlResponse.loadXmlFromBase64(request.getParameter("SAMLResponse"));
30-
samlResponse.setDestinationUrl(request.getRequestURL().toString());
31+
samlResponse.setDestinationUrl(request.getRequestURL().toString());
3132
3233
if (samlResponse.isValid()) {
3334
@@ -37,15 +38,16 @@
3738
String nameId = samlResponse.getNameId();
3839
writer.write(nameId);
3940
writer.flush();
40-
41+
4142
} else {
4243
4344
// the signature of the SAML Response is not valid
4445
java.io.PrintWriter writer = response.getWriter();
45-
writer.write("Failed");
46+
writer.write("Failed\n");
47+
writer.write(samlResponse.getError());
4648
writer.flush();
4749
4850
}
4951
%>
5052
</body>
51-
</html>
53+
</html>

sample/src/main/webapp/index.jsp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<%@page import="java.net.URLEncoder"%>
2+
<%@ page import = "java.util.Map" %>
23
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
34
<%@ page import="com.onelogin.saml.*,com.onelogin.*" %>
45
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
@@ -15,21 +16,31 @@
1516
appSettings.setAssertionConsumerServiceUrl("http://localhost:8080/consume.jsp");
1617
1718
// set the issuer of the authentication request. This would usually be the URL of the issuing web application
18-
appSettings.setIssuer("https://www.mywebapp.com");
19-
20-
// the accSettings object contains settings specific to the users account.
19+
appSettings.setIssuer("http://localhost:8080/index.jsp");
20+
21+
// the accSettings object contains settings specific to the users account.
2122
// At this point, your application must have identified the users origin
2223
AccountSettings accSettings = new AccountSettings();
2324
2425
// The URL at the Identity Provider where to the authentication request should be sent
2526
accSettings.setIdpSsoTargetUrl("https://app.onelogin.com/saml/signon/20956");
26-
27+
2728
// Generate an AuthRequest and send it to the identity provider
2829
AuthRequest authReq = new AuthRequest(appSettings, accSettings);
29-
String reqString = accSettings.getIdp_sso_target_url()+"?SAMLRequest=" + URLEncoder.encode(authReq.getRequest(AuthRequest.base64),"UTF-8");
30+
31+
//Get RelayState
32+
Map<String, String[]> parameters = request.getParameterMap();
33+
String relayState = null;
34+
for(String parameter : parameters.keySet()) {
35+
if(parameter.equalsIgnoreCase("relaystate")) {
36+
String[] values = parameters.get(parameter);
37+
relayState = values[0];
38+
}
39+
}
40+
String reqString = authReq.getSSOurl(relayState);
3041
response.sendRedirect(reqString);
3142
%>
3243
</head>
3344
<body>
3445
</body>
35-
</html>
46+
</html>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.onelogin;
2+
3+
public class Constants {
4+
// Value added to the current time in time condition validations
5+
public static Integer ALOWED_CLOCK_DRIFT = 180; // 3 min in seconds
6+
7+
// NameID Formats
8+
public static String NAMEID_EMAIL_ADDRESS = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";
9+
public static String NAMEID_X509_SUBJECT_NAME = "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName";
10+
public static String NAMEID_WINDOWS_DOMAIN_QUALIFIED_NAME = "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName";
11+
public static String NAMEID_KERBEROS = "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos";
12+
public static String NAMEID_ENTITY = "urn:oasis:names:tc:SAML:2.0:nameid-format:entity";
13+
public static String NAMEID_TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient";
14+
public static String NAMEID_PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent";
15+
public static String NAMEID_ENCRYPTED = "urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted";
16+
17+
// Attribute Name Formats
18+
public static String ATTRNAME_FORMAT_UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified";
19+
public static String ATTRNAME_FORMAT_URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
20+
public static String ATTRNAME_FORMAT_BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic";
21+
22+
// Namespaces
23+
public static String NS_SAML = "urn:oasis:names:tc:SAML:2.0:assertion";
24+
public static String NS_SAMLP = "urn:oasis:names:tc:SAML:2.0:protocol";
25+
public static String NS_SOAP = "http://schemas.xmlsoap.org/soap/envelope/";
26+
public static String NS_MD = "urn:oasis:names:tc:SAML:2.0:metadata";
27+
public static String NS_XS = "http://www.w3.org/2001/XMLSchema";
28+
public static String NS_XSI = "http://www.w3.org/2001/XMLSchema-instance";
29+
public static String NS_XENC = "http://www.w3.org/2001/04/xmlenc#";
30+
public static String NS_DS = "http://www.w3.org/2000/09/xmldsig#";
31+
32+
// Bindings
33+
public static String BINDING_HTTP_POST = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST";
34+
public static String BINDING_HTTP_REDIRECT = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect";
35+
public static String BINDING_HTTP_ARTIFACT = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact";
36+
public static String BINDING_SOAP = "urn:oasis:names:tc:SAML:2.0:bindings:SOAP";
37+
public static String BINDING_DEFLATE = "urn:oasis:names:tc:SAML:2.0:bindings:URL-Encoding:DEFLATE";
38+
39+
// Auth Context Class
40+
public static String AC_UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified";
41+
public static String AC_PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password";
42+
public static String AC_X509 = "urn:oasis:names:tc:SAML:2.0:ac:classes:X509";
43+
public static String AC_SMARTCARD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Smartcard";
44+
public static String AC_KERBEROS = "urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos";
45+
46+
// Subject Confirmation
47+
public static String CM_BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer";
48+
public static String CM_HOLDER_KEY = "urn:oasis:names:tc:SAML:2.0:cm:holder-of-key";
49+
public static String CM_SENDER_VOUCHES = "urn:oasis:names:tc:SAML:2.0:cm:sender-vouches";
50+
51+
// Status Codes
52+
public static String STATUS_SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success";
53+
public static String STATUS_REQUESTER = "urn:oasis:names:tc:SAML:2.0:status:Requester";
54+
public static String STATUS_RESPONDER = "urn:oasis:names:tc:SAML:2.0:status:Responder";
55+
public static String STATUS_VERSION_MISMATCH = "urn:oasis:names:tc:SAML:2.0:status:VersionMismatch";
56+
public static String STATUS_NO_PASSIVE = "urn:oasis:names:tc:SAML:2.0:status:NoPassive";
57+
public static String STATUS_PARTIAL_LOGOUT = "urn:oasis:names:tc:SAML:2.0:status:PartialLogout";
58+
public static String STATUS_PROXY_COUNT_EXCEEDED = "urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded";
59+
60+
// XMLSecurityKey
61+
public static String RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
62+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.onelogin;
2+
3+
/**
4+
* Error class of OneLogin Java Toolkit Defines the Error class
5+
*/
6+
@SuppressWarnings("serial")
7+
public class Error extends Exception {
8+
// Errors
9+
public static Integer SETTINGS_FILE_NOT_FOUND = 0;
10+
public static Integer SETTINGS_INVALID_SYNTAX = 1;
11+
public static Integer SETTINGS_INVALID = 2;
12+
public static Integer METADATA_SP_INVALID = 3;
13+
public static Integer SP_CERTS_NOT_FOUND = 4;
14+
public static Integer REDIRECT_INVALID_URL = 5;
15+
public static Integer PUBLIC_CERT_FILE_NOT_FOUND = 6;
16+
public static Integer PRIVATE_KEY_FILE_NOT_FOUND = 7;
17+
public static Integer SAML_RESPONSE_NOT_FOUND = 8;
18+
public static Integer SAML_LOGOUTMESSAGE_NOT_FOUND = 9;
19+
public static Integer SAML_LOGOUTREQUEST_INVALID = 10;
20+
public static Integer SAML_LOGOUTRESPONSE_INVALID = 11;
21+
public static Integer SAML_SINGLE_LOGOUT_NOT_SUPPORTED = 12;
22+
23+
public Error() {
24+
}
25+
26+
/**
27+
* Constructor that receives a message string.
28+
*
29+
* @param message
30+
* Error message
31+
*/
32+
public Error(String message) {
33+
super(message);
34+
}
35+
36+
/**
37+
* Constructor that receives a message string and an inner exception.
38+
*
39+
* @param message
40+
* Error Message
41+
* @param inner
42+
* Inner exception
43+
*/
44+
public Error(String message, Exception inner) {
45+
super(message, inner);
46+
}
47+
}

src/main/java/com/onelogin/saml/AuthRequest.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,36 @@
22

33
import com.onelogin.AccountSettings;
44
import com.onelogin.AppSettings;
5+
56
import java.io.ByteArrayOutputStream;
67
import java.io.IOException;
8+
import java.io.UnsupportedEncodingException;
9+
import java.net.URLEncoder;
710
import java.text.SimpleDateFormat;
811
import java.util.Date;
12+
import java.util.Map;
913
import java.util.UUID;
1014
import java.util.zip.Deflater;
1115
import java.util.zip.DeflaterOutputStream;
16+
1217
import javax.xml.stream.XMLOutputFactory;
1318
import javax.xml.stream.XMLStreamException;
1419
import javax.xml.stream.XMLStreamWriter;
20+
1521
import org.apache.commons.codec.binary.Base64;
1622

1723
public class AuthRequest {
1824

1925
private final String id;
2026
private final String issueInstant;
2127
private final AppSettings appSettings;
28+
private AccountSettings accountSettings;
2229
public static final int base64 = 1;
2330
private Deflater deflater;
2431

25-
public AuthRequest(AppSettings appSettings, AccountSettings accountSettings){
32+
public AuthRequest(AppSettings appSettings, AccountSettings accSettings){
2633
this.appSettings = appSettings;
34+
this.accountSettings = accSettings;
2735
id="_"+UUID.randomUUID().toString();
2836
SimpleDateFormat simpleDf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
2937
issueInstant = simpleDf.format(new Date());
@@ -94,4 +102,20 @@ private String encodeSAMLRequest(byte[] pSAMLRequest) throws RuntimeException {
94102
throw new RuntimeException(e);
95103
}
96104
}
105+
106+
107+
public String getSSOurl(String relayState) throws UnsupportedEncodingException, XMLStreamException, IOException{
108+
109+
String ssourl = getSSOurl();
110+
if(relayState != null && !relayState.isEmpty()){
111+
ssourl = ssourl + "&RelayState=" + relayState;
112+
}
113+
return ssourl;
114+
}
115+
116+
public String getSSOurl() throws UnsupportedEncodingException, XMLStreamException, IOException{
117+
String ssourl = accountSettings.getIdp_sso_target_url()+"?SAMLRequest=" + URLEncoder.encode(getRequest(base64),"UTF-8");
118+
return ssourl;
119+
}
120+
97121
}

0 commit comments

Comments
 (0)