Added warning when storage contains multi-valued attributes and Keycloak model doesn't support them.
Closes #9714
This commit is contained in:
parent
781ceb24fd
commit
9e257d4a01
3 changed files with 35 additions and 3 deletions
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.map.client;
|
package org.keycloak.models.map.client;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
|
@ -39,6 +40,7 @@ import java.util.stream.Stream;
|
||||||
*/
|
*/
|
||||||
public abstract class MapClientAdapter extends AbstractClientModel<MapClientEntity> implements ClientModel {
|
public abstract class MapClientAdapter extends AbstractClientModel<MapClientEntity> implements ClientModel {
|
||||||
|
|
||||||
|
private static final Logger LOG = Logger.getLogger(MapClientAdapter.class);
|
||||||
private final MapProtocolMapperUtils pmUtils;
|
private final MapProtocolMapperUtils pmUtils;
|
||||||
|
|
||||||
public MapClientAdapter(KeycloakSession session, RealmModel realm, MapClientEntity entity) {
|
public MapClientAdapter(KeycloakSession session, RealmModel realm, MapClientEntity entity) {
|
||||||
|
@ -286,7 +288,15 @@ public abstract class MapClientAdapter extends AbstractClientModel<MapClientEnti
|
||||||
final Map<String, List<String>> a = attributes == null ? Collections.emptyMap() : attributes;
|
final Map<String, List<String>> a = attributes == null ? Collections.emptyMap() : attributes;
|
||||||
return a.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
|
return a.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
|
||||||
entry -> {
|
entry -> {
|
||||||
if (entry.getValue().isEmpty()) return null;
|
if (entry.getValue().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else if (entry.getValue().size() > 1) {
|
||||||
|
// This could be caused by an inconsistency in the storage, a programming error,
|
||||||
|
// or a downgrade from a future version of Keycloak that already supports multi-valued attributes.
|
||||||
|
// The caller will not see the other values, and when this entity is later updated, the additional values will be lost.
|
||||||
|
LOG.warnf("Client '%s' realm '%s' has attribute '%s' with %d values, retrieving only the first", getClientId(), getRealm().getName(), entry.getKey(),
|
||||||
|
entry.getValue().size());
|
||||||
|
}
|
||||||
return entry.getValue().get(0);
|
return entry.getValue().get(0);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -25,6 +25,8 @@ import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.models.ClientScopeModel;
|
import org.keycloak.models.ClientScopeModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
|
@ -37,6 +39,7 @@ import org.keycloak.models.utils.RoleUtils;
|
||||||
|
|
||||||
public class MapClientScopeAdapter extends AbstractClientScopeModel<MapClientScopeEntity> implements ClientScopeModel {
|
public class MapClientScopeAdapter extends AbstractClientScopeModel<MapClientScopeEntity> implements ClientScopeModel {
|
||||||
|
|
||||||
|
private static final Logger LOG = Logger.getLogger(MapClientScopeAdapter.class);
|
||||||
private final MapProtocolMapperUtils pmUtils;
|
private final MapProtocolMapperUtils pmUtils;
|
||||||
|
|
||||||
public MapClientScopeAdapter(KeycloakSession session, RealmModel realm, MapClientScopeEntity entity) {
|
public MapClientScopeAdapter(KeycloakSession session, RealmModel realm, MapClientScopeEntity entity) {
|
||||||
|
@ -115,7 +118,15 @@ public class MapClientScopeAdapter extends AbstractClientScopeModel<MapClientSco
|
||||||
final Map<String, List<String>> a = attributes == null ? Collections.emptyMap() : attributes;
|
final Map<String, List<String>> a = attributes == null ? Collections.emptyMap() : attributes;
|
||||||
return a.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
|
return a.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
|
||||||
entry -> {
|
entry -> {
|
||||||
if (entry.getValue().isEmpty()) return null;
|
if (entry.getValue().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else if (entry.getValue().size() > 1) {
|
||||||
|
// This could be caused by an inconsistency in the storage, a programming error,
|
||||||
|
// or a downgrade from a future version of Keycloak that already supports multi-valued attributes.
|
||||||
|
// The caller will not see the other values, and when this entity is later updated, the additional values will be lost.
|
||||||
|
LOG.warnf("ClientScope '%s' realm '%s' has attribute '%s' with %d values, retrieving only the first", getName(), getRealm().getName(), entry.getKey(),
|
||||||
|
entry.getValue().size());
|
||||||
|
}
|
||||||
return entry.getValue().get(0);
|
return entry.getValue().get(0);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -24,6 +24,8 @@ import static java.util.Objects.nonNull;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.common.enums.SslRequired;
|
import org.keycloak.common.enums.SslRequired;
|
||||||
import org.keycloak.component.ComponentFactory;
|
import org.keycloak.component.ComponentFactory;
|
||||||
|
@ -64,6 +66,7 @@ import org.keycloak.models.utils.ComponentUtil;
|
||||||
|
|
||||||
public class MapRealmAdapter extends AbstractRealmModel<MapRealmEntity> implements RealmModel {
|
public class MapRealmAdapter extends AbstractRealmModel<MapRealmEntity> implements RealmModel {
|
||||||
|
|
||||||
|
private static final Logger LOG = Logger.getLogger(MapRealmAdapter.class);
|
||||||
private static final String ACTION_TOKEN_GENERATED_BY_USER_LIFESPAN = "actionTokenGeneratedByUserLifespan";
|
private static final String ACTION_TOKEN_GENERATED_BY_USER_LIFESPAN = "actionTokenGeneratedByUserLifespan";
|
||||||
private static final String DEFAULT_SIGNATURE_ALGORITHM = "defaultSignatureAlgorithm";
|
private static final String DEFAULT_SIGNATURE_ALGORITHM = "defaultSignatureAlgorithm";
|
||||||
private static final String BRUTE_FORCE_PROTECTED = "bruteForceProtected";
|
private static final String BRUTE_FORCE_PROTECTED = "bruteForceProtected";
|
||||||
|
@ -207,7 +210,15 @@ public class MapRealmAdapter extends AbstractRealmModel<MapRealmEntity> implemen
|
||||||
public Map<String, String> getAttributes() {
|
public Map<String, String> getAttributes() {
|
||||||
return entity.getAttributes().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
|
return entity.getAttributes().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
|
||||||
entry -> {
|
entry -> {
|
||||||
if (entry.getValue().isEmpty()) return null;
|
if (entry.getValue().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else if (entry.getValue().size() > 1) {
|
||||||
|
// This could be caused by an inconsistency in the storage, a programming error,
|
||||||
|
// or a downgrade from a future version of Keycloak that already supports multi-valued attributes.
|
||||||
|
// The caller will not see the other values, and when this entity is later updated, the additional values be will lost.
|
||||||
|
LOG.warnf("Realm '%s' has attribute '%s' with %d values, retrieving only the first", getId(), entry.getKey(),
|
||||||
|
entry.getValue().size());
|
||||||
|
}
|
||||||
return entry.getValue().get(0);
|
return entry.getValue().get(0);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue