Skip to content

Commit a94cb28

Browse files
committed
#86. Let login and logout methods to not execute redirections
1 parent 8e95972 commit a94cb28

4 files changed

Lines changed: 172 additions & 10 deletions

File tree

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

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,13 @@ public void setStrict(Boolean value)
221221
* When true the AuthNRequest will set the IsPassive='true'
222222
* @param setNameIdPolicy
223223
* When true the AuthNRequest will set a nameIdPolicy
224-
* @returns the representation of the AuthNRequest generated
224+
* @param stay
225+
* True if we want to stay (returns the url string) False to execute redirection
226+
*
227+
* @return the SSO URL with the AuthNRequest if stay = True
225228
* @throws IOException
226229
*/
227-
public void login(String returnTo, Boolean forceAuthn, Boolean isPassive, Boolean setNameIdPolicy) throws IOException {
230+
public String login(String returnTo, Boolean forceAuthn, Boolean isPassive, Boolean setNameIdPolicy, Boolean stay) throws IOException {
228231
Map<String, String> parameters = new HashMap<String, String>();
229232

230233
AuthnRequest authnRequest = new AuthnRequest(settings, forceAuthn, isPassive, setNameIdPolicy);
@@ -253,11 +256,32 @@ public void login(String returnTo, Boolean forceAuthn, Boolean isPassive, Boolea
253256

254257
String ssoUrl = getSSOurl();
255258

256-
LOGGER.debug("AuthNRequest sent to " + ssoUrl + " --> " + samlRequest);
257-
ServletUtils.sendRedirect(response, ssoUrl, parameters);
258259
lastRequestId = authnRequest.getId();
260+
261+
if (!stay) {
262+
LOGGER.debug("AuthNRequest sent to " + ssoUrl + " --> " + samlRequest);
263+
}
264+
return ServletUtils.sendRedirect(response, ssoUrl, parameters, stay);
259265
}
260266

267+
/**
268+
* Initiates the SSO process.
269+
*
270+
* @param returnTo
271+
* The target URL the user should be returned to after login (relayState).
272+
* Will be a self-routed URL when null, or not be appended at all when an empty string is provided
273+
* @param forceAuthn
274+
* When true the AuthNRequest will set the ForceAuthn='true'
275+
* @param isPassive
276+
* When true the AuthNRequest will set the IsPassive='true'
277+
* @param setNameIdPolicy
278+
* When true the AuthNRequest will set a nameIdPolicy
279+
* @throws IOException
280+
*/
281+
public void login(String returnTo, Boolean forceAuthn, Boolean isPassive, Boolean setNameIdPolicy) throws IOException {
282+
login(returnTo ,forceAuthn, isPassive, setNameIdPolicy, false);
283+
}
284+
261285
/**
262286
* Initiates the SSO process.
263287
*
@@ -290,11 +314,15 @@ public void login(String returnTo) throws IOException {
290314
* The NameID that will be set in the LogoutRequest.
291315
* @param sessionIndex
292316
* The SessionIndex (taken from the SAML Response in the SSO process).
317+
* @param stay
318+
* True if we want to stay (returns the url string) False to execute redirection
319+
*
320+
* @return the SLO URL with the LogoutRequest if stay = True
293321
*
294322
* @throws IOException
295323
* @throws XMLEntityException
296324
*/
297-
public void logout(String returnTo, String nameId, String sessionIndex) throws IOException, XMLEntityException {
325+
public String logout(String returnTo, String nameId, String sessionIndex, Boolean stay) throws IOException, XMLEntityException {
298326
Map<String, String> parameters = new HashMap<String, String>();
299327

300328
LogoutRequest logoutRequest = new LogoutRequest(settings, null, nameId, sessionIndex);
@@ -321,9 +349,30 @@ public void logout(String returnTo, String nameId, String sessionIndex) throws I
321349
}
322350

323351
String sloUrl = getSLOurl();
324-
LOGGER.debug("Logout request sent to " + sloUrl + " --> " + samlLogoutRequest);
325-
ServletUtils.sendRedirect(response, sloUrl, parameters);
326352
lastRequestId = logoutRequest.getId();
353+
354+
if (!stay) {
355+
LOGGER.debug("Logout request sent to " + sloUrl + " --> " + samlLogoutRequest);
356+
}
357+
return ServletUtils.sendRedirect(response, sloUrl, parameters, stay);
358+
}
359+
360+
/**
361+
* Initiates the SLO process.
362+
*
363+
* @param returnTo
364+
* The target URL the user should be returned to after logout (relayState).
365+
* Will be a self-routed URL when null, or not be appended at all when an empty string is provided
366+
* @param nameId
367+
* The NameID that will be set in the LogoutRequest.
368+
* @param sessionIndex
369+
* The SessionIndex (taken from the SAML Response in the SSO process).
370+
*
371+
* @throws IOException
372+
* @throws XMLEntityException
373+
*/
374+
public void logout(String returnTo, String nameId, String sessionIndex) throws IOException, XMLEntityException {
375+
logout(returnTo, nameId, sessionIndex, false);
327376
}
328377

329378
/**

toolkit/src/main/java/com/onelogin/saml2/servlet/ServletUtils.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,15 @@ public static String getSelfRoutedURLNoQuery(HttpServletRequest request) {
136136
* target location url
137137
* @param parameters
138138
* GET parameters to be added
139-
*
139+
* @param stay
140+
* True if we want to stay (returns the url string) False to execute redirection
141+
*
142+
* @return string the target URL
140143
* @throws IOException
141144
*
142145
* @see javax.servlet.http.HttpServletResponse#sendRedirect(String)
143146
*/
144-
public static void sendRedirect(HttpServletResponse response, String location, Map<String, String> parameters) throws IOException {
147+
public static String sendRedirect(HttpServletResponse response, String location, Map<String, String> parameters, Boolean stay) throws IOException {
145148
String target = location;
146149

147150
if (!parameters.isEmpty()) {
@@ -160,9 +163,33 @@ public static void sendRedirect(HttpServletResponse response, String location, M
160163
}
161164
}
162165
}
163-
response.sendRedirect(target);
166+
if (!stay) {
167+
response.sendRedirect(target);
168+
}
169+
170+
return target;
164171
}
165172

173+
/**
174+
* Redirect to location url
175+
*
176+
* @param response
177+
* HttpServletResponse object to be used
178+
* @param location
179+
* target location url
180+
* @param parameters
181+
* GET parameters to be added
182+
* @param stay
183+
* True if we want to stay (returns the url string) False to execute redirection
184+
*
185+
* @throws IOException
186+
*
187+
* @see javax.servlet.http.HttpServletResponse#sendRedirect(String)
188+
*/
189+
public static void sendRedirect(HttpServletResponse response, String location, Map<String, String> parameters) throws IOException {
190+
sendRedirect(response, location, parameters, false);
191+
}
192+
166193
/**
167194
* Redirect to location url
168195
*

toolkit/src/test/java/com/onelogin/saml2/test/AuthTest.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,39 @@ public void testLoginWithoutRelayState() throws IOException, SettingsException,
995995
assertThat(urlCaptor.getValue(), not(containsString("&RelayState=")));
996996
}
997997

998+
/**
999+
* Tests the login method of Auth
1000+
* Case: Login with stay enabled
1001+
*
1002+
* @throws SettingsException
1003+
* @throws IOException
1004+
* @throws URISyntaxException
1005+
*
1006+
* @see com.onelogin.saml2.Auth#login
1007+
*/
1008+
@Test
1009+
public void testLoginStay() throws IOException, SettingsException, URISyntaxException {
1010+
HttpServletRequest request = mock(HttpServletRequest.class);
1011+
HttpServletResponse response = mock(HttpServletResponse.class);
1012+
when(request.getScheme()).thenReturn("http");
1013+
when(request.getServerPort()).thenReturn(8080);
1014+
when(request.getServerName()).thenReturn("localhost");
1015+
when(request.getRequestURI()).thenReturn("/initial.jsp");
1016+
1017+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
1018+
settings.setAuthnRequestsSigned(false);
1019+
1020+
Auth auth = new Auth(settings, request, response);
1021+
String target = auth.login("", false, false, false, true);
1022+
assertThat(target, startsWith("https://pitbulk.no-ip.org/simplesaml/saml2/idp/SSOService.php?SAMLRequest="));
1023+
assertThat(target, not(containsString("&RelayState=")));
1024+
1025+
String relayState = "http://localhost:8080/expected.jsp";
1026+
target = auth.login(relayState, false, false, false, true);
1027+
assertThat(target, startsWith("https://pitbulk.no-ip.org/simplesaml/saml2/idp/SSOService.php?SAMLRequest="));
1028+
assertThat(target, containsString("&RelayState=http%3A%2F%2Flocalhost%3A8080%2Fexpected.jsp"));
1029+
}
1030+
9981031
/**
9991032
* Tests the login method of Auth
10001033
* Case: Signed Login but no sp key
@@ -1143,6 +1176,39 @@ public void testLogoutWithoutRelayState() throws IOException, SettingsException,
11431176
assertThat(urlCaptor.getValue(), not(containsString("&RelayState=")));
11441177
}
11451178

1179+
/**
1180+
* Tests the logout method of Auth
1181+
* Case: Logout Stay
1182+
*
1183+
* @throws IOException
1184+
* @throws SettingsException
1185+
* @throws XMLEntityException
1186+
*
1187+
* @see com.onelogin.saml2.Auth#logout
1188+
*/
1189+
@Test
1190+
public void testLogoutStay() throws IOException, SettingsException, XMLEntityException {
1191+
HttpServletRequest request = mock(HttpServletRequest.class);
1192+
HttpServletResponse response = mock(HttpServletResponse.class);
1193+
when(request.getScheme()).thenReturn("http");
1194+
when(request.getServerPort()).thenReturn(8080);
1195+
when(request.getServerName()).thenReturn("localhost");
1196+
when(request.getRequestURI()).thenReturn("/initial.jsp");
1197+
1198+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
1199+
settings.setLogoutRequestSigned(false);
1200+
1201+
Auth auth = new Auth(settings, request, response);
1202+
String target = auth.logout("", null, null, true);
1203+
assertThat(target, startsWith("https://pitbulk.no-ip.org/simplesaml/saml2/idp/SingleLogoutService.php?SAMLRequest="));
1204+
assertThat(target, not(containsString("&RelayState=")));
1205+
1206+
String relayState = "http://localhost:8080/expected.jsp";
1207+
target = auth.logout(relayState, null, null, true);
1208+
assertThat(target, startsWith("https://pitbulk.no-ip.org/simplesaml/saml2/idp/SingleLogoutService.php?SAMLRequest="));
1209+
assertThat(target, containsString("&RelayState=http%3A%2F%2Flocalhost%3A8080%2Fexpected.jsp"));
1210+
}
1211+
11461212
/**
11471213
* Tests the logout method of Auth
11481214
* Case: Signed Logout but no sp key

toolkit/src/test/java/com/onelogin/saml2/test/servlet/ServletUtilsTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,26 @@ public void testSendRedirectParams() throws IOException {
117117
verify(response_5).sendRedirect("http://example.com/expectedurl.jsp?novalue");
118118
}
119119

120+
/**
121+
* Tests the sendRedirect method
122+
* Use Case: Stay and don't execute redirection
123+
*
124+
* @throws IOException
125+
*
126+
* @see ServletUtils#sendRedirect
127+
*/
128+
@Test
129+
public void testSendRedirectStay() throws IOException {
130+
HttpServletResponse response = mock(HttpServletResponse.class);
131+
Map<String, String> parameters = new HashMap<String, String>();
132+
133+
String url = ServletUtils.sendRedirect(response, "http://example.com/expectedurl.jsp", parameters, true);
134+
assertEquals("http://example.com/expectedurl.jsp", url);
135+
136+
url = ServletUtils.sendRedirect(response, "http://example.com/expectedurl.jsp?idpid=ffee-aabbb", singletonMap("SAMLRequest", "data"), true);
137+
assertEquals("http://example.com/expectedurl.jsp?idpid=ffee-aabbb&SAMLRequest=data", url);
138+
}
139+
120140
/**
121141
* Tests the getSelfURLhost method
122142
*

0 commit comments

Comments
 (0)