diff --git a/src/main/java/com/casinthecloud/simpletest/cas/CasDelegateTest.java b/src/main/java/com/casinthecloud/simpletest/cas/CasDelegateTest.java new file mode 100644 index 0000000..fa2afbd --- /dev/null +++ b/src/main/java/com/casinthecloud/simpletest/cas/CasDelegateTest.java @@ -0,0 +1,63 @@ +package com.casinthecloud.simpletest.cas; + +import com.casinthecloud.simpletest.execution.Context; +import lombok.Getter; +import lombok.Setter; +import lombok.val; + +import static org.apache.commons.lang3.StringUtils.substringBetween; + +/** + * A test performing a CAS authn delegation in the CAS server. + * + * @author Jerome LELEU + * @since 1.0.0 + */ +@Getter +@Setter +public class CasDelegateTest extends CasLoginTest { + + private final String clientName; + + public CasDelegateTest(final String clientName, final CasTest casTest) { + this.tests = new CasTest[] { casTest }; + this.clientName = clientName; + } + + public void run(final Context ctx) throws Exception { + + val loginUrl = callLoginPage(ctx); + + delegate(ctx, loginUrl); + + super.run(ctx); + + callbackCas(ctx); + + callbackCas(ctx); + + } + + protected void delegate(final Context ctx, final String loginUrl) throws Exception { + val webflow = substringBetween(ctx.getBody(), "name=\"execution\" value=\"", "\"/>"); + + ctx.getFormParameters().put("client_name", getClientName()); + ctx.getFormParameters().put("_eventId", "delegatedAuthenticationRedirect"); + ctx.getFormParameters().put("execution", webflow); + + ctx.setRequest(post(ctx, loginUrl)); + execute(ctx); + + saveCasSession(ctx); + } + + protected void callbackCas(final Context ctx) throws Exception { + val callbackUrl = getLocation(ctx); + + useCasSession(ctx); + + ctx.setRequest(get(ctx, callbackUrl)); + execute(ctx); + assertStatus(ctx, 302); + } +} diff --git a/src/main/java/com/casinthecloud/simpletest/cas/CasLoginTest.java b/src/main/java/com/casinthecloud/simpletest/cas/CasLoginTest.java index d429eae..a86051e 100644 --- a/src/main/java/com/casinthecloud/simpletest/cas/CasLoginTest.java +++ b/src/main/java/com/casinthecloud/simpletest/cas/CasLoginTest.java @@ -4,7 +4,6 @@ import lombok.Getter; import lombok.Setter; import lombok.val; -import org.apache.commons.lang3.tuple.Pair; import static com.casinthecloud.simpletest.util.Utils.addUrlParameter; import static org.apache.commons.lang3.StringUtils.isBlank; @@ -22,17 +21,7 @@ public class CasLoginTest extends CasTest { public void run(final Context ctx) throws Exception { - var loginUrl = getLocation(ctx); - if (isBlank(loginUrl)) { - loginUrl = addUrlParameter(getCasPrefixUrl() + "/login", "service", getServiceUrl()); - } - login(ctx, loginUrl); - - } - - protected void login(final Context ctx, final String loginUrl) throws Exception { - - callLoginPage(ctx, loginUrl); + val loginUrl = callLoginPage(ctx); if (ctx.getStatus() == 200) { postCredentials(ctx, loginUrl); @@ -42,18 +31,22 @@ protected void login(final Context ctx, final String loginUrl) throws Exception } - protected void callLoginPage(final Context ctx, final String loginUrl) throws Exception { - val tgc = (Pair) ctx.get(TGC); - - if (tgc != null) { - info("Re-use: " + tgc.getLeft() + "=" + tgc.getRight()); - ctx.getCookies().put(getCasCookieName(), tgc.getRight()); + protected String callLoginPage(final Context ctx) throws Exception { + var loginUrl = getLocation(ctx); + if (isBlank(loginUrl)) { + loginUrl = addUrlParameter(getCasPrefixUrl() + "/login", "service", getServiceUrl()); } + useSsoSession(ctx); + ctx.setRequest(get(ctx, loginUrl)); execute(ctx); + + return loginUrl; } + + protected void postCredentials(final Context ctx, final String loginUrl) throws Exception { val webflow = substringBetween(ctx.getBody(), "name=\"execution\" value=\"", "\"/>"); @@ -66,8 +59,6 @@ protected void postCredentials(final Context ctx, final String loginUrl) throws ctx.setRequest(post(ctx, loginUrl)); execute(ctx); - val tgc = getCookie(ctx, getCasCookieName()); - ctx.put(TGC, tgc); - info("Found: " + tgc.getLeft() + "=" + tgc.getRight()); + saveSsoSession(ctx); } } diff --git a/src/main/java/com/casinthecloud/simpletest/cas/CasOIDCLoginTest.java b/src/main/java/com/casinthecloud/simpletest/cas/CasOIDCLoginTest.java index c491385..80fc299 100644 --- a/src/main/java/com/casinthecloud/simpletest/cas/CasOIDCLoginTest.java +++ b/src/main/java/com/casinthecloud/simpletest/cas/CasOIDCLoginTest.java @@ -4,7 +4,6 @@ import lombok.Getter; import lombok.Setter; import lombok.val; -import org.apache.commons.lang3.tuple.Pair; import static com.casinthecloud.simpletest.util.Utils.addUrlParameter; import static com.casinthecloud.simpletest.util.Utils.random; @@ -37,9 +36,9 @@ public void run(final Context ctx) throws Exception { super.run(ctx); - callbackCas(ctx); + callback(ctx); - callbackApp(ctx); + callback(ctx); } @@ -57,31 +56,16 @@ protected void authorize(final Context ctx) throws Exception { execute(ctx); assertStatus(ctx, 302); - val casSession = getCookie(ctx, DISSESSION); - ctx.put(CAS_SESSION, casSession); - info("Found CAS session: " + casSession.getLeft() + "=" + casSession.getRight()); + saveCasSession(ctx); } - protected void callbackCas(final Context ctx) throws Exception { - val callbackCasUrl = getLocation(ctx); - val tgc = (Pair) ctx.get(TGC); - val casSession = (Pair) ctx.get(CAS_SESSION); + protected void callback(final Context ctx) throws Exception { + val callbackUrl = getLocation(ctx); - ctx.getCookies().put(casSession.getLeft(), casSession.getRight()); - ctx.getCookies().put(tgc.getLeft(), tgc.getRight()); - ctx.setRequest(get(ctx, callbackCasUrl)); - execute(ctx); - assertStatus(ctx, 302); - } - - protected void callbackApp(final Context ctx) throws Exception { - val callbackAppUrl = getLocation(ctx); - val tgc = (Pair) ctx.get(TGC); - val casSession = (Pair) ctx.get(CAS_SESSION); + useSsoSession(ctx); + useCasSession(ctx); - ctx.getCookies().put(casSession.getLeft(), casSession.getRight()); - ctx.getCookies().put(TGC, tgc.getRight()); - ctx.setRequest(get(ctx, callbackAppUrl)); + ctx.setRequest(get(ctx, callbackUrl)); execute(ctx); assertStatus(ctx, 302); } diff --git a/src/main/java/com/casinthecloud/simpletest/cas/CasOIDCValidateOCTest.java b/src/main/java/com/casinthecloud/simpletest/cas/CasOIDCValidateOCTest.java index c3c619e..6e14761 100644 --- a/src/main/java/com/casinthecloud/simpletest/cas/CasOIDCValidateOCTest.java +++ b/src/main/java/com/casinthecloud/simpletest/cas/CasOIDCValidateOCTest.java @@ -9,7 +9,7 @@ import static org.apache.commons.lang3.StringUtils.substringBetween; /** - * A test performing an OIDC login in the CAS server. + * A test performing a code OC validation to retrieve the access token in the CAS server. * * @author Jerome LELEU * @since 1.0.0 diff --git a/src/main/java/com/casinthecloud/simpletest/cas/CasSAML2LoginTest.java b/src/main/java/com/casinthecloud/simpletest/cas/CasSAML2LoginTest.java index a116d13..68a61fa 100644 --- a/src/main/java/com/casinthecloud/simpletest/cas/CasSAML2LoginTest.java +++ b/src/main/java/com/casinthecloud/simpletest/cas/CasSAML2LoginTest.java @@ -4,7 +4,6 @@ import lombok.Getter; import lombok.Setter; import lombok.val; -import org.apache.commons.lang3.tuple.Pair; import java.time.ZoneOffset; import java.time.ZonedDateTime; @@ -65,18 +64,15 @@ protected void postRequest(final Context ctx) throws Exception { execute(ctx); assertStatus(ctx, 302); - val casSession = getCookie(ctx, JSESSIONID); - ctx.put(CAS_SESSION, casSession); - info("Found CAS session: " + casSession.getLeft() + "=" + casSession.getRight()); + saveCasSession(ctx); } protected void callbackCas(final Context ctx) throws Exception { val callbackUrl = getLocation(ctx); - val tgc = (Pair) ctx.get(TGC); - val casSession = (Pair) ctx.get(CAS_SESSION); - ctx.getCookies().put(casSession.getLeft(), casSession.getRight()); - ctx.getCookies().put(tgc.getLeft(), tgc.getRight()); + useSsoSession(ctx); + useCasSession(ctx); + ctx.setRequest(get(ctx, callbackUrl)); execute(ctx); assertStatus(ctx, 200); diff --git a/src/main/java/com/casinthecloud/simpletest/cas/CasTest.java b/src/main/java/com/casinthecloud/simpletest/cas/CasTest.java index 9f1465f..4e619e9 100644 --- a/src/main/java/com/casinthecloud/simpletest/cas/CasTest.java +++ b/src/main/java/com/casinthecloud/simpletest/cas/CasTest.java @@ -1,8 +1,11 @@ package com.casinthecloud.simpletest.cas; +import com.casinthecloud.simpletest.execution.Context; import com.casinthecloud.simpletest.test.ChainingTest; import lombok.Getter; import lombok.Setter; +import lombok.val; +import org.apache.commons.lang3.tuple.Pair; /** * A test for CAS. @@ -15,10 +18,10 @@ @Setter public abstract class CasTest extends ChainingTest { - protected static final String JSESSIONID = "JSESSIONID"; - protected static final String TGC = "TGC"; - protected static final String DISSESSION = "DISSESSION"; - protected static final String CAS_SESSION = "CAS_SESSION"; + private static final String JSESSIONID = "JSESSIONID"; + private static final String DISSESSION = "DISSESSION"; + private static final String CAS_SESSION = "CAS_SESSION"; + private static final String TGC = "TGC"; private String casPrefixUrl = "http://localhost:8080/cas"; @@ -29,4 +32,35 @@ public abstract class CasTest extends ChainingTest { private String username = "jleleu"; private String password = "jleleu"; + + protected void saveCasSession(final Context ctx) { + var casSession = getCookie(ctx, DISSESSION); + if (casSession == null) { + casSession = getCookie(ctx, JSESSIONID); + } + ctx.put(testId + CAS_SESSION, casSession); + info("Found CAS session: " + casSession.getLeft() + "=" + casSession.getRight()); + } + + protected void useCasSession(final Context ctx) { + val casSession = (Pair) ctx.get(testId + CAS_SESSION); + if (casSession != null) { + info("Re-use: " + casSession.getLeft() + "=" + casSession.getRight()); + ctx.getCookies().put(casSession.getLeft(), casSession.getRight()); + } + } + + protected void saveSsoSession(final Context ctx) { + val tgc = getCookie(ctx, getCasCookieName()); + ctx.put(testId + TGC, tgc); + info("Found: " + tgc.getLeft() + "=" + tgc.getRight()); + } + + protected void useSsoSession(final Context ctx) { + val tgc = (Pair) ctx.get(testId + TGC); + if (tgc != null) { + info("Re-use: " + tgc.getLeft() + "=" + tgc.getRight()); + ctx.getCookies().put(getCasCookieName(), tgc.getRight()); + } + } } diff --git a/src/main/java/com/casinthecloud/simpletest/cas/CasValidateTest.java b/src/main/java/com/casinthecloud/simpletest/cas/CasValidateTest.java index 24c78e7..527eb89 100644 --- a/src/main/java/com/casinthecloud/simpletest/cas/CasValidateTest.java +++ b/src/main/java/com/casinthecloud/simpletest/cas/CasValidateTest.java @@ -9,7 +9,7 @@ import static org.apache.commons.lang3.StringUtils.substringAfter; /** - * A test performing a CAS login in the CAS server. + * A test performing a ST validation in the CAS server. * * @author Jerome LELEU * @since 1.0.0 @@ -22,6 +22,7 @@ public void run(final Context ctx) throws Exception { val callbackUrl = getLocation(ctx); val st = substringAfter(callbackUrl, "ticket="); + info("Service ticket: " + st); var validateUrl = getCasPrefixUrl() + "/p3/serviceValidate"; validateUrl = addUrlParameter(validateUrl, "service", getServiceUrl()); diff --git a/src/main/java/com/casinthecloud/simpletest/test/BaseTest.java b/src/main/java/com/casinthecloud/simpletest/test/BaseTest.java index 7ead117..76aac50 100644 --- a/src/main/java/com/casinthecloud/simpletest/test/BaseTest.java +++ b/src/main/java/com/casinthecloud/simpletest/test/BaseTest.java @@ -29,6 +29,10 @@ */ public abstract class BaseTest { + private static int SEQ = 1; + + protected int testId; + @Setter private HttpClient client; @@ -48,6 +52,10 @@ public abstract class BaseTest { @Setter private boolean displayInfos; + protected BaseTest() { + testId = SEQ++; + } + public abstract void run(final Context ctx) throws Exception; protected String getLocation(final Context ctx) { diff --git a/src/test/java/com/casinthecloud/simpletest/MainDelegate.java b/src/test/java/com/casinthecloud/simpletest/MainDelegate.java new file mode 100644 index 0000000..d8c8097 --- /dev/null +++ b/src/test/java/com/casinthecloud/simpletest/MainDelegate.java @@ -0,0 +1,18 @@ +package com.casinthecloud.simpletest; + +import com.casinthecloud.simpletest.cas.CasDelegateTest; +import com.casinthecloud.simpletest.cas.CasLoginTest; +import com.casinthecloud.simpletest.cas.CasOIDCLoginTest; +import com.casinthecloud.simpletest.cas.CasOIDCValidateOCTest; +import com.casinthecloud.simpletest.execution.Execution; + +import static com.casinthecloud.simpletest.util.Utils.AND; + +public class MainDelegate { + + public static void main(final String... args) throws Exception { + new Execution(() -> { + return AND(new CasOIDCLoginTest(new CasDelegateTest("CasClient", new CasLoginTest())), new CasOIDCValidateOCTest()); + }).launch(); + } +}