Skip to content

Commit 64dba94

Browse files
committed
#60: allow retrieving the generated request ids
- Auth now has getLastLoginRequestId/getLastLogoutRequestId methods that allow retrieving the id of the generated AuthnRequest/LogoutRequest message to be used in response validation
1 parent 525ba97 commit 64dba94

8 files changed

Lines changed: 84 additions & 21 deletions

File tree

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

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
* Defines the methods that you can invoke in your application in
3838
* order to add SAML support (initiates sso, initiates slo, processes a
3939
* SAML Response, a Logout Request or a Logout Response).
40+
*
41+
* This is stateful and not thread-safe, you should create a new instance for each request/response.
4042
*/
4143
public class Auth {
4244
/**
@@ -94,6 +96,16 @@ public class Auth {
9496
*/
9597
private String errorReason;
9698

99+
/**
100+
* The id of the last AuthnRequest generated
101+
*/
102+
private String lastLoginRequestId;
103+
104+
/**
105+
* The id of the last LogoutRequest generated
106+
*/
107+
private String lastLogoutRequestId;
108+
97109
/**
98110
* Initializes the SP SAML instance.
99111
*
@@ -191,14 +203,15 @@ public void setStrict(Boolean value)
191203
/**
192204
* Initiates the SSO process.
193205
*
194-
* @param returnTo
195-
* The target URL the user should be returned to after login.
196-
* @param forceAuthn
197-
* When true the AuthNReuqest will set the ForceAuthn='true'
198-
* @param isPassive
199-
* When true the AuthNReuqest will set the IsPassive='true'
206+
* @param returnTo
207+
* The target URL the user should be returned to after login.
208+
* @param forceAuthn
209+
* When true the AuthNRequest will set the ForceAuthn='true'
210+
* @param isPassive
211+
* When true the AuthNRequest will set the IsPassive='true'
200212
* @param setNameIdPolicy
201-
* When true the AuthNReuqest will set a nameIdPolicy
213+
* When true the AuthNRequest will set a nameIdPolicy
214+
* @return the representation of the AuthNRequest generated
202215
* @throws IOException
203216
*/
204217
public void login(String returnTo, Boolean forceAuthn, Boolean isPassive, Boolean setNameIdPolicy) throws IOException {
@@ -229,6 +242,7 @@ public void login(String returnTo, Boolean forceAuthn, Boolean isPassive, Boolea
229242

230243
LOGGER.debug("AuthNRequest sent to " + ssoUrl + " --> " + samlRequest);
231244
Util.sendRedirect(response, ssoUrl, parameters);
245+
lastLoginRequestId = authnRequest.getId();
232246
}
233247

234248
/**
@@ -292,6 +306,7 @@ public void logout(String returnTo, String nameId, String sessionIndex) throws I
292306
String sloUrl = getSLOurl();
293307
LOGGER.debug("Logout request sent to " + sloUrl + " --> " + samlLogoutRequest);
294308
Util.sendRedirect(response, sloUrl, parameters);
309+
lastLogoutRequestId = logoutRequest.getId();
295310
}
296311

297312
/**
@@ -538,7 +553,23 @@ public String getLastErrorReason()
538553
{
539554
return errorReason;
540555
}
541-
556+
557+
/**
558+
* @return the id of the last AuthnRequest generated, null if none
559+
*/
560+
public String getLastLoginRequestId()
561+
{
562+
return lastLoginRequestId;
563+
}
564+
565+
/**
566+
* @return the id of the last LogoutRequest generated, null if none
567+
*/
568+
public String getLastLogoutRequestId()
569+
{
570+
return lastLogoutRequestId;
571+
}
572+
542573
/**
543574
* @return the Saml2Settings object. The Settings data.
544575
*/

core/src/main/java/com/onelogin/saml2/authn/AuthnRequest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,12 @@ private static StringBuilder getAuthnRequestTemplate() {
186186
template.append("${nameIDPolicyStr}${requestedAuthnContextStr}</samlp:AuthnRequest>");
187187
return template;
188188
}
189+
190+
/**
191+
* @return the generated id of the AuthnRequest message
192+
*/
193+
public String getId()
194+
{
195+
return id;
196+
}
189197
}

core/src/main/java/com/onelogin/saml2/logout/LogoutRequest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,4 +599,12 @@ public static List<String> getSessionIndexes(String samlLogoutRequestString) thr
599599
public String getError() {
600600
return error;
601601
}
602+
603+
/**
604+
* @return the generated id of the LogoutRequest message
605+
*/
606+
public String getId()
607+
{
608+
return id;
609+
}
602610
}

core/src/main/java/com/onelogin/saml2/util/Util.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public final class Util {
103103

104104
private static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'").withZone(DateTimeZone.UTC);
105105
private static final DateTimeFormatter DATE_TIME_FORMAT_MILLS = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(DateTimeZone.UTC);
106+
public static final String UNIQUE_ID_PREFIX = "ONELOGIN_";
106107

107108
/**
108109
* This function load an XML string in a save way. Prevent XEE/XXE Attacks
@@ -1344,9 +1345,6 @@ private static SecretKey generateSymmetricKey() throws Exception {
13441345
* @return A unique string
13451346
*/
13461347
public static String generateUniqueID() {
1347-
String uniqueIdSha1 = StringUtils.EMPTY;
1348-
String uniqueId = StringUtils.EMPTY;
1349-
13501348
try {
13511349
Random r = new Random();
13521350
Integer n = r.nextInt();
@@ -1356,14 +1354,13 @@ public static String generateUniqueID() {
13561354
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
13571355
crypt.reset();
13581356
crypt.update(id.getBytes());
1359-
uniqueIdSha1 = new BigInteger(1, crypt.digest()).toString(16);
1357+
final String uniqueIdSha1 = new BigInteger(1, crypt.digest()).toString(16);
13601358

1361-
uniqueId = "ONELOGIN_" + uniqueIdSha1;
1359+
return UNIQUE_ID_PREFIX + uniqueIdSha1;
13621360
} catch (Exception e) {
1363-
LOGGER.error("Error executing generateUniqueID: " + e.getMessage(), e);
1361+
throw new RuntimeException("Error executing generateUniqueID: " + e.getMessage(), e);
13641362
}
1365-
return uniqueId;
1366-
}
1363+
}
13671364

13681365
/**
13691366
* Generates random UUID

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package com.onelogin.saml2.test;
22

33

4+
import static com.onelogin.saml2.util.Util.UNIQUE_ID_PREFIX;
45
import static org.hamcrest.CoreMatchers.is;
56
import static org.hamcrest.CoreMatchers.containsString;
67
import static org.hamcrest.CoreMatchers.not;
8+
import static org.hamcrest.CoreMatchers.startsWith;
79
import static org.junit.Assert.assertEquals;
810
import static org.junit.Assert.assertFalse;
911
import static org.junit.Assert.assertNotEquals;
@@ -91,6 +93,8 @@ public void testConstructor() throws IOException, SettingsException {
9193
Saml2Settings settings = new SettingsBuilder().fromFile("onelogin.saml.properties").build();
9294
assertEquals(settings.getIdpEntityId(), auth.getSettings().getIdpEntityId());
9395
assertEquals(settings.getSpEntityId(), auth.getSettings().getSpEntityId());
96+
assertNull(auth.getLastLoginRequestId());
97+
assertNull(auth.getLastLogoutRequestId());
9498
}
9599

96100
/**
@@ -896,6 +900,7 @@ public void testLogin() throws IOException, SettingsException, URISyntaxExceptio
896900
Auth auth = new Auth(settings, request, response);
897901
auth.login();
898902
verify(response).sendRedirect(matches("https:\\/\\/pitbulk.no-ip.org\\/simplesaml\\/saml2\\/idp\\/SSOService.php\\?SAMLRequest=(.)*&RelayState=http%3A%2F%2Flocalhost%3A8080%2Finitial.jsp"));
903+
assertThat(auth.getLastLoginRequestId(), startsWith(Util.UNIQUE_ID_PREFIX));
899904
}
900905

901906
/**
@@ -1011,6 +1016,7 @@ public void testLogout() throws IOException, SettingsException, XMLEntityExcepti
10111016
auth.logout();
10121017

10131018
verify(response).sendRedirect(matches("https:\\/\\/pitbulk.no-ip.org\\/simplesaml\\/saml2\\/idp\\/SingleLogoutService.php\\?SAMLRequest=(.)*&RelayState=http%3A%2F%2Flocalhost%3A8080%2Finitial.jsp"));
1019+
assertThat(auth.getLastLogoutRequestId(), startsWith(Util.UNIQUE_ID_PREFIX));
10141020
}
10151021

10161022
/**

core/src/test/java/com/onelogin/saml2/test/authn/AuthnRequestTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,18 @@ public void testAuthNContext() throws Exception {
241241
assertThat(authnRequestStr, containsString("<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:X509</saml:AuthnContextClassRef>"));
242242
}
243243

244+
@Test
245+
public void testAuthNId() throws Exception
246+
{
247+
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
248+
249+
AuthnRequest authnRequest = new AuthnRequest(settings);
250+
final String authnRequestStr = Util.base64decodedInflated(authnRequest.getEncodedAuthnRequest());
251+
252+
assertThat(authnRequestStr, containsString("<samlp:AuthnRequest"));
253+
assertThat(authnRequestStr, containsString("ID=\"" + authnRequest.getId() + "\""));
254+
}
255+
244256
/**
245257
* Tests the AuthnRequest Constructor
246258
* The creation of a deflated SAML Request with and without Destination

core/src/test/java/com/onelogin/saml2/test/logout/LogoutRequestTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public void testConstructor() throws Exception {
8181
String logoutRequestStr = Util.base64decodedInflated(logoutRequestStringBase64);
8282

8383
assertThat(logoutRequestStr, containsString("<samlp:LogoutRequest"));
84+
assertThat(logoutRequestStr, containsString("ID=\"" + logoutRequest.getId() + "\""));
8485
assertThat(logoutRequestStr, not(containsString("<samlp:SessionIndex>")));
8586
}
8687

core/src/test/java/com/onelogin/saml2/test/util/UtilsTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,7 +1893,7 @@ public void testGenerateNameId() throws URISyntaxException, IOException, Certifi
18931893
public void testGenerateUniqueID() {
18941894
String s1 = Util.generateUniqueID();
18951895

1896-
assertThat(s1, containsString("ONELOGIN_"));
1896+
assertThat(s1, containsString(Util.UNIQUE_ID_PREFIX));
18971897
assertTrue(s1.length() > 40);
18981898

18991899
String s2 = Util.generateUniqueID();
@@ -1923,10 +1923,10 @@ public void testUniqid() {
19231923
assertNotEquals(id_2, id_3);
19241924
assertNotEquals(id_2, id_4);
19251925

1926-
String id_5 = Util.uniqid("ONELOGIN_", false);
1927-
String id_6 = Util.uniqid("ONELOGIN_", true);
1928-
assertThat(id_5, containsString("ONELOGIN_"));
1929-
assertThat(id_6, containsString("ONELOGIN_"));
1926+
String id_5 = Util.uniqid(Util.UNIQUE_ID_PREFIX, false);
1927+
String id_6 = Util.uniqid(Util.UNIQUE_ID_PREFIX, true);
1928+
assertThat(id_5, containsString(Util.UNIQUE_ID_PREFIX));
1929+
assertThat(id_6, containsString(Util.UNIQUE_ID_PREFIX));
19301930
assertNotEquals(id_5, id_6);
19311931

19321932
String id_7 = Util.uniqid("", false);

0 commit comments

Comments
 (0)