KEYCLOAK-5315 Conditional OTP enforcement does not work (#4399)
This commit is contained in:
parent
550e5f752a
commit
b7af96aa4d
2 changed files with 85 additions and 0 deletions
|
@ -300,10 +300,27 @@ public class ConditionalOtpFormAuthenticator extends OTPFormAuthenticator {
|
||||||
&& configModel.getConfig().size() <= 1) {
|
&& configModel.getConfig().size() <= 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (containsConditionalOtpConfig(configModel.getConfig())
|
||||||
|
&& voteForUserOtpControlAttribute(user, configModel.getConfig()) == ABSTAIN
|
||||||
|
&& voteForUserRole(realm, user, configModel.getConfig()) == ABSTAIN
|
||||||
|
&& voteForHttpHeaderMatchesPattern(requestHeaders, configModel.getConfig()) == ABSTAIN
|
||||||
|
&& (voteForDefaultFallback(configModel.getConfig()) == SHOW_OTP
|
||||||
|
|| voteForDefaultFallback(configModel.getConfig()) == ABSTAIN)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean containsConditionalOtpConfig(Map config) {
|
||||||
|
return config.containsKey(OTP_CONTROL_USER_ATTRIBUTE)
|
||||||
|
|| config.containsKey(SKIP_OTP_ROLE)
|
||||||
|
|| config.containsKey(FORCE_OTP_ROLE)
|
||||||
|
|| config.containsKey(SKIP_OTP_FOR_HTTP_HEADER)
|
||||||
|
|| config.containsKey(FORCE_OTP_FOR_HTTP_HEADER)
|
||||||
|
|| config.containsKey(DEFAULT_OTP_OUTCOME);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
|
public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||||
if (!isOTPRequired(session, realm, user)) {
|
if (!isOTPRequired(session, realm, user)) {
|
||||||
|
|
|
@ -175,6 +175,74 @@ public class CustomAuthFlowOTPTest extends AbstractCustomAccountManagementTest {
|
||||||
assertCurrentUrlStartsWith(testLoginOneTimeCodePage);
|
assertCurrentUrlStartsWith(testLoginOneTimeCodePage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void conditionalOTPNoDefaultWithChecks() {
|
||||||
|
configureRequiredActions();
|
||||||
|
configureOTP();
|
||||||
|
//prepare config - no configuration specified
|
||||||
|
Map<String, String> config = new HashMap<>();
|
||||||
|
config.put(OTP_CONTROL_USER_ATTRIBUTE, "noSuchUserSkipAttribute");
|
||||||
|
config.put(SKIP_OTP_ROLE, "no_such_otp_role");
|
||||||
|
config.put(FORCE_OTP_ROLE, "no_such_otp_role");
|
||||||
|
config.put(SKIP_OTP_FOR_HTTP_HEADER, "NoSuchHost: nolocalhost:65536");
|
||||||
|
config.put(FORCE_OTP_FOR_HTTP_HEADER, "NoSuchHost: nolocalhost:65536");
|
||||||
|
setConditionalOTPForm(config);
|
||||||
|
|
||||||
|
//test OTP is required
|
||||||
|
testRealmAccountManagementPage.navigateTo();
|
||||||
|
testRealmLoginPage.form().login(testUser);
|
||||||
|
testRealmLoginPage.form().totpForm().waitForTotpInputFieldPresent();
|
||||||
|
|
||||||
|
//verify that the page is login page, not totp setup
|
||||||
|
assertCurrentUrlStartsWith(testLoginOneTimeCodePage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void conditionalOTPDefaultSkipWithChecks() {
|
||||||
|
//prepare config - default skip
|
||||||
|
Map<String, String> config = new HashMap<>();
|
||||||
|
config.put(OTP_CONTROL_USER_ATTRIBUTE, "noSuchUserSkipAttribute");
|
||||||
|
config.put(SKIP_OTP_ROLE, "no_such_otp_role");
|
||||||
|
config.put(FORCE_OTP_ROLE, "no_such_otp_role");
|
||||||
|
config.put(SKIP_OTP_FOR_HTTP_HEADER, "NoSuchHost: nolocalhost:65536");
|
||||||
|
config.put(FORCE_OTP_FOR_HTTP_HEADER, "NoSuchHost: nolocalhost:65536");
|
||||||
|
config.put(DEFAULT_OTP_OUTCOME, SKIP);
|
||||||
|
|
||||||
|
setConditionalOTPForm(config);
|
||||||
|
|
||||||
|
//test OTP is skipped
|
||||||
|
testRealmAccountManagementPage.navigateTo();
|
||||||
|
testRealmLoginPage.form().login(testUser);
|
||||||
|
assertCurrentUrlStartsWith(testRealmAccountManagementPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void conditionalOTPDefaultForceWithChecks() {
|
||||||
|
|
||||||
|
//prepare config - default force
|
||||||
|
Map<String, String> config = new HashMap<>();
|
||||||
|
config.put(OTP_CONTROL_USER_ATTRIBUTE, "noSuchUserSkipAttribute");
|
||||||
|
config.put(SKIP_OTP_ROLE, "no_such_otp_role");
|
||||||
|
config.put(FORCE_OTP_ROLE, "no_such_otp_role");
|
||||||
|
config.put(SKIP_OTP_FOR_HTTP_HEADER, "NoSuchHost: nolocalhost:65536");
|
||||||
|
config.put(FORCE_OTP_FOR_HTTP_HEADER, "NoSuchHost: nolocalhost:65536");
|
||||||
|
config.put(DEFAULT_OTP_OUTCOME, FORCE);
|
||||||
|
|
||||||
|
setConditionalOTPForm(config);
|
||||||
|
|
||||||
|
//test OTP is forced
|
||||||
|
testRealmAccountManagementPage.navigateTo();
|
||||||
|
testRealmLoginPage.form().login(testUser);
|
||||||
|
assertTrue(loginConfigTotpPage.isCurrent());
|
||||||
|
|
||||||
|
configureOTP();
|
||||||
|
testRealmLoginPage.form().login(testUser);
|
||||||
|
testRealmLoginPage.form().totpForm().waitForTotpInputFieldPresent();
|
||||||
|
|
||||||
|
//verify that the page is login page, not totp setup
|
||||||
|
assertCurrentUrlStartsWith(testLoginOneTimeCodePage);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void conditionalOTPUserAttributeSkip() {
|
public void conditionalOTPUserAttributeSkip() {
|
||||||
//prepare config - user attribute, default to force
|
//prepare config - user attribute, default to force
|
||||||
|
|
Loading…
Reference in a new issue