Merge pull request #3051 from patriot1burke/master
user fed spi fixes and simple test
This commit is contained in:
commit
76c4fbb241
20 changed files with 1096 additions and 82 deletions
|
@ -27,7 +27,6 @@ import org.keycloak.models.ModelException;
|
|||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredActionProviderModel;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
|
@ -41,6 +40,7 @@ import org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity;
|
|||
import org.keycloak.models.jpa.entities.UserConsentRoleEntity;
|
||||
import org.keycloak.models.jpa.entities.UserEntity;
|
||||
import org.keycloak.models.utils.CredentialValidation;
|
||||
import org.keycloak.models.utils.DefaultRoles;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
|
@ -88,15 +88,7 @@ public class JpaUserProvider implements UserProvider {
|
|||
UserAdapter userModel = new UserAdapter(session, realm, em, entity);
|
||||
|
||||
if (addDefaultRoles) {
|
||||
for (String r : realm.getDefaultRoles()) {
|
||||
userModel.grantRoleImpl(realm.getRole(r)); // No need to check if user has role as it's new user
|
||||
}
|
||||
|
||||
for (ClientModel application : realm.getClients()) {
|
||||
for (String r : application.getDefaultRoles()) {
|
||||
userModel.grantRoleImpl(application.getRole(r)); // No need to check if user has role as it's new user
|
||||
}
|
||||
}
|
||||
DefaultRoles.addDefaultRoles(realm, userModel);
|
||||
|
||||
for (GroupModel g : realm.getDefaultGroups()) {
|
||||
userModel.joinGroupImpl(g); // No need to check if user has group as it's new user
|
||||
|
|
|
@ -19,6 +19,10 @@ package org.keycloak.models;
|
|||
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
import org.keycloak.storage.user.UserCredentialValidatorProvider;
|
||||
import org.keycloak.storage.user.UserLookupProvider;
|
||||
import org.keycloak.storage.user.UserQueryProvider;
|
||||
import org.keycloak.storage.user.UserUpdateProvider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -27,7 +31,11 @@ import java.util.Set;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserProvider extends Provider, UserLookupProvider, UserQueryProvider, UserCredentialValidatorProvider, UserUpdateProvider {
|
||||
public interface UserProvider extends Provider,
|
||||
UserLookupProvider,
|
||||
UserQueryProvider,
|
||||
UserCredentialValidatorProvider,
|
||||
UserUpdateProvider {
|
||||
// Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
|
||||
|
||||
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink);
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models.utils;
|
||||
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class DefaultRoles {
|
||||
public static Set<RoleModel> getDefaultRoles(RealmModel realm) {
|
||||
Set<RoleModel> set = new HashSet<>();
|
||||
for (String r : realm.getDefaultRoles()) {
|
||||
set.add(realm.getRole(r));
|
||||
}
|
||||
|
||||
for (ClientModel application : realm.getClients()) {
|
||||
for (String r : application.getDefaultRoles()) {
|
||||
set.add(application.getRole(r));
|
||||
}
|
||||
}
|
||||
return set;
|
||||
|
||||
}
|
||||
public static void addDefaultRoles(RealmModel realm, UserModel userModel) {
|
||||
for (RoleModel role : getDefaultRoles(realm)) {
|
||||
userModel.grantRole(role);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,6 +42,12 @@ public class StorageId implements Serializable {
|
|||
|
||||
}
|
||||
|
||||
public StorageId(String providerId, String storageId) {
|
||||
this.id = "f:" + providerId + ":" + storageId;
|
||||
this.providerId = providerId;
|
||||
this.storageId = storageId;
|
||||
}
|
||||
|
||||
public static String resolveProviderId(UserModel user) {
|
||||
return new StorageId(user.getId()).getProviderId();
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.keycloak.provider.Provider;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface StorageProvider extends Provider {
|
||||
StorageProviderModel getModel();
|
||||
|
||||
void preRemove(RealmModel realm);
|
||||
void preRemove(RealmModel realm, GroupModel group);
|
||||
|
|
|
@ -28,16 +28,16 @@ import org.keycloak.models.ProtocolMapperModel;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserCredentialAuthenticationProvider;
|
||||
import org.keycloak.storage.user.UserCredentialAuthenticationProvider;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValidatorProvider;
|
||||
import org.keycloak.storage.user.UserCredentialValidatorProvider;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserLookupProvider;
|
||||
import org.keycloak.storage.user.UserLookupProvider;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.models.UserQueryProvider;
|
||||
import org.keycloak.models.UserUpdateProvider;
|
||||
import org.keycloak.storage.user.UserQueryProvider;
|
||||
import org.keycloak.storage.user.UserUpdateProvider;
|
||||
import org.keycloak.models.utils.CredentialValidation;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
|
||||
|
|
|
@ -16,138 +16,211 @@
|
|||
*/
|
||||
package org.keycloak.storage.adapter;
|
||||
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
import org.keycloak.models.utils.DefaultRoles;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.storage.StorageId;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This abstract class provides implementations for everything but getUsername(). getId() returns a default value
|
||||
* of "f:" + providerId + ":" + getUsername(). isEnabled() returns true. getRoleMappings() will return default roles.
|
||||
* getGroups() will return default groups.
|
||||
*
|
||||
* All other read methods return null, an empty collection, or false depending
|
||||
* on the type. All update methods throw a ReadOnlyException.
|
||||
*
|
||||
* Provider implementors should override the methods for attributes, properties, and mappings they support.
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public abstract class AbstractUserAdapter implements UserModel {
|
||||
public static class ReadOnlyException extends RuntimeException {
|
||||
public ReadOnlyException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
protected KeycloakSession session;
|
||||
protected RealmModel realm;
|
||||
protected StorageProviderModel storageProviderModel;
|
||||
|
||||
public UserFederatedStorageProvider getFederatedStorage() {
|
||||
return null;
|
||||
public AbstractUserAdapter(KeycloakSession session, RealmModel realm, StorageProviderModel storageProviderModel) {
|
||||
this.session = session;
|
||||
this.realm = realm;
|
||||
this.storageProviderModel = storageProviderModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRequiredActions() {
|
||||
return getFederatedStorage().getRequiredActions(realm, this);
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredAction(String action) {
|
||||
getFederatedStorage().addRequiredAction(realm, this, action);
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(String action) {
|
||||
getFederatedStorage().removeRequiredAction(realm, this, action);
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredAction(RequiredAction action) {
|
||||
getFederatedStorage().addRequiredAction(realm, this, action.name());
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(RequiredAction action) {
|
||||
getFederatedStorage().removeRequiredAction(realm, this, action.name());
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get group membership mappings that are managed by this storage provider
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected Set<GroupModel> getGroupsInternal() {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the realm's default groups be appended to getGroups() call?
|
||||
* If your storage provider is not managing group mappings then it is recommended that
|
||||
* this method return true
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean appendDefaultGroups() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<GroupModel> getGroups() {
|
||||
return null;
|
||||
Set<GroupModel> set = new HashSet<>();
|
||||
if (appendDefaultGroups()) set.addAll(realm.getDefaultGroups());
|
||||
set.addAll(getGroupsInternal());
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinGroup(GroupModel group) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveGroup(GroupModel group) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMemberOf(GroupModel group) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFederationLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFederationLink(String link) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceAccountClientLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServiceAccountClientLink(String clientInternalId) {
|
||||
|
||||
Set<GroupModel> roles = getGroups();
|
||||
return KeycloakModelUtils.isMember(roles, group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmRoleMappings() {
|
||||
return null;
|
||||
Set<RoleModel> roleMappings = getRoleMappings();
|
||||
|
||||
Set<RoleModel> realmRoles = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof RealmModel) {
|
||||
realmRoles.add(role);
|
||||
}
|
||||
}
|
||||
return realmRoles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getClientRoleMappings(ClientModel app) {
|
||||
return null;
|
||||
Set<RoleModel> roleMappings = getRoleMappings();
|
||||
|
||||
Set<RoleModel> roles = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof ClientModel) {
|
||||
ClientModel appModel = (ClientModel) container;
|
||||
if (appModel.getId().equals(app.getId())) {
|
||||
roles.add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRole(RoleModel role) {
|
||||
return false;
|
||||
Set<RoleModel> roles = getRoleMappings();
|
||||
return KeycloakModelUtils.hasRole(roles, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantRole(RoleModel role) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the realm's default roles be appended to getRoleMappings() call?
|
||||
* If your storage provider is not managing all role mappings then it is recommended that
|
||||
* this method return true
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean appendDefaultRolesToRoleMappings() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Set<RoleModel> getRoleMappingsInternal() {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoleMappings() {
|
||||
return null;
|
||||
Set<RoleModel> set = new HashSet<>();
|
||||
if (appendDefaultRolesToRoleMappings()) set.addAll(DefaultRoles.getDefaultRoles(realm));
|
||||
set.addAll(getRoleMappingsInternal());
|
||||
return set;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deleteRoleMapping(RoleModel role) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -157,6 +230,176 @@ public abstract class AbstractUserAdapter implements UserModel {
|
|||
|
||||
@Override
|
||||
public void setOtpEnabled(boolean totp) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be overriden
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getFederationLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be overriden
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void setFederationLink(String link) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be overriden
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getServiceAccountClientLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be overriden
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void setServiceAccountClientLink(String clientInternalId) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
protected StorageId storageId;
|
||||
|
||||
/**
|
||||
* Defaults to 'f:' + storageProvider.getId() + ':' + getUsername()
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
if (storageId == null) {
|
||||
storageId = new StorageId(storageProviderModel.getId(), getUsername());
|
||||
}
|
||||
return storageId.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
}
|
||||
|
||||
protected long created = System.currentTimeMillis();
|
||||
|
||||
@Override
|
||||
public Long getCreatedTimestamp() {
|
||||
return created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCreatedTimestamp(Long timestamp) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSingleAttribute(String name, String value) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, List<String> values) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstAttribute(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getAttributes() {
|
||||
return new MultivaluedHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAttribute(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFirstName(String firstName) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLastName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastName(String lastName) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmail() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmail(String email) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmailVerified() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmailVerified(boolean verified) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserCredentialValueModel> getCredentialsDirectly() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
throw new ReadOnlyException("user is read only for this update");
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,419 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.adapter;
|
||||
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.DefaultRoles;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.storage.StorageId;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Assumes everything is managed by federated storage except for username. getId() returns a default value
|
||||
* of "f:" + providerId + ":" + getUsername(). UserModel properties like enabled, firstName, lastName, email, etc. are all
|
||||
* stored as attributes in federated storage.
|
||||
*
|
||||
* isEnabled() defaults to true if the ENABLED_ATTRIBUTE isn't set in federated
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
|
||||
public static String FIRST_NAME_ATTRIBUTE = "FIRST_NAME";
|
||||
public static String LAST_NAME_ATTRIBUTE = "LAST_NAME";
|
||||
public static String EMAIL_ATTRIBUTE = "EMAIL";
|
||||
public static String EMAIL_VERIFIED_ATTRIBUTE = "EMAIL_VERIFIED";
|
||||
public static String CREATED_TIMESTAMP_ATTRIBUTE = "CREATED_TIMESTAMP";
|
||||
public static String ENABLED_ATTRIBUTE = "ENABLED";
|
||||
public static String OTP_ENABLED_ATTRIBUTE = "OTP_ENABLED";
|
||||
|
||||
|
||||
protected KeycloakSession session;
|
||||
protected RealmModel realm;
|
||||
protected StorageProviderModel storageProviderModel;
|
||||
|
||||
public AbstractUserAdapterFederatedStorage(KeycloakSession session, RealmModel realm, StorageProviderModel storageProviderModel) {
|
||||
this.session = session;
|
||||
this.realm = realm;
|
||||
this.storageProviderModel = storageProviderModel;
|
||||
}
|
||||
|
||||
public UserFederatedStorageProvider getFederatedStorage() {
|
||||
return session.userFederatedStorage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRequiredActions() {
|
||||
return getFederatedStorage().getRequiredActions(realm, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredAction(String action) {
|
||||
getFederatedStorage().addRequiredAction(realm, this, action);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(String action) {
|
||||
getFederatedStorage().removeRequiredAction(realm, this, action);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredAction(RequiredAction action) {
|
||||
getFederatedStorage().addRequiredAction(realm, this, action.name());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(RequiredAction action) {
|
||||
getFederatedStorage().removeRequiredAction(realm, this, action.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get group membership mappings that are managed by this storage provider
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected Set<GroupModel> getGroupsInternal() {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the realm's default groups be appended to getGroups() call?
|
||||
* If your storage provider is not managing group mappings then it is recommended that
|
||||
* this method return true
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean appendDefaultGroups() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<GroupModel> getGroups() {
|
||||
Set<GroupModel> set = new HashSet<>();
|
||||
set.addAll(getFederatedStorage().getGroups(realm, this));
|
||||
if (appendDefaultGroups()) set.addAll(realm.getDefaultGroups());
|
||||
set.addAll(getGroupsInternal());
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinGroup(GroupModel group) {
|
||||
getFederatedStorage().joinGroup(realm, this, group);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveGroup(GroupModel group) {
|
||||
getFederatedStorage().leaveGroup(realm, this, group);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMemberOf(GroupModel group) {
|
||||
Set<GroupModel> roles = getGroups();
|
||||
return KeycloakModelUtils.isMember(roles, group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmRoleMappings() {
|
||||
Set<RoleModel> roleMappings = getRoleMappings();
|
||||
|
||||
Set<RoleModel> realmRoles = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof RealmModel) {
|
||||
realmRoles.add(role);
|
||||
}
|
||||
}
|
||||
return realmRoles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getClientRoleMappings(ClientModel app) {
|
||||
Set<RoleModel> roleMappings = getRoleMappings();
|
||||
|
||||
Set<RoleModel> roles = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof ClientModel) {
|
||||
ClientModel appModel = (ClientModel) container;
|
||||
if (appModel.getId().equals(app.getId())) {
|
||||
roles.add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRole(RoleModel role) {
|
||||
Set<RoleModel> roles = getRoleMappings();
|
||||
return KeycloakModelUtils.hasRole(roles, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantRole(RoleModel role) {
|
||||
getFederatedStorage().grantRole(realm, this, role);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the realm's default roles be appended to getRoleMappings() call?
|
||||
* If your storage provider is not managing all role mappings then it is recommended that
|
||||
* this method return true
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean appendDefaultRolesToRoleMappings() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Set<RoleModel> getRoleMappingsInternal() {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoleMappings() {
|
||||
Set<RoleModel> set = new HashSet<>();
|
||||
set.addAll(getFederatedRoleMappings());
|
||||
if (appendDefaultRolesToRoleMappings()) set.addAll(DefaultRoles.getDefaultRoles(realm));
|
||||
set.addAll(getRoleMappingsInternal());
|
||||
return set;
|
||||
}
|
||||
|
||||
protected Set<RoleModel> getFederatedRoleMappings() {
|
||||
return getFederatedStorage().getRoleMappings(realm, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRoleMapping(RoleModel role) {
|
||||
getFederatedStorage().deleteRoleMapping(realm, this, role);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
String val = getFirstAttribute(ENABLED_ATTRIBUTE);
|
||||
if (val == null) return true;
|
||||
else return Boolean.valueOf(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
setSingleAttribute(ENABLED_ATTRIBUTE, Boolean.toString(enabled));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOtpEnabled() {
|
||||
String val = getFirstAttribute(OTP_ENABLED_ATTRIBUTE);
|
||||
if (val == null) return false;
|
||||
else return Boolean.valueOf(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOtpEnabled(boolean totp) {
|
||||
setSingleAttribute(OTP_ENABLED_ATTRIBUTE, Boolean.toString(totp));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be overriden
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getFederationLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be overriden
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void setFederationLink(String link) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be overriden
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getServiceAccountClientLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be overriden
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void setServiceAccountClientLink(String clientInternalId) {
|
||||
|
||||
}
|
||||
|
||||
protected StorageId storageId;
|
||||
|
||||
/**
|
||||
* Defaults to 'f:' + storageProvider.getId() + ':' + getUsername()
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
if (storageId == null) {
|
||||
storageId = new StorageId(storageProviderModel.getId(), getUsername());
|
||||
}
|
||||
return storageId.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getCreatedTimestamp() {
|
||||
String val = getFirstAttribute(CREATED_TIMESTAMP_ATTRIBUTE);
|
||||
if (val == null) return null;
|
||||
else return Long.valueOf(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCreatedTimestamp(Long timestamp) {
|
||||
if (timestamp == null) {
|
||||
setSingleAttribute(CREATED_TIMESTAMP_ATTRIBUTE, null);
|
||||
} else {
|
||||
setSingleAttribute(CREATED_TIMESTAMP_ATTRIBUTE, Long.toString(timestamp));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSingleAttribute(String name, String value) {
|
||||
getFederatedStorage().setSingleAttribute(realm, this, name, value);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
getFederatedStorage().removeAttribute(realm, this, name);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, List<String> values) {
|
||||
getFederatedStorage().setAttribute(realm, this, name, values);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstAttribute(String name) {
|
||||
return getFederatedStorage().getAttributes(realm, this).getFirst(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getAttributes() {
|
||||
return getFederatedStorage().getAttributes(realm, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAttribute(String name) {
|
||||
return getFederatedStorage().getAttributes(realm, this).get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstName() {
|
||||
return getFirstAttribute(FIRST_NAME_ATTRIBUTE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFirstName(String firstName) {
|
||||
setSingleAttribute(FIRST_NAME_ATTRIBUTE, firstName);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLastName() {
|
||||
return getFirstAttribute(LAST_NAME_ATTRIBUTE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastName(String lastName) {
|
||||
setSingleAttribute(LAST_NAME_ATTRIBUTE, lastName);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmail() {
|
||||
return getFirstAttribute(EMAIL_ATTRIBUTE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmail(String email) {
|
||||
setSingleAttribute(EMAIL_ATTRIBUTE, email);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmailVerified() {
|
||||
String val = getFirstAttribute(EMAIL_VERIFIED_ATTRIBUTE);
|
||||
if (val == null) return false;
|
||||
else return Boolean.valueOf(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmailVerified(boolean verified) {
|
||||
setSingleAttribute(EMAIL_VERIFIED_ATTRIBUTE, Boolean.toString(verified));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
getFederatedStorage().updateCredential(realm, this, cred);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserCredentialValueModel> getCredentialsDirectly() {
|
||||
return getFederatedStorage().getCredentials(realm, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
getFederatedStorage().updateCredential(realm, this, cred);
|
||||
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CredentialModel {
|
||||
}
|
|
@ -14,7 +14,12 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models;
|
||||
package org.keycloak.storage.user;
|
||||
|
||||
import org.keycloak.models.CredentialValidationOutput;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
|
||||
import java.util.Set;
|
||||
|
|
@ -14,7 +14,12 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models;
|
||||
package org.keycloak.storage.user;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
|
@ -14,7 +14,10 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models;
|
||||
package org.keycloak.storage.user;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
@ -14,7 +14,11 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models;
|
||||
package org.keycloak.storage.user;
|
||||
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
|
@ -14,7 +14,11 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models;
|
||||
package org.keycloak.storage.user;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.federation.storage;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
import org.keycloak.testsuite.OAuthClient;
|
||||
import org.keycloak.testsuite.pages.AppPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.rule.KeycloakRule;
|
||||
import org.keycloak.testsuite.rule.WebResource;
|
||||
import org.keycloak.testsuite.rule.WebRule;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserFederationStorageTest {
|
||||
@ClassRule
|
||||
public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
|
||||
|
||||
@Override
|
||||
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
||||
StorageProviderModel model = new StorageProviderModel();
|
||||
model.setDisplayName("user-props");
|
||||
model.setPriority(1);
|
||||
model.setProviderName(UserPropertyFileStorageFactory.PROVIDER_ID);
|
||||
appRealm.addStorageProvider(model);
|
||||
}
|
||||
});
|
||||
@Rule
|
||||
public WebRule webRule = new WebRule(this);
|
||||
|
||||
@WebResource
|
||||
protected OAuthClient oauth;
|
||||
|
||||
@WebResource
|
||||
protected WebDriver driver;
|
||||
|
||||
@WebResource
|
||||
protected AppPage appPage;
|
||||
|
||||
@WebResource
|
||||
protected LoginPage loginPage;
|
||||
|
||||
private void loginSuccessAndLogout(String username, String password) {
|
||||
loginPage.open();
|
||||
loginPage.login(username, password);
|
||||
Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||
Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE));
|
||||
oauth.openLogout();
|
||||
}
|
||||
|
||||
public void loginBadPassword(String username) {
|
||||
loginPage.open();
|
||||
loginPage.login("username", "badpassword");
|
||||
Assert.assertEquals("Invalid username or password.", loginPage.getError());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLoginSuccess() {
|
||||
loginSuccessAndLogout("tbrady", "goat");
|
||||
loginBadPassword("tbrady");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.federation.storage;
|
||||
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.storage.StorageId;
|
||||
import org.keycloak.storage.StorageProvider;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
import org.keycloak.storage.adapter.AbstractUserAdapter;
|
||||
import org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
import org.keycloak.storage.user.UserCredentialValidatorProvider;
|
||||
import org.keycloak.storage.user.UserLookupProvider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserPropertyFileStorage implements UserLookupProvider, StorageProvider, UserCredentialValidatorProvider {
|
||||
|
||||
protected Properties userPasswords;
|
||||
protected StorageProviderModel model;
|
||||
protected KeycloakSession session;
|
||||
protected boolean federatedStorageEnabled;
|
||||
|
||||
public UserPropertyFileStorage(KeycloakSession session, StorageProviderModel model, Properties userPasswords) {
|
||||
this.session = session;
|
||||
this.model = model;
|
||||
this.userPasswords = userPasswords;
|
||||
this.federatedStorageEnabled = model.getConfig().containsKey("USER_FEDERATED_STORAGE");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UserModel getUserById(String id, RealmModel realm) {
|
||||
StorageId storageId = new StorageId(id);
|
||||
final String username = storageId.getStorageId();
|
||||
if (!userPasswords.containsKey(username)) return null;
|
||||
|
||||
return createUser(realm, username);
|
||||
}
|
||||
|
||||
private UserModel createUser(final RealmModel realm, final String username) {
|
||||
return new AbstractUserAdapter(session, realm, model) {
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByUsername(String username, RealmModel realm) {
|
||||
if (!userPasswords.containsKey(username)) return null;
|
||||
|
||||
return createUser(realm, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByEmail(String email, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, GroupModel group) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, RoleModel role) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, StorageProviderModel model) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||
for (UserCredentialModel cred : input) {
|
||||
if (!cred.getType().equals(UserCredentialModel.PASSWORD)) return false;
|
||||
String password = (String)userPasswords.get(user.getUsername());
|
||||
if (password == null) return false;
|
||||
if (!password.equals(cred.getValue())) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.federation.storage;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.storage.StorageProvider;
|
||||
import org.keycloak.storage.StorageProviderFactory;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserPropertyFileStorageFactory implements StorageProviderFactory {
|
||||
|
||||
|
||||
public static final String PROVIDER_ID = "user-password-props";
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> type) {
|
||||
return type.isAssignableFrom(UserPropertyFileStorage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageProvider getInstance(KeycloakSession session, StorageProviderModel model) {
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(getClass().getResourceAsStream("/storage-test/user-password.properties"));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return new UserPropertyFileStorage(session, model, props);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getConfigurationOptions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.keycloak.testsuite.federation.storage.UserPropertyFileStorageFactory
|
|
@ -23,6 +23,7 @@ log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p %t [%c] %m%
|
|||
|
||||
log4j.logger.org.keycloak=info
|
||||
|
||||
|
||||
# Enable to view events
|
||||
# log4j.logger.org.keycloak.events=debug
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
tbrady=goat
|
Loading…
Reference in a new issue