parent
8238467c49
commit
07ab29378b
4 changed files with 62 additions and 41 deletions
|
@ -99,6 +99,8 @@ public class DefaultRequiredActions {
|
|||
addUpdateLocaleAction(realm);
|
||||
addDeleteAccountAction(realm);
|
||||
addUpdateEmailAction(realm);
|
||||
addWebAuthnRegisterAction(realm);
|
||||
addWebAuthnPasswordlessRegisterAction(realm);
|
||||
}
|
||||
|
||||
public static void addDeleteAccountAction(RealmModel realm) {
|
||||
|
@ -140,4 +142,40 @@ public class DefaultRequiredActions {
|
|||
realm.addRequiredActionProvider(updateEmail);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addWebAuthnRegisterAction(RealmModel realm) {
|
||||
final String PROVIDER_ID = "webauthn-register";
|
||||
|
||||
final boolean isWebAuthnFeatureEnabled = Profile.isFeatureEnabled(Profile.Feature.WEB_AUTHN);
|
||||
final boolean isRequiredActionActive = realm.getRequiredActionProviderByAlias(PROVIDER_ID) != null;
|
||||
|
||||
if (isWebAuthnFeatureEnabled && !isRequiredActionActive) {
|
||||
final RequiredActionProviderModel webauthnRegister = new RequiredActionProviderModel();
|
||||
webauthnRegister.setEnabled(true);
|
||||
webauthnRegister.setAlias(PROVIDER_ID);
|
||||
webauthnRegister.setName("Webauthn Register");
|
||||
webauthnRegister.setProviderId(PROVIDER_ID);
|
||||
webauthnRegister.setDefaultAction(false);
|
||||
webauthnRegister.setPriority(70);
|
||||
realm.addRequiredActionProvider(webauthnRegister);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addWebAuthnPasswordlessRegisterAction(RealmModel realm) {
|
||||
final String PROVIDER_ID = "webauthn-register-passwordless";
|
||||
|
||||
final boolean isWebAuthnFeatureEnabled = Profile.isFeatureEnabled(Profile.Feature.WEB_AUTHN);
|
||||
final boolean isRequiredActionActive = realm.getRequiredActionProviderByAlias(PROVIDER_ID) != null;
|
||||
|
||||
if (isWebAuthnFeatureEnabled && !isRequiredActionActive) {
|
||||
final RequiredActionProviderModel webauthnRegister = new RequiredActionProviderModel();
|
||||
webauthnRegister.setEnabled(true);
|
||||
webauthnRegister.setAlias(PROVIDER_ID);
|
||||
webauthnRegister.setName("Webauthn Register Passwordless");
|
||||
webauthnRegister.setProviderId(PROVIDER_ID);
|
||||
webauthnRegister.setDefaultAction(false);
|
||||
webauthnRegister.setPriority(80);
|
||||
realm.addRequiredActionProvider(webauthnRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ import org.keycloak.testsuite.util.UserBuilder;
|
|||
import org.keycloak.userprofile.UserProfileContext;
|
||||
import org.keycloak.validate.validators.EmailValidator;
|
||||
|
||||
import javax.ws.rs.ClientErrorException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
@ -76,12 +77,14 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
|
@ -533,14 +536,28 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
requiredAction.setId("12345");
|
||||
requiredAction.setName(WebAuthnRegisterFactory.PROVIDER_ID);
|
||||
requiredAction.setProviderId(WebAuthnRegisterFactory.PROVIDER_ID);
|
||||
testRealm().flows().registerRequiredAction(requiredAction);
|
||||
|
||||
try {
|
||||
testRealm().flows().registerRequiredAction(requiredAction);
|
||||
} catch (ClientErrorException e) {
|
||||
assertThat(e.getResponse(), notNullValue());
|
||||
assertThat(e.getResponse().getStatus(), is(409));
|
||||
}
|
||||
|
||||
getCleanup().addRequiredAction(requiredAction.getProviderId());
|
||||
|
||||
requiredAction = new RequiredActionProviderSimpleRepresentation();
|
||||
requiredAction.setId("6789");
|
||||
requiredAction.setName(WebAuthnPasswordlessRegisterFactory.PROVIDER_ID);
|
||||
requiredAction.setProviderId(WebAuthnPasswordlessRegisterFactory.PROVIDER_ID);
|
||||
testRealm().flows().registerRequiredAction(requiredAction);
|
||||
|
||||
try {
|
||||
testRealm().flows().registerRequiredAction(requiredAction);
|
||||
} catch (ClientErrorException e) {
|
||||
assertThat(e.getResponse(), notNullValue());
|
||||
assertThat(e.getResponse().getStatus(), is(409));
|
||||
}
|
||||
|
||||
getCleanup().addRequiredAction(requiredAction.getProviderId());
|
||||
|
||||
List<AccountCredentialResource.CredentialContainer> credentials = getCredentials();
|
||||
|
|
|
@ -52,6 +52,8 @@ public class RequiredActionsTest extends AbstractAuthenticationTest {
|
|||
addRequiredAction(expected, "delete_account", "Delete Account", false, false, null);
|
||||
addRequiredAction(expected, "terms_and_conditions", "Terms and Conditions", false, false, null);
|
||||
addRequiredAction(expected, "update_user_locale", "Update User Locale", true, false, null);
|
||||
addRequiredAction(expected, "webauthn-register", "Webauthn Register", true, false, null);
|
||||
addRequiredAction(expected, "webauthn-register-passwordless", "Webauthn Register Passwordless", true, false, null);
|
||||
|
||||
compareRequiredActions(expected, sort(result));
|
||||
|
||||
|
@ -82,7 +84,7 @@ public class RequiredActionsTest extends AbstractAuthenticationTest {
|
|||
|
||||
// Dummy RequiredAction is not registered in the realm and WebAuthn actions
|
||||
List<RequiredActionProviderSimpleRepresentation> result = authMgmtResource.getUnregisteredRequiredActions();
|
||||
Assert.assertEquals(4, result.size());
|
||||
Assert.assertEquals(2, result.size());
|
||||
RequiredActionProviderSimpleRepresentation action = result.stream().filter(
|
||||
a -> a.getProviderId().equals(DummyRequiredActionFactory.PROVIDER_ID)
|
||||
).findFirst().get();
|
||||
|
|
|
@ -959,43 +959,16 @@ public class BrowserFlowTest extends AbstractTestRealmKeycloakTest {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test checks that if a REQUIRED authentication execution which has isUserSetupAllowed -> true
|
||||
* has its requiredActionProvider in a not registered state, then it will not try to create the required action,
|
||||
* and will instead raise an credential setup required error.
|
||||
* NOTE: webauthn currently isn't configured by default in the realm. When this changes, this test will need to be adapted
|
||||
*/
|
||||
@Test
|
||||
@AuthServerContainerExclude(REMOTE)
|
||||
public void testLoginWithWithNoWebAuthnCredentialAndNoRequiredActionProviderRegistered(){
|
||||
String newFlowAlias = "browser - copy 1";
|
||||
configureBrowserFlowWithRequiredWebAuthn(newFlowAlias);
|
||||
try {
|
||||
provideUsernamePassword("test-user@localhost");
|
||||
|
||||
// Assert that the login evaluates to an error, as all required elements to not validate to successful
|
||||
errorPage.assertCurrent();
|
||||
|
||||
} finally {
|
||||
revertFlows("browser - copy 1");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test checks that if a REQUIRED authentication execution which has isUserSetupAllowed -> true
|
||||
* has its requiredActionProvider disabled, then it will not try to create the required action,
|
||||
* and will instead raise an credential setup required error.
|
||||
* NOTE: webauthn currently isn't configured by default in the realm. When this changes, this test will need to be adapted
|
||||
*/
|
||||
@Test
|
||||
@AuthServerContainerExclude(REMOTE)
|
||||
public void testLoginWithWithNoWebAuthnCredentialAndRequiredActionProviderDisabled(){
|
||||
String newFlowAlias = "browser - copy 1";
|
||||
configureBrowserFlowWithRequiredWebAuthn(newFlowAlias);
|
||||
RequiredActionProviderSimpleRepresentation requiredActionRepresentation = new RequiredActionProviderSimpleRepresentation();
|
||||
requiredActionRepresentation.setName("WebAuthn Required Action");
|
||||
requiredActionRepresentation.setProviderId(WebAuthnRegisterFactory.PROVIDER_ID);
|
||||
testRealm().flows().registerRequiredAction(requiredActionRepresentation);
|
||||
RequiredActionProviderRepresentation rapr = testRealm().flows().getRequiredAction(WebAuthnRegisterFactory.PROVIDER_ID);
|
||||
rapr.setEnabled(false);
|
||||
testRealm().flows().updateRequiredAction(WebAuthnRegisterFactory.PROVIDER_ID, rapr);
|
||||
|
@ -1007,14 +980,12 @@ public class BrowserFlowTest extends AbstractTestRealmKeycloakTest {
|
|||
|
||||
} finally {
|
||||
revertFlows("browser - copy 1");
|
||||
testRealm().flows().removeRequiredAction(WebAuthnRegisterFactory.PROVIDER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test checks that if a REQUIRED authentication execution which has isUserSetupAllowed -> true
|
||||
* has its requiredActionProvider enabled, than it will login and show the otpSetup page.
|
||||
* NOTE: webauthn currently isn't configured by default in the realm. When this changes, this test will need to be adapted
|
||||
* has its requiredActionProvider enabled, then it will login and show the WebAuthn registration page.
|
||||
*/
|
||||
@Test
|
||||
@AuthServerContainerExclude(REMOTE)
|
||||
|
@ -1022,20 +993,13 @@ public class BrowserFlowTest extends AbstractTestRealmKeycloakTest {
|
|||
String newFlowAlias = "browser - copy 1";
|
||||
configureBrowserFlowWithRequiredWebAuthn(newFlowAlias);
|
||||
|
||||
RequiredActionProviderSimpleRepresentation requiredActionRepresentation = new RequiredActionProviderSimpleRepresentation();
|
||||
requiredActionRepresentation.setName("WebAuthn Required Action");
|
||||
requiredActionRepresentation.setProviderId(WebAuthnRegisterFactory.PROVIDER_ID);
|
||||
testRealm().flows().registerRequiredAction(requiredActionRepresentation);
|
||||
|
||||
try {
|
||||
provideUsernamePassword("test-user@localhost");
|
||||
|
||||
// Assert that in this case you arrive to an webauthn setup
|
||||
Assert.assertTrue(driver.getCurrentUrl().contains("required-action?execution=" + WebAuthnRegisterFactory.PROVIDER_ID));
|
||||
|
||||
} finally {
|
||||
revertFlows("browser - copy 1");
|
||||
testRealm().flows().removeRequiredAction(WebAuthnRegisterFactory.PROVIDER_ID);
|
||||
UserRepresentation user = testRealm().users().search("test-user@localhost").get(0);
|
||||
user.setRequiredActions(Collections.emptyList());
|
||||
testRealm().users().get(user.getId()).update(user);
|
||||
|
|
Loading…
Reference in a new issue