KEYCLOAK-12742 Authentication -> WebAuthn Policy: Unable to delete the Acceptable AAGUIDS via the provided minus (-) button, once set (#6695)

This commit is contained in:
Denis Richtárik 2020-01-24 11:55:20 +01:00 committed by Marek Posolda
parent 303861f7e8
commit 24c6e2ba08
3 changed files with 21 additions and 18 deletions

View file

@ -1034,8 +1034,9 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
if (acceptableAaguids != null && !acceptableAaguids.isEmpty()) { if (acceptableAaguids != null && !acceptableAaguids.isEmpty()) {
String acceptableAaguidsString = String.join(",", acceptableAaguids); String acceptableAaguidsString = String.join(",", acceptableAaguids);
setAttribute(RealmAttributes.WEBAUTHN_POLICY_ACCEPTABLE_AAGUIDS, acceptableAaguidsString); setAttribute(RealmAttributes.WEBAUTHN_POLICY_ACCEPTABLE_AAGUIDS, acceptableAaguidsString);
} else {
removeAttribute(RealmAttributes.WEBAUTHN_POLICY_ACCEPTABLE_AAGUIDS);
} }
} }
@Override @Override

View file

@ -68,13 +68,7 @@ import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException; import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
@ -245,7 +239,7 @@ public class RealmTest extends AbstractAdminTest {
} }
//test will fail on AssertionError when both BadRequestException and NotFoundException is not thrown //test will fail on AssertionError when both BadRequestException and NotFoundException is not thrown
} }
//KEYCLOAK-6146 //KEYCLOAK-6146
@Test @Test
public void createRealmWithPasswordPolicyFromJsonWithValidPasswords() { public void createRealmWithPasswordPolicyFromJsonWithValidPasswords() {
@ -318,7 +312,7 @@ public class RealmTest extends AbstractAdminTest {
recr.setAdminEventsDetailsEnabled(rep.isAdminEventsDetailsEnabled()); recr.setAdminEventsDetailsEnabled(rep.isAdminEventsDetailsEnabled());
return recr; return recr;
} }
private void checkRealmEventsConfigRepresentation(RealmEventsConfigRepresentation expected, private void checkRealmEventsConfigRepresentation(RealmEventsConfigRepresentation expected,
RealmEventsConfigRepresentation actual) { RealmEventsConfigRepresentation actual) {
assertEquals(expected.getEnabledEventTypes().size(), actual.getEnabledEventTypes().size()); assertEquals(expected.getEnabledEventTypes().size(), actual.getEnabledEventTypes().size());
@ -330,15 +324,15 @@ public class RealmTest extends AbstractAdminTest {
assertEquals(expected.isAdminEventsEnabled(), actual.isAdminEventsEnabled()); assertEquals(expected.isAdminEventsEnabled(), actual.isAdminEventsEnabled());
assertEquals(expected.isAdminEventsDetailsEnabled(), actual.isAdminEventsDetailsEnabled()); assertEquals(expected.isAdminEventsDetailsEnabled(), actual.isAdminEventsDetailsEnabled());
} }
@Test @Test
public void updateRealmEventsConfig() { public void updateRealmEventsConfig() {
RealmEventsConfigRepresentation rep = realm.getRealmEventsConfig(); RealmEventsConfigRepresentation rep = realm.getRealmEventsConfig();
RealmEventsConfigRepresentation repOrig = copyRealmEventsConfigRepresentation(rep); RealmEventsConfigRepresentation repOrig = copyRealmEventsConfigRepresentation(rep);
// the "event-queue" listener should be enabled by default // the "event-queue" listener should be enabled by default
assertTrue("event-queue should be enabled initially", rep.getEventsListeners().contains(EventsListenerProviderFactory.PROVIDER_ID)); assertTrue("event-queue should be enabled initially", rep.getEventsListeners().contains(EventsListenerProviderFactory.PROVIDER_ID));
// first modification => remove "event-queue", should be sent to the queue // first modification => remove "event-queue", should be sent to the queue
rep.setEnabledEventTypes(Arrays.asList(EventType.LOGIN.name(), EventType.LOGIN_ERROR.name())); rep.setEnabledEventTypes(Arrays.asList(EventType.LOGIN.name(), EventType.LOGIN_ERROR.name()));
rep.setEventsListeners(Arrays.asList(JBossLoggingEventListenerProviderFactory.ID)); rep.setEventsListeners(Arrays.asList(JBossLoggingEventListenerProviderFactory.ID));
@ -350,15 +344,15 @@ public class RealmTest extends AbstractAdminTest {
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, "events/config", rep, ResourceType.REALM); assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, "events/config", rep, ResourceType.REALM);
RealmEventsConfigRepresentation actual = realm.getRealmEventsConfig(); RealmEventsConfigRepresentation actual = realm.getRealmEventsConfig();
checkRealmEventsConfigRepresentation(rep, actual); checkRealmEventsConfigRepresentation(rep, actual);
// second modification => should not be sent cos event-queue was removed in the first mod // second modification => should not be sent cos event-queue was removed in the first mod
rep.setEnabledEventTypes(Arrays.asList(EventType.LOGIN.name(), rep.setEnabledEventTypes(Arrays.asList(EventType.LOGIN.name(),
EventType.LOGIN_ERROR.name(), EventType.CLIENT_LOGIN.name())); EventType.LOGIN_ERROR.name(), EventType.CLIENT_LOGIN.name()));
adminClient.realms().realm(REALM_NAME).updateRealmEventsConfig(rep); adminClient.realms().realm(REALM_NAME).updateRealmEventsConfig(rep);
assertAdminEvents.assertEmpty(); assertAdminEvents.assertEmpty();
actual = realm.getRealmEventsConfig(); actual = realm.getRealmEventsConfig();
checkRealmEventsConfigRepresentation(rep, actual); checkRealmEventsConfigRepresentation(rep, actual);
// third modification => restore queue => should be sent and recovered // third modification => restore queue => should be sent and recovered
adminClient.realms().realm(REALM_NAME).updateRealmEventsConfig(repOrig); adminClient.realms().realm(REALM_NAME).updateRealmEventsConfig(repOrig);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, "events/config", repOrig, ResourceType.REALM); assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, "events/config", repOrig, ResourceType.REALM);
@ -446,10 +440,15 @@ public class RealmTest extends AbstractAdminTest {
public void updateRealmAttributes() { public void updateRealmAttributes() {
// first change // first change
RealmRepresentation rep = new RealmRepresentation(); RealmRepresentation rep = new RealmRepresentation();
List<String> webAuthnPolicyAcceptableAaguids = new ArrayList<>();
webAuthnPolicyAcceptableAaguids.add("aaguid1");
webAuthnPolicyAcceptableAaguids.add("aaguid2");
rep.setAttributes(new HashMap<>()); rep.setAttributes(new HashMap<>());
rep.getAttributes().put("foo1", "bar1"); rep.getAttributes().put("foo1", "bar1");
rep.getAttributes().put("foo2", "bar2"); rep.getAttributes().put("foo2", "bar2");
rep.setWebAuthnPolicyAcceptableAaguids(webAuthnPolicyAcceptableAaguids);
rep.setBruteForceProtected(true); rep.setBruteForceProtected(true);
rep.setDisplayName("dn1"); rep.setDisplayName("dn1");
@ -457,17 +456,19 @@ public class RealmTest extends AbstractAdminTest {
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM); assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM);
rep = realm.toRepresentation(); rep = realm.toRepresentation();
assertEquals("bar1", rep.getAttributes().get("foo1")); assertEquals("bar1", rep.getAttributes().get("foo1"));
assertEquals("bar2", rep.getAttributes().get("foo2")); assertEquals("bar2", rep.getAttributes().get("foo2"));
assertTrue(rep.isBruteForceProtected()); assertTrue(rep.isBruteForceProtected());
assertEquals("dn1", rep.getDisplayName()); assertEquals("dn1", rep.getDisplayName());
assertEquals(webAuthnPolicyAcceptableAaguids, rep.getWebAuthnPolicyAcceptableAaguids());
// second change // second change
webAuthnPolicyAcceptableAaguids.clear();
rep.setBruteForceProtected(false); rep.setBruteForceProtected(false);
rep.setDisplayName("dn2"); rep.setDisplayName("dn2");
rep.getAttributes().put("foo1", "bar11"); rep.getAttributes().put("foo1", "bar11");
rep.getAttributes().remove("foo2"); rep.getAttributes().remove("foo2");
rep.setWebAuthnPolicyAcceptableAaguids(webAuthnPolicyAcceptableAaguids);
realm.update(rep); realm.update(rep);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM); assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM);
@ -479,6 +480,7 @@ public class RealmTest extends AbstractAdminTest {
assertEquals("bar11", rep.getAttributes().get("foo1")); assertEquals("bar11", rep.getAttributes().get("foo1"));
assertFalse(rep.getAttributes().containsKey("foo2")); assertFalse(rep.getAttributes().containsKey("foo2"));
assertTrue(rep.getWebAuthnPolicyAcceptableAaguids().isEmpty());
} }
@Test @Test

View file

@ -125,7 +125,7 @@
<label for="type" class="col-md-2 control-label">{{:: 'webauthn-acceptable-aaguids' | translate}}</label> <label for="type" class="col-md-2 control-label">{{:: 'webauthn-acceptable-aaguids' | translate}}</label>
<div class="col-sm-4"> <div class="col-sm-4">
<div class="input-group" ng-repeat="(i, acceptableAaguid) in realm.webAuthnPolicyAcceptableAaguids track by $index"> <div class="input-group" ng-repeat="(i, acceptableAaguid) in realm.webAuthnPolicyAcceptableAaguids track by $index">
<input class="form-control" ng-model="realm.webAuthnPolicyAcceptableAaguids[i]"> <input id="type" class="form-control" ng-model="realm.webAuthnPolicyAcceptableAaguids[i]">
<div class="input-group-btn"> <div class="input-group-btn">
<button class="btn btn-default" type="button" data-ng-click="deleteAcceptableAaguid($index)"> <button class="btn btn-default" type="button" data-ng-click="deleteAcceptableAaguid($index)">
<span class="fa fa-minus"></span> <span class="fa fa-minus"></span>