Skip to content

Commit 2917a41

Browse files
committed
Change factory approach to use just a single multi-message factory
In this way the API of Auth gets simplified.
1 parent b54bff0 commit 2917a41

File tree

6 files changed

+201
-197
lines changed

6 files changed

+201
-197
lines changed

README.md

+16-10
Original file line numberDiff line numberDiff line change
@@ -653,19 +653,25 @@ All the provided SAML message classes (`AuthnRequest`, `SamlResponse`, `LogoutRe
653653

654654
In particular, the classes used to produce outgoing messages (`AuthnRequest`, `LogoutRequest`, and `LogoutResponse`) also provide a `postProcessXml` method that can be overridden to customise the generation of the corresponding SAML message XML, along with the ability to pass in proper extensions of the input parameter classes (`AuthnRequestParams`, `LogoutRequestParams`, and `LogoutResponseParams` respectively).
655655

656-
Once you have prepared your extension classes, in order to make the `Auth` class use them, appropriate factories can then be
657-
specified:
656+
Once you have prepared your extension classes, in order to make the `Auth` class use them, an appropriate `SamlMessageFactory` implementation can be specified. As an example, assuming you've created two extension classes `AuthnRequestEx` and `SamlResponseEx` to customise the creation of AuthnRequest SAML messages and the validation of SAML responses respectively, as well as an extended `AuthnRequestParamsEx` input parameter class to drive the AuthnRequest generation post-processing, you can do the following:
658657

659658
```java
660-
// let AuthnRequestEx, SamlResponseEx, LogoutRequestEx, LogoutResponseEx be your extension classes
661659
Auth auth = new Auth(request, response);
662-
auth.setAuthnRequestFactory(AuthnRequestEx::new); // to make it build custom AuthnRequests
663-
auth.setSamlResponseFactory(SamlResponseEx::new); // to make it build custom SamlResponses
664-
auth.setOutgoingLogoutRequestFactory(LogoutRequestEx::new); // to make it build custom outgoing LogoutRequests
665-
auth.setReceivedLogoutRequestFactory(LogoutRequestEx::new); // to make it build custom incoming LogoutRequests
666-
auth.setOutgoingLogoutResponseFactory(LogoutResponseEx::new); // to make it build custom outgoing LogoutResponses
667-
auth.setReceivedLogoutResponseFactory(LogoutResponseEx::new); // to make it build custom incoming LogoutResponses
668-
// then proceed with login/processResponse/logout/processSLO...
660+
auth.setSamlMessageFactory(new SamlMessageFactory() {
661+
@Override
662+
public AuthnRequest createAuthnRequest(Saml2Settings settings, AuthnRequestParams params) {
663+
return new AuthnRequestEx(settings, (AuthnRequestParamsEx) params);
664+
}
665+
666+
@Override
667+
public SamlResponse createSamlResponse(Saml2Settings settings, HttpRequest request) throws Exception {
668+
return new SamlResponseEx(settings, request);
669+
}
670+
});
671+
// then proceed with login...
672+
auth.login(relayState, new AuthnRequestParamsEx()); // the custom generation of AuthnReqeustEx will be executed
673+
// ... or process the response as usual
674+
auth.processResponse(); // the custom validation of SamlResponseEx will be executed
669675
```
670676

671677
### Working behind load balancer

toolkit/src/main/java/com/onelogin/saml2/Auth.java

+19-118
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@
2626
import com.onelogin.saml2.authn.AuthnRequestParams;
2727
import com.onelogin.saml2.authn.SamlResponse;
2828
import com.onelogin.saml2.exception.SettingsException;
29-
import com.onelogin.saml2.factory.SamlOutgoingMessageFactory;
30-
import com.onelogin.saml2.factory.SamlReceivedMessageFactory;
29+
import com.onelogin.saml2.factory.SamlMessageFactory;
3130
import com.onelogin.saml2.exception.Error;
3231
import com.onelogin.saml2.http.HttpRequest;
3332
import com.onelogin.saml2.logout.LogoutRequest;
@@ -171,19 +170,9 @@ public class Auth {
171170
*/
172171
private String lastResponse;
173172

174-
private static final SamlOutgoingMessageFactory<AuthnRequestParams, AuthnRequest> DEFAULT_AUTHN_REQUEST_FACTORY = AuthnRequest::new;
175-
private static final SamlReceivedMessageFactory<SamlResponse> DEFAULT_SAML_RESPONSE_FACTORY = SamlResponse::new;
176-
private static final SamlOutgoingMessageFactory<LogoutRequestParams, LogoutRequest> DEFAULT_OUTGOING_LOGOUT_REQUEST_FACTORY = LogoutRequest::new;
177-
private static final SamlReceivedMessageFactory<LogoutRequest> DEFAULT_RECEIVED_LOGOUT_REQUEST_FACTORY = LogoutRequest::new;
178-
private static final SamlOutgoingMessageFactory<LogoutResponseParams, LogoutResponse> DEFAULT_OUTGOING_LOGOUT_RESPONSE_FACTORY = LogoutResponse::new;
179-
private static final SamlReceivedMessageFactory<LogoutResponse> DEFAULT_RECEIVED_LOGOUT_RESPONSE_FACTORY = LogoutResponse::new;
173+
private static final SamlMessageFactory DEFAULT_SAML_MESSAGE_FACTORY = new SamlMessageFactory() {};
180174

181-
private SamlOutgoingMessageFactory<AuthnRequestParams, AuthnRequest> authnRequestFactory = DEFAULT_AUTHN_REQUEST_FACTORY;
182-
private SamlReceivedMessageFactory<SamlResponse> samlResponseFactory = DEFAULT_SAML_RESPONSE_FACTORY;
183-
private SamlOutgoingMessageFactory<LogoutRequestParams, LogoutRequest> outgoingLogoutRequestFactory = DEFAULT_OUTGOING_LOGOUT_REQUEST_FACTORY;
184-
private SamlReceivedMessageFactory<LogoutRequest> receivedLogoutRequestFactory = DEFAULT_RECEIVED_LOGOUT_REQUEST_FACTORY;
185-
private SamlOutgoingMessageFactory<LogoutResponseParams, LogoutResponse> outgoingLogoutResponseFactory = DEFAULT_OUTGOING_LOGOUT_RESPONSE_FACTORY;
186-
private SamlReceivedMessageFactory<LogoutResponse> receivedLogoutResponseFactory = DEFAULT_RECEIVED_LOGOUT_RESPONSE_FACTORY;
175+
private SamlMessageFactory samlMessageFactory = DEFAULT_SAML_MESSAGE_FACTORY;
187176

188177
/**
189178
* Initializes the SP SAML instance.
@@ -626,7 +615,7 @@ public String login(String relayState, AuthnRequestParams authnRequestParams, Bo
626615
* @throws SettingsException
627616
*/
628617
public String login(String relayState, AuthnRequestParams authnRequestParams, Boolean stay, Map<String, String> parameters) throws IOException, SettingsException {
629-
AuthnRequest authnRequest = authnRequestFactory.create(settings, authnRequestParams);
618+
AuthnRequest authnRequest = samlMessageFactory.createAuthnRequest(settings, authnRequestParams);
630619

631620
if (parameters == null) {
632621
parameters = new HashMap<String, String>();
@@ -802,7 +791,7 @@ public String logout(String relayState, LogoutRequestParams logoutRequestParams,
802791
parameters = new HashMap<String, String>();
803792
}
804793

805-
LogoutRequest logoutRequest = outgoingLogoutRequestFactory.create(settings, logoutRequestParams);
794+
LogoutRequest logoutRequest = samlMessageFactory.createOutgoingLogoutRequest(settings, logoutRequestParams);
806795
String samlLogoutRequest = logoutRequest.getEncodedLogoutRequest();
807796
parameters.put("SAMLRequest", samlLogoutRequest);
808797

@@ -1213,7 +1202,7 @@ public void processResponse(String requestId) throws Exception {
12131202
final String samlResponseParameter = httpRequest.getParameter("SAMLResponse");
12141203

12151204
if (samlResponseParameter != null) {
1216-
SamlResponse samlResponse = samlResponseFactory.create(settings, httpRequest);
1205+
SamlResponse samlResponse = samlMessageFactory.createSamlResponse(settings, httpRequest);
12171206
lastResponse = samlResponse.getSAMLResponseXml();
12181207

12191208
if (samlResponse.isValid(requestId)) {
@@ -1286,7 +1275,7 @@ public String processSLO(Boolean keepLocalSession, String requestId, Boolean sta
12861275
final String samlResponseParameter = httpRequest.getParameter("SAMLResponse");
12871276

12881277
if (samlResponseParameter != null) {
1289-
LogoutResponse logoutResponse = receivedLogoutResponseFactory.create(settings, httpRequest);
1278+
LogoutResponse logoutResponse = samlMessageFactory.createIncomingLogoutResponse(settings, httpRequest);
12901279
lastResponse = logoutResponse.getLogoutResponseXml();
12911280
if (!logoutResponse.isValid(requestId)) {
12921281
errors.add("invalid_logout_response");
@@ -1316,7 +1305,7 @@ public String processSLO(Boolean keepLocalSession, String requestId, Boolean sta
13161305
}
13171306
return null;
13181307
} else if (samlRequestParameter != null) {
1319-
LogoutRequest logoutRequest = receivedLogoutRequestFactory.create(settings, httpRequest);
1308+
LogoutRequest logoutRequest = samlMessageFactory.createIncomingLogoutRequest(settings, httpRequest);
13201309
lastRequest = logoutRequest.getLogoutRequestXml();
13211310
if (!logoutRequest.isValid()) {
13221311
errors.add("invalid_logout_request");
@@ -1334,7 +1323,7 @@ public String processSLO(Boolean keepLocalSession, String requestId, Boolean sta
13341323
}
13351324

13361325
String inResponseTo = logoutRequest.id;
1337-
LogoutResponse logoutResponseBuilder = outgoingLogoutResponseFactory.create(settings,
1326+
LogoutResponse logoutResponseBuilder = samlMessageFactory.createOutgoingLogoutResponse(settings,
13381327
new LogoutResponseParams(inResponseTo, Constants.STATUS_SUCCESS));
13391328
lastResponse = logoutResponseBuilder.getLogoutResponseXml();
13401329

@@ -1663,107 +1652,19 @@ public String getLastResponseXML() {
16631652
}
16641653

16651654
/**
1666-
* Sets the factory this {@link Auth} will use to create {@link AuthnRequest}
1667-
* objects.
1655+
* Sets the factory this {@link Auth} will use to create SAML messages.
16681656
* <p>
1669-
* This allows consumers to provide their own extension of {@link AuthnRequest}
1670-
* possibly implementing custom features and/or XML post-processing.
1657+
* This allows consumers to provide their own extension classes for SAML message
1658+
* XML generation and/or processing.
16711659
*
1672-
* @param authnRequestFactory
1673-
* the factory to use to create {@link AuthnRequest} objects; if
1660+
* @param samlMessageFactory
1661+
* the factory to use to create SAML message objects; if
16741662
* <code>null</code>, a default provider will be used which creates
1675-
* plain {@link AuthnRequest} instances
1663+
* the standard message implementation provided by this library
1664+
* (i.e.: {@link AuthnRequest}, {@link SamlResponse},
1665+
* {@link LogoutRequest} and {@link LogoutResponse})
16761666
*/
1677-
public void setAuthnRequestFactory(
1678-
final SamlOutgoingMessageFactory<AuthnRequestParams, AuthnRequest> authnRequestFactory) {
1679-
this.authnRequestFactory = authnRequestFactory != null ? authnRequestFactory
1680-
: DEFAULT_AUTHN_REQUEST_FACTORY;
1681-
}
1682-
1683-
/**
1684-
* Sets the factory this {@link Auth} will use to create {@link SamlResponse}
1685-
* objects.
1686-
* <p>
1687-
* This allows consumers to provide their own extension of {@link SamlResponse}
1688-
* possibly implementing custom features and/or XML validation.
1689-
*
1690-
* @param samlResponseFactory
1691-
* the factory to use to create {@link SamlResponse} objects; if
1692-
* <code>null</code>, a default factory will be used which creates
1693-
* plain {@link SamlResponse} instances
1694-
*/
1695-
public void setSamlResponseFactory(final SamlReceivedMessageFactory<SamlResponse> samlResponseFactory) {
1696-
this.samlResponseFactory = samlResponseFactory != null? samlResponseFactory: DEFAULT_SAML_RESPONSE_FACTORY;
1697-
}
1698-
1699-
/**
1700-
* Sets the factory this {@link Auth} will use to create outgoing
1701-
* {@link LogoutRequest} objects.
1702-
* <p>
1703-
* This allows consumers to provide their own extension of {@link LogoutRequest}
1704-
* possibly implementing custom features and/or XML post-processing.
1705-
*
1706-
* @param outgoingLogoutRequestFactory
1707-
* the factory to use to create outgoing {@link LogoutRequest}
1708-
* objects; if <code>null</code>, a default provider will be used
1709-
* which creates plain {@link LogoutRequest} instances
1710-
*/
1711-
public void setOutgoingLogoutRequestFactory(final
1712-
SamlOutgoingMessageFactory<LogoutRequestParams, LogoutRequest> outgoingLogoutRequestFactory) {
1713-
this.outgoingLogoutRequestFactory = outgoingLogoutRequestFactory != null? outgoingLogoutRequestFactory: DEFAULT_OUTGOING_LOGOUT_REQUEST_FACTORY;
1714-
}
1715-
1716-
/**
1717-
* Sets the factory this {@link Auth} will use to create received
1718-
* {@link LogoutRequest} objects.
1719-
* <p>
1720-
* This allows consumers to provide their own extension of {@link LogoutRequest}
1721-
* possibly implementing custom features and/or XML validation.
1722-
*
1723-
* @param receivedLogoutRequestFactory
1724-
* the factory to use to create received {@link LogoutRequest}
1725-
* objects; if <code>null</code>, a default provider will be used
1726-
* which creates plain {@link LogoutRequest} instances
1727-
*/
1728-
public void setReceivedLogoutRequestFactory(
1729-
final SamlReceivedMessageFactory<LogoutRequest> receivedLogoutRequestFactory) {
1730-
this.receivedLogoutRequestFactory = receivedLogoutRequestFactory != null ? receivedLogoutRequestFactory
1731-
: DEFAULT_RECEIVED_LOGOUT_REQUEST_FACTORY;
1732-
}
1733-
1734-
/**
1735-
* Sets the factory this {@link Auth} will use to create outgoing
1736-
* {@link LogoutResponse} objects.
1737-
* <p>
1738-
* This allows consumers to provide their own extension of
1739-
* {@link LogoutResponse} possibly implementing custom features and/or XML
1740-
* post-processing.
1741-
*
1742-
* @param outgoingLogoutResponseFactory
1743-
* the factory to use to create outgoing {@link LogoutResponse}
1744-
* objects; if <code>null</code>, a default provider will be used
1745-
* which creates plain {@link LogoutResponse} instances
1746-
*/
1747-
public void setOutgoingLogoutResponseFactory(final
1748-
SamlOutgoingMessageFactory<LogoutResponseParams, LogoutResponse> outgoingLogoutResponseFactory) {
1749-
this.outgoingLogoutResponseFactory = outgoingLogoutResponseFactory != null? outgoingLogoutResponseFactory: DEFAULT_OUTGOING_LOGOUT_RESPONSE_FACTORY;
1750-
}
1751-
1752-
/**
1753-
* Sets the factory this {@link Auth} will use to create received
1754-
* {@link LogoutResponse} objects.
1755-
* <p>
1756-
* This allows consumers to provide their own extension of
1757-
* {@link LogoutResponse} possibly implementing custom features and/or XML
1758-
* validation.
1759-
*
1760-
* @param receivedLogoutResponseFactory
1761-
* the factory to use to create received {@link LogoutResponse}
1762-
* objects; if <code>null</code>, a default provider will be used
1763-
* which creates plain {@link LogoutResponse} instances
1764-
*/
1765-
public void setReceivedLogoutResponseFactory(final
1766-
SamlReceivedMessageFactory<LogoutResponse> receivedLogoutResponseFactory) {
1767-
this.receivedLogoutResponseFactory = receivedLogoutResponseFactory != null? receivedLogoutResponseFactory: DEFAULT_RECEIVED_LOGOUT_RESPONSE_FACTORY;
1667+
public void setSamlMessageFactory(final SamlMessageFactory samlMessageFactory) {
1668+
this.samlMessageFactory = samlMessageFactory != null ? samlMessageFactory : DEFAULT_SAML_MESSAGE_FACTORY;
17681669
}
17691670
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package com.onelogin.saml2.factory;
2+
3+
import com.onelogin.saml2.Auth;
4+
import com.onelogin.saml2.authn.AuthnRequest;
5+
import com.onelogin.saml2.authn.AuthnRequestParams;
6+
import com.onelogin.saml2.authn.SamlResponse;
7+
import com.onelogin.saml2.http.HttpRequest;
8+
import com.onelogin.saml2.logout.LogoutRequest;
9+
import com.onelogin.saml2.logout.LogoutRequestParams;
10+
import com.onelogin.saml2.logout.LogoutResponse;
11+
import com.onelogin.saml2.logout.LogoutResponseParams;
12+
import com.onelogin.saml2.settings.Saml2Settings;
13+
14+
/**
15+
* Factory which can create all kind of SAML message objects.
16+
* <p>
17+
* One such factory is used by the {@link Auth} class to orchestrate login and
18+
* logout operations.
19+
* <p>
20+
* Default implementations for all creation methods are provided: they create
21+
* instances of the standard classes provided by the library. Any extension
22+
* class may simply override the desired creation methods in order to return
23+
* instances of custom extensions of those standard classes.
24+
*/
25+
public interface SamlMessageFactory {
26+
27+
/**
28+
* Creates an {@link AuthnRequest} instance.
29+
*
30+
* @param settings
31+
* the settings
32+
* @param params
33+
* the authentication request input parameters
34+
* @return the created {@link AuthnRequest} instance
35+
*/
36+
default AuthnRequest createAuthnRequest(final Saml2Settings settings, final AuthnRequestParams params) {
37+
return new AuthnRequest(settings, params);
38+
}
39+
40+
/**
41+
* Creates a {@link SamlResponse} instance.
42+
*
43+
* @param settings
44+
* the settings
45+
* @param request
46+
* the HTTP request from which the response is to be extracted and
47+
* parsed
48+
* @return the created {@link SamlResponse} instance
49+
* @throws Exception
50+
* in case some error occurred while trying to create the
51+
* {@link SamlResponse} instance
52+
*/
53+
default SamlResponse createSamlResponse(final Saml2Settings settings, final HttpRequest request)
54+
throws Exception {
55+
return new SamlResponse(settings, request);
56+
}
57+
58+
/**
59+
* Creates a {@link LogoutRequest} instance for an outgoing request.
60+
*
61+
* @param settings
62+
* the settings
63+
* @param params
64+
* the logout request input parameters
65+
* @return the created {@link LogoutRequest} instance
66+
*/
67+
default LogoutRequest createOutgoingLogoutRequest(final Saml2Settings settings, final LogoutRequestParams params) {
68+
return new LogoutRequest(settings, params);
69+
}
70+
71+
/**
72+
* Creates a {@link LogoutRequest} instance for an incoming request.
73+
*
74+
* @param settings
75+
* the settings
76+
* @param request
77+
* the HTTP request from which the logout request is to be
78+
* extracted and parsed
79+
* @return the created {@link LogoutRequest} instance
80+
* @throws Exception
81+
* in case some error occurred while trying to create the
82+
* {@link LogoutRequest} instance
83+
*/
84+
default LogoutRequest createIncomingLogoutRequest(final Saml2Settings settings, final HttpRequest request)
85+
throws Exception {
86+
return new LogoutRequest(settings, request);
87+
}
88+
89+
/**
90+
* Creates a {@link LogoutResponse} instance for an outgoing response.
91+
*
92+
* @param settings
93+
* the settings
94+
* @param params
95+
* the logout response input parameters
96+
* @return the created {@link LogoutResponse} instance
97+
*/
98+
default LogoutResponse createOutgoingLogoutResponse(final Saml2Settings settings, final LogoutResponseParams params) {
99+
return new LogoutResponse(settings, params);
100+
}
101+
102+
/**
103+
* Creates a {@link LogoutRequest} instance for an incoming response.
104+
*
105+
* @param settings
106+
* the settings
107+
* @param request
108+
* the HTTP request from which the logout response is to be
109+
* extracted and parsed
110+
* @return the created {@link LogoutResponse} instance
111+
* @throws Exception
112+
* in case some error occurred while trying to create the
113+
* {@link LogoutResponse} instance
114+
*/
115+
default LogoutResponse createIncomingLogoutResponse(final Saml2Settings settings, final HttpRequest request)
116+
throws Exception {
117+
return new LogoutResponse(settings, request);
118+
}
119+
}

toolkit/src/main/java/com/onelogin/saml2/factory/SamlOutgoingMessageFactory.java

-27
This file was deleted.

0 commit comments

Comments
 (0)