Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.parosproxy.paros.Constant;
Expand All @@ -51,6 +52,8 @@ public final class MsLoginAuthenticator implements Authenticator {
private static final By PASSWORD_FIELD = By.id("i0118");
private static final By SUBMIT_BUTTON = By.id("idSIButton9");
private static final By KMSI_FIELD = By.id("KmsiCheckboxField");
private static final By PROOF_REDIRECT_FIELD = By.id("idSubmit_ProofUp_Redirect");
private static final By PROOF_DONE_FIELD = By.id("id__5");

private enum State {
START,
Expand All @@ -61,6 +64,9 @@ private enum State {

POST_PASSWORD,
STAY_SIGNED_IN,

PROOF_REDIRECT,
PROOF,
}

@Override
Expand Down Expand Up @@ -177,7 +183,13 @@ private Result authenticateImpl(
Constant.messages.getString(
"authhelper.auth.method.diags.steps.ms.stepchoice"));

// XXX There might be a proof step too…
try {
waitForElement(wd, PROOF_REDIRECT_FIELD);
states.add(State.PROOF_REDIRECT);
break;
} catch (TimeoutException e) {
// Ignore, there's still the next step to check.
}

try {
waitForElement(wd, KMSI_FIELD);
Expand Down Expand Up @@ -206,15 +218,54 @@ private Result authenticateImpl(
states.add(State.SUBMIT);
states.add(State.POST_PASSWORD);
break;

case PROOF_REDIRECT:
WebElement proofElement = wd.findElement(PROOF_REDIRECT_FIELD);
proofElement.click();
diags.recordStep(
wd,
Constant.messages.getString(
"authhelper.auth.method.diags.steps.ms.clickproofredirect"),
proofElement);

states.add(State.PROOF);
break;

case PROOF:
try {
waitForElement(wd, new ElementWithText(By.tagName("button"), "Skip setup"));
WebElement doneElement =
waitForElement(wd, new ElementWithText(PROOF_DONE_FIELD, "Done"));
doneElement.click();
diags.recordStep(
wd,
Constant.messages.getString(
"authhelper.auth.method.diags.steps.ms.clickproofdone"),
doneElement);

states.add(State.POST_PASSWORD);
break;
} catch (TimeoutException e) {
diags.recordStep(
wd,
Constant.messages.getString(
"authhelper.auth.method.diags.steps.ms.stepproofunknown"));
LOGGER.debug(
"Still in proof but no skip/done button found, assuming unsuccessful login.");
break;
}
}
} while (!states.isEmpty());

return new Result(true, successful, userField, pwdField);
}

private WebElement waitForElement(WebDriver wd, By by) {
return new WebDriverWait(wd, DEFAULT_WAIT_UNTIL)
.until(ExpectedConditions.elementToBeClickable(by));
return waitForElement(wd, ExpectedConditions.elementToBeClickable(by));
}

private WebElement waitForElement(WebDriver wd, ExpectedCondition<WebElement> condition) {
return new WebDriverWait(wd, DEFAULT_WAIT_UNTIL).until(condition);
}

private static boolean isMsLoginFlow(WebDriver wd) {
Expand All @@ -230,4 +281,28 @@ private static boolean isMsLoginFlow(WebDriver wd, Duration duration) {
return false;
}
}

private static class ElementWithText implements ExpectedCondition<WebElement> {

private final By locator;
private final String text;

ElementWithText(By locator, String text) {
this.locator = locator;
this.text = text;
}

@Override
public WebElement apply(WebDriver driver) {
return driver.findElements(locator).stream()
.filter(e -> text.equalsIgnoreCase(e.getText()))
.findFirst()
.orElse(null);
}

@Override
public String toString() {
return String.format("element '%s' with text '%s' is not present", locator, text);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,13 @@ authhelper.auth.method.diags.steps.finish = Finished Steps
authhelper.auth.method.diags.steps.loginlink = Login Link
authhelper.auth.method.diags.steps.ms.clickbutton = [MS] Click Button
authhelper.auth.method.diags.steps.ms.clickkmsi = [MS] Click KMSI
authhelper.auth.method.diags.steps.ms.clickproofdone = [MS] Click Proof Done
authhelper.auth.method.diags.steps.ms.clickproofredirect = [MS] Click Proof Redirect
authhelper.auth.method.diags.steps.ms.missingbutton = [MS] Missing Button
authhelper.auth.method.diags.steps.ms.missingpassword = [MS] Missing Password Field
authhelper.auth.method.diags.steps.ms.missingusername = [MS] Missing Username Field
authhelper.auth.method.diags.steps.ms.stepchoice = [MS] Step Choice
authhelper.auth.method.diags.steps.ms.stepproofunknown = [MS] Step Proof Unknown
authhelper.auth.method.diags.steps.ms.stepunknown = [MS] Step Unknown
authhelper.auth.method.diags.steps.password = Auto Fill Password
authhelper.auth.method.diags.steps.refresh = Auto Refresh
Expand Down