Skip to content

Commit 89ce157

Browse files
committed
Allow java-saml to be used in non-JavaEE containers
The default Auth and ServletUtils classes were previously tied to the javax.servlet APIs, so couldn't be used in other frameworks (e.g. Play) Instead, introduce abstract HttpRequest and HttpResponse classes which can be used as wrappers around different request and response objects depending on the framework (plus default javax implementations).
1 parent 9274e6b commit 89ce157

13 files changed

Lines changed: 591 additions & 539 deletions

File tree

toolkit/src/main/java/com/onelogin/saml2/Auth.java renamed to core/src/main/java/com/onelogin/saml2/Auth.java

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
import java.util.List;
1313
import java.util.Map;
1414

15-
import javax.servlet.http.HttpServletRequest;
16-
import javax.servlet.http.HttpServletResponse;
17-
1815
import org.apache.commons.lang3.StringUtils;
1916
import org.joda.time.DateTime;
2017
import org.joda.time.Instant;
@@ -27,6 +24,7 @@
2724
import com.onelogin.saml2.exception.Error;
2825
import com.onelogin.saml2.exception.XMLEntityException;
2926
import com.onelogin.saml2.http.HttpRequest;
27+
import com.onelogin.saml2.http.HttpResponse;
3028
import com.onelogin.saml2.logout.LogoutRequest;
3129
import com.onelogin.saml2.logout.LogoutResponse;
3230
import com.onelogin.saml2.servlet.ServletUtils;
@@ -57,14 +55,14 @@ public class Auth {
5755
private Saml2Settings settings;
5856

5957
/**
60-
* HttpServletRequest object to be processed (Contains GET and POST parameters, session, ...).
58+
* HttpRequest object to be processed (Contains GET and POST parameters, session, ...).
6159
*/
62-
private HttpServletRequest request;
60+
private HttpRequest request;
6361

6462
/**
65-
* HttpServletResponse object to be used (For example to execute the redirections).
63+
* HttpResponse object to be used (For example to execute the redirections).
6664
*/
67-
private HttpServletResponse response;
65+
private HttpResponse response;
6866

6967
/**
7068
* NameID.
@@ -168,15 +166,15 @@ public Auth(String filename) throws IOException, SettingsException, Error {
168166
* Initializes the SP SAML instance.
169167
*
170168
* @param request
171-
* HttpServletRequest object to be processed
169+
* HttpRequest object to be processed
172170
* @param response
173-
* HttpServletResponse object to be used
171+
* HttpResponse object to be used
174172
*
175173
* @throws IOException
176174
* @throws SettingsException
177175
* @throws Error
178176
*/
179-
public Auth(HttpServletRequest request, HttpServletResponse response) throws IOException, SettingsException, Error {
177+
public Auth(HttpRequest request, HttpResponse response) throws IOException, SettingsException, Error {
180178
this(new SettingsBuilder().fromFile("onelogin.saml.properties").build(), request, response);
181179
}
182180

@@ -186,15 +184,15 @@ public Auth(HttpServletRequest request, HttpServletResponse response) throws IOE
186184
* @param filename
187185
* String Filename with the settings
188186
* @param request
189-
* HttpServletRequest object to be processed
187+
* HttpRequest object to be processed
190188
* @param response
191-
* HttpServletResponse object to be used
189+
* HttpResponse object to be used
192190
*
193191
* @throws SettingsException
194192
* @throws IOException
195193
* @throws Error
196194
*/
197-
public Auth(String filename, HttpServletRequest request, HttpServletResponse response) throws SettingsException, IOException, Error {
195+
public Auth(String filename, HttpRequest request, HttpResponse response) throws SettingsException, IOException, Error {
198196
this(new SettingsBuilder().fromFile(filename).build(), request, response);
199197
}
200198

@@ -204,13 +202,13 @@ public Auth(String filename, HttpServletRequest request, HttpServletResponse res
204202
* @param settings
205203
* Saml2Settings object. Setting data
206204
* @param request
207-
* HttpServletRequest object to be processed
205+
* HttpRequest object to be processed
208206
* @param response
209-
* HttpServletResponse object to be used
207+
* HttpResponse object to be used
210208
*
211209
* @throws SettingsException
212210
*/
213-
public Auth(Saml2Settings settings, HttpServletRequest request, HttpServletResponse response) throws SettingsException {
211+
public Auth(Saml2Settings settings, HttpRequest request, HttpResponse response) throws SettingsException {
214212
this.settings = settings;
215213
this.request = request;
216214
this.response = response;
@@ -516,11 +514,10 @@ public String getSLOResponseUrl() {
516514
*/
517515
public void processResponse(String requestId) throws Exception {
518516
authenticated = false;
519-
final HttpRequest httpRequest = ServletUtils.makeHttpRequest(this.request);
520-
final String samlResponseParameter = httpRequest.getParameter("SAMLResponse");
517+
final String samlResponseParameter = request.getParameter("SAMLResponse");
521518

522519
if (samlResponseParameter != null) {
523-
SamlResponse samlResponse = new SamlResponse(settings, httpRequest);
520+
SamlResponse samlResponse = new SamlResponse(settings, request);
524521
lastResponse = samlResponse.getSAMLResponseXml();
525522

526523
if (samlResponse.isValid(requestId)) {
@@ -568,13 +565,12 @@ public void processResponse() throws Exception {
568565
* @throws Exception
569566
*/
570567
public void processSLO(Boolean keepLocalSession, String requestId) throws Exception {
571-
final HttpRequest httpRequest = ServletUtils.makeHttpRequest(this.request);
572568

573-
final String samlRequestParameter = httpRequest.getParameter("SAMLRequest");
574-
final String samlResponseParameter = httpRequest.getParameter("SAMLResponse");
569+
final String samlRequestParameter = request.getParameter("SAMLRequest");
570+
final String samlResponseParameter = request.getParameter("SAMLResponse");
575571

576572
if (samlResponseParameter != null) {
577-
LogoutResponse logoutResponse = new LogoutResponse(settings, httpRequest);
573+
LogoutResponse logoutResponse = new LogoutResponse(settings, request);
578574
lastResponse = logoutResponse.getLogoutResponseXml();
579575
if (!logoutResponse.isValid(requestId)) {
580576
errors.add("invalid_logout_response");
@@ -591,12 +587,12 @@ public void processSLO(Boolean keepLocalSession, String requestId) throws Except
591587
lastMessageId = logoutResponse.getId();
592588
LOGGER.debug("processSLO success --> " + samlResponseParameter);
593589
if (!keepLocalSession) {
594-
request.getSession().invalidate();
590+
request.invalidateSession();
595591
}
596592
}
597593
}
598594
} else if (samlRequestParameter != null) {
599-
LogoutRequest logoutRequest = new LogoutRequest(settings, httpRequest);
595+
LogoutRequest logoutRequest = new LogoutRequest(settings, request);
600596
lastRequest = logoutRequest.getLogoutRequestXml();
601597
if (!logoutRequest.isValid()) {
602598
errors.add("invalid_logout_request");
@@ -607,11 +603,11 @@ public void processSLO(Boolean keepLocalSession, String requestId) throws Except
607603
lastMessageId = logoutRequest.getId();
608604
LOGGER.debug("processSLO success --> " + samlRequestParameter);
609605
if (!keepLocalSession) {
610-
request.getSession().invalidate();
606+
request.invalidateSession();
611607
}
612608

613609
String inResponseTo = logoutRequest.id;
614-
LogoutResponse logoutResponseBuilder = new LogoutResponse(settings, httpRequest);
610+
LogoutResponse logoutResponseBuilder = new LogoutResponse(settings, request);
615611
logoutResponseBuilder.build(inResponseTo);
616612
lastResponse = logoutResponseBuilder.getLogoutResponseXml();
617613

@@ -819,7 +815,7 @@ public String buildResponseSignature(String samlResponse, String relayState, Str
819815
/**
820816
* Generates the Signature for a SAML Response
821817
*
822-
* @param samlResponse
818+
* @param samlMessage
823819
* The SAML Response
824820
* @param relayState
825821
* The RelayState
Lines changed: 26 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,151 +1,61 @@
11
package com.onelogin.saml2.http;
22

3-
import static com.onelogin.saml2.util.Preconditions.checkNotNull;
4-
import static java.util.Collections.unmodifiableList;
5-
import static java.util.Collections.unmodifiableMap;
3+
import com.onelogin.saml2.util.Util;
64

7-
import java.util.ArrayList;
8-
import java.util.Collections;
9-
import java.util.HashMap;
10-
import java.util.List;
11-
import java.util.Map;
12-
import java.util.Objects;
135
import java.util.regex.Matcher;
146
import java.util.regex.Pattern;
157

16-
import org.apache.commons.lang3.StringUtils;
17-
18-
import com.onelogin.saml2.util.Util;
19-
208
/**
219
* Framework-agnostic representation of an HTTP request.
2210
*
2311
* @since 2.0.0
2412
*/
25-
public final class HttpRequest {
26-
27-
public static final Map<String, List<String>> EMPTY_PARAMETERS = Collections.<String, List<String>>emptyMap();
28-
29-
private final String requestURL;
30-
private final Map<String, List<String>> parameters;
31-
private final String queryString;
13+
public abstract class HttpRequest {
3214

3315
/**
34-
* Creates a new HttpRequest.
35-
*
36-
* @param requestURL the request URL (up to but not including query parameters)
37-
* @throws NullPointerException if requestURL is null
38-
* @deprecated Not providing a queryString can cause HTTP Redirect binding to fail.
16+
* @return true if the request is using a secure scheme (HTTPS)
3917
*/
40-
@Deprecated
41-
public HttpRequest(String requestURL) {
42-
this(requestURL, EMPTY_PARAMETERS);
43-
}
18+
public abstract boolean isSecure();
4419

4520
/**
46-
* Creates a new HttpRequest.
47-
*
48-
* @param requestURL the request URL (up to but not including query parameters)
49-
* @param queryString string that is contained in the request URL after the path
21+
* @return the name of the request protocol (HTTP / HTTPS)
5022
*/
51-
public HttpRequest(String requestURL, String queryString) {
52-
this(requestURL, EMPTY_PARAMETERS, queryString);
53-
}
23+
public abstract String getScheme();
5424

5525
/**
56-
* Creates a new HttpRequest.
57-
*
58-
* @param requestURL the request URL (up to but not including query parameters)
59-
* @param parameters the request query parameters
60-
* @throws NullPointerException if any of the parameters is null
61-
* @deprecated Not providing a queryString can cause HTTP Redirect binding to fail.
26+
* @return the server name in the request e.g. www.example.com
6227
*/
63-
@Deprecated
64-
public HttpRequest(String requestURL, Map<String, List<String>> parameters) {
65-
this(requestURL, parameters, null);
66-
}
28+
public abstract String getServerName();
6729

6830
/**
69-
* Creates a new HttpRequest.
70-
*
71-
* @param requestURL the request URL (up to but not including query parameters)
72-
* @param parameters the request query parameters
73-
* @param queryString string that is contained in the request URL after the path
74-
* @throws NullPointerException if any of the parameters is null
31+
* @return the port over which the request is made e.g. 80 or 443
7532
*/
76-
public HttpRequest(String requestURL, Map<String, List<String>> parameters, String queryString) {
77-
this.requestURL = checkNotNull(requestURL, "requestURL");
78-
this.parameters = unmodifiableCopyOf(checkNotNull(parameters, "queryParams"));
79-
this.queryString = StringUtils.trimToEmpty(queryString);
80-
}
33+
public abstract int getServerPort();
8134

8235
/**
83-
* @param name the query parameter name
84-
* @param value the query parameter value
85-
* @return a new HttpRequest with the given query parameter added
86-
* @throws NullPointerException if any of the parameters is null
36+
* @return the query string part of the URL
8737
*/
88-
public HttpRequest addParameter(String name, String value) {
89-
checkNotNull(name, "name");
90-
checkNotNull(value, "value");
91-
92-
final List<String> oldValues = parameters.containsKey(name) ? parameters.get(name) : new ArrayList<String>();
93-
final List<String> newValues = new ArrayList<>(oldValues);
94-
newValues.add(value);
95-
final Map<String, List<String>> params = new HashMap<>(parameters);
96-
params.put(name, newValues);
97-
98-
return new HttpRequest(requestURL, params, queryString);
99-
}
38+
public abstract String getQueryString();
10039

10140
/**
102-
* @param name the query parameter name
103-
* @return a new HttpRequest with the given query parameter removed
104-
* @throws NullPointerException if any of the parameters is null
41+
* @return the URI the client used to make the request - only includes
42+
* the server path, but not the query string parameters.
10543
*/
106-
public HttpRequest removeParameter(String name) {
107-
checkNotNull(name, "name");
108-
109-
final Map<String, List<String>> params = new HashMap<>(parameters);
110-
params.remove(name);
44+
public abstract String getRequestURI();
11145

112-
return new HttpRequest(requestURL, params, queryString);
113-
}
114-
11546
/**
11647
* The URL the client used to make the request. Includes a protocol, server name, port number, and server path, but
11748
* not the query string parameters.
11849
*
11950
* @return the request URL
12051
*/
121-
public String getRequestURL() {
122-
return requestURL;
123-
}
52+
public abstract String getRequestURL();
12453

12554
/**
12655
* @param name the query parameter name
12756
* @return the first value for the parameter, or null
12857
*/
129-
public String getParameter(String name) {
130-
List<String> values = getParameters(name);
131-
return values.isEmpty() ? null : values.get(0);
132-
}
133-
134-
/**
135-
* @param name the query parameter name
136-
* @return a List containing all values for the parameter
137-
*/
138-
public List<String> getParameters(String name) {
139-
List<String> values = parameters.get(name);
140-
return values != null ? values : Collections.<String>emptyList();
141-
}
142-
143-
/**
144-
* @return a map of all query parameters
145-
*/
146-
public Map<String, List<String>> getParameters() {
147-
return parameters;
148-
}
58+
public abstract String getParameter(String name);
14959

15060
/**
15161
* Return an url encoded get parameter value
@@ -155,8 +65,8 @@ public Map<String, List<String>> getParameters() {
15565
* @param name
15666
* @return the first value for the parameter, or null
15767
*/
158-
public String getEncodedParameter(String name) {
159-
Matcher matcher = Pattern.compile(Pattern.quote(name) + "=([^&#]+)").matcher(queryString);
68+
public final String getEncodedParameter(String name) {
69+
Matcher matcher = Pattern.compile(Pattern.quote(name) + "=([^&#]+)").matcher(getQueryString());
16070
if (matcher.find()) {
16171
return matcher.group(1);
16272
} else {
@@ -173,49 +83,13 @@ public String getEncodedParameter(String name) {
17383
* @param defaultValue
17484
* @return the first value for the parameter, or url encoded default value
17585
*/
176-
public String getEncodedParameter(String name, String defaultValue) {
177-
String value = getEncodedParameter(name);
178-
return (value != null ? value : Util.urlEncoder(defaultValue));
179-
}
180-
181-
@Override
182-
public boolean equals(Object o) {
183-
if (this == o) {
184-
return true;
185-
}
186-
187-
if (o == null || getClass() != o.getClass()) {
188-
return false;
189-
}
190-
191-
HttpRequest that = (HttpRequest) o;
192-
return Objects.equals(requestURL, that.requestURL) &&
193-
Objects.equals(parameters, that.parameters) &&
194-
Objects.equals(queryString, that.queryString);
86+
public final String getEncodedParameter(String name, String defaultValue) {
87+
String value = getEncodedParameter(name);
88+
return (value != null ? value : Util.urlEncoder(defaultValue));
19589
}
19690

197-
@Override
198-
public int hashCode() {
199-
return Objects.hash(requestURL, parameters, queryString);
200-
}
201-
202-
@Override
203-
public String toString() {
204-
return "HttpRequest{" +
205-
"requestURL='" + requestURL + '\'' +
206-
", parameters=" + parameters +
207-
", queryString=" + queryString +
208-
'}';
209-
}
210-
211-
private static Map<String, List<String>> unmodifiableCopyOf(Map<String, List<String>> orig) {
212-
Map<String, List<String>> copy = new HashMap<>();
213-
for (Map.Entry<String, List<String>> entry : orig.entrySet()) {
214-
copy.put(entry.getKey(), unmodifiableList(new ArrayList<>(entry.getValue())));
215-
}
216-
217-
return unmodifiableMap(copy);
218-
}
219-
220-
91+
/**
92+
* Invalidate the current session
93+
*/
94+
public abstract void invalidateSession();
22195
}

0 commit comments

Comments
 (0)