You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2017/06/15 15:06:19 UTC

[5/8] ambari git commit: AMBARI-21147. Update Database Access Layer to Support New Database Schema for Improved User Account Management (rlevas)

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index fb06e6d..9227366 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -65,7 +65,7 @@ import org.apache.ambari.server.orm.entities.StageEntity;
 import org.apache.ambari.server.security.ClientSecurityType;
 import org.apache.ambari.server.security.authentication.kerberos.AmbariKerberosAuthenticationProperties;
 import org.apache.ambari.server.security.authorization.LdapServerProperties;
-import org.apache.ambari.server.security.authorization.UserType;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
 import org.apache.ambari.server.security.authorization.jwt.JwtAuthenticationProperties;
 import org.apache.ambari.server.security.encryption.CertificateUtils;
 import org.apache.ambari.server.security.encryption.CredentialProvider;
@@ -5997,7 +5997,7 @@ public class Configuration {
     // Get and process the configured user type values to convert the comma-delimited string of
     // user types into a ordered (as found in the comma-delimited value) list of UserType values.
     String userTypes = getProperty(KERBEROS_AUTH_USER_TYPES);
-    List<UserType> orderedUserTypes = new ArrayList<>();
+    List<UserAuthenticationType> orderedUserTypes = new ArrayList<>();
 
     String[] types = userTypes.split(",");
     for (String type : types) {
@@ -6005,7 +6005,7 @@ public class Configuration {
 
       if (!type.isEmpty()) {
         try {
-          orderedUserTypes.add(UserType.valueOf(type.toUpperCase()));
+          orderedUserTypes.add(UserAuthenticationType.valueOf(type.toUpperCase()));
         } catch (IllegalArgumentException e) {
           String message = String.format("While processing ordered user types from %s, " +
                   "%s was found to be an invalid user type.",
@@ -6020,7 +6020,7 @@ public class Configuration {
     if (orderedUserTypes.isEmpty()) {
       LOG.info("No (valid) user types were specified in {}. Using the default value of LOCAL.",
           KERBEROS_AUTH_USER_TYPES.getKey());
-      orderedUserTypes.add(UserType.LDAP);
+      orderedUserTypes.add(UserAuthenticationType.LDAP);
     }
 
     kerberosAuthProperties.setOrderedUserTypes(orderedUserTypes);

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
index 807bded..f4220bd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
@@ -119,15 +119,6 @@ public interface AmbariManagementController {
                       String versionTag, Map<String, Map<String, String>> propertiesAttributes);
 
   /**
-   * Creates users.
-   *
-   * @param requests the request objects which define the user.
-   *
-   * @throws AmbariException when the user cannot be created.
-   */
-  void createUsers(Set<UserRequest> requests) throws AmbariException;
-
-  /**
    * Creates groups.
    *
    * @param requests the request objects which define the groups.
@@ -196,18 +187,6 @@ public interface AmbariManagementController {
       throws AmbariException;
 
   /**
-   * Gets the users identified by the given request objects.
-   *
-   * @param requests the request objects
-   *
-   * @return a set of user responses
-   *
-   * @throws AmbariException if the users could not be read
-   */
-  Set<UserResponse> getUsers(Set<UserRequest> requests)
-      throws AmbariException, AuthorizationException;
-
-  /**
    * Gets the user groups identified by the given request objects.
    *
    * @param requests the request objects
@@ -253,15 +232,6 @@ public interface AmbariManagementController {
       throws AmbariException, AuthorizationException;
 
   /**
-   * Updates the users specified.
-   *
-   * @param requests the users to modify
-   *
-   * @throws AmbariException if the resources cannot be updated
-   */
-  void updateUsers(Set<UserRequest> requests) throws AmbariException, AuthorizationException;
-
-  /**
    * Updates the groups specified.
    *
    * @param requests the groups to modify
@@ -304,15 +274,6 @@ public interface AmbariManagementController {
       Set<ServiceComponentHostRequest> requests) throws AmbariException, AuthorizationException;
 
   /**
-   * Deletes the users specified.
-   *
-   * @param requests the users to delete
-   *
-   * @throws AmbariException if the resources cannot be deleted
-   */
-  void deleteUsers(Set<UserRequest> requests) throws AmbariException;
-
-  /**
    * Deletes the user groups specified.
    *
    * @param requests the groups to delete

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 8d262e2..a979845 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -136,7 +136,6 @@ import org.apache.ambari.server.security.authorization.GroupType;
 import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.ambari.server.security.authorization.User;
-import org.apache.ambari.server.security.authorization.UserType;
 import org.apache.ambari.server.security.authorization.Users;
 import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
 import org.apache.ambari.server.security.encryption.CredentialStoreService;
@@ -947,20 +946,6 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   }
 
   @Override
-  public void createUsers(Set<UserRequest> requests) throws AmbariException {
-
-    for (UserRequest request : requests) {
-
-      if (null == request.getUsername() || request.getUsername().isEmpty() ||
-          null == request.getPassword() || request.getPassword().isEmpty()) {
-        throw new AmbariException("Username and password must be supplied.");
-      }
-
-      users.createUser(request.getUsername(), request.getPassword(), UserType.LOCAL, request.isActive(), request.isAdmin());
-    }
-  }
-
-  @Override
   public void createGroups(Set<GroupRequest> requests) throws AmbariException {
     for (GroupRequest request : requests) {
       if (StringUtils.isBlank(request.getGroupName())) {
@@ -3405,65 +3390,6 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     return cluster.getServiceByComponentName(componentName).getName();
   }
 
-  /**
-   * Updates the users specified.
-   *
-   * @param requests the users to modify
-   *
-   * @throws AmbariException if the resources cannot be updated
-   * @throws IllegalArgumentException if the authenticated user is not authorized to update all of
-   * the requested properties
-   */
-  @Override
-  public synchronized void updateUsers(Set<UserRequest> requests) throws AmbariException, AuthorizationException {
-    boolean isUserAdministrator = AuthorizationHelper.isAuthorized(ResourceType.AMBARI, null,
-        RoleAuthorization.AMBARI_MANAGE_USERS);
-    String authenticatedUsername = AuthorizationHelper.getAuthenticatedName();
-
-    for (UserRequest request : requests) {
-      String requestedUsername = request.getUsername();
-
-      // An administrator can modify any user, else a user can only modify themself.
-      if (!isUserAdministrator && (!authenticatedUsername.equalsIgnoreCase(requestedUsername))) {
-        throw new AuthorizationException();
-      }
-
-      User u = users.getAnyUser(requestedUsername);
-      if (null == u) {
-        continue;
-      }
-
-      if (null != request.isActive()) {
-        // If this value is being set, make sure the authenticated user is an administrator before
-        // allowing to change it. Only administrators should be able to change a user's active state
-        if (!isUserAdministrator) {
-          throw new AuthorizationException("The authenticated user is not authorized to update the requested resource property");
-        }
-        users.setUserActive(u.getUserName(), request.isActive());
-      }
-
-      if (null != request.isAdmin()) {
-        // If this value is being set, make sure the authenticated user is an administrator before
-        // allowing to change it. Only administrators should be able to change a user's administrative
-        // privileges
-        if (!isUserAdministrator) {
-          throw new AuthorizationException("The authenticated user is not authorized to update the requested resource property");
-        }
-
-        if (request.isAdmin()) {
-          users.grantAdminPrivilege(u.getUserId());
-        } else {
-          users.revokeAdminPrivilege(u.getUserId());
-        }
-      }
-
-      if (null != request.getOldPassword() && null != request.getPassword()) {
-        users.modifyPassword(u.getUserName(), request.getOldPassword(),
-            request.getPassword());
-      }
-    }
-  }
-
   @Override
   public synchronized void deleteCluster(ClusterRequest request)
       throws AmbariException {
@@ -3637,21 +3563,6 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   }
 
   @Override
-  public void deleteUsers(Set<UserRequest> requests)
-    throws AmbariException {
-
-    for (UserRequest r : requests) {
-      if (LOG.isDebugEnabled()) {
-        LOG.debug("Received a delete user request, username={}", r.getUsername());
-      }
-      User u = users.getAnyUser(r.getUsername());
-      if (null != u) {
-        users.removeUser(u);
-      }
-    }
-  }
-
-  @Override
   public void deleteGroups(Set<GroupRequest> requests) throws AmbariException {
     for (GroupRequest request: requests) {
       LOG.debug("Received a delete group request, groupname={}", request.getGroupName());
@@ -3809,64 +3720,6 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   }
 
   @Override
-  public Set<UserResponse> getUsers(Set<UserRequest> requests)
-      throws AmbariException, AuthorizationException {
-
-    Set<UserResponse> responses = new HashSet<>();
-
-    for (UserRequest r : requests) {
-
-      if (LOG.isDebugEnabled()) {
-        LOG.debug("Received a getUsers request, userRequest={}", r);
-      }
-
-      String requestedUsername = r.getUsername();
-      String authenticatedUsername = AuthorizationHelper.getAuthenticatedName();
-
-      // A user resource may be retrieved by an administrator or the same user.
-      if(!AuthorizationHelper.isAuthorized(ResourceType.AMBARI, null, RoleAuthorization.AMBARI_MANAGE_USERS)) {
-        if (null == requestedUsername) {
-          // Since the authenticated user is not the administrator, force only that user's resource
-          // to be returned
-          requestedUsername = authenticatedUsername;
-        } else if (!requestedUsername.equalsIgnoreCase(authenticatedUsername)) {
-          // Since the authenticated user is not the administrator and is asking for a different user,
-          // throw an AuthorizationException
-          throw new AuthorizationException();
-        }
-      }
-
-      // get them all
-      if (null == requestedUsername) {
-        for (User u : users.getAllUsers()) {
-          UserResponse resp = new UserResponse(u.getUserName(), u.getUserType(), u.isLdapUser(), u.isActive(), u
-              .isAdmin());
-          resp.setGroups(new HashSet<>(u.getGroups()));
-          responses.add(resp);
-        }
-      } else {
-
-        User u = users.getAnyUser(requestedUsername);
-        if (null == u) {
-          if (requests.size() == 1) {
-            // only throw exceptin if there is a single request
-            // if there are multiple requests, this indicates an OR predicate
-            throw new ObjectNotFoundException("Cannot find user '"
-                + requestedUsername + "'");
-          }
-        } else {
-          UserResponse resp = new UserResponse(u.getUserName(), u.getUserType(), u.isLdapUser(), u.isActive(), u
-              .isAdmin());
-          resp.setGroups(new HashSet<>(u.getGroups()));
-          responses.add(resp);
-        }
-      }
-    }
-
-    return responses;
-  }
-
-  @Override
   public Set<GroupResponse> getGroups(Set<GroupRequest> requests)
       throws AmbariException {
     final Set<GroupResponse> responses = new HashSet<>();

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index aeba739..01920f8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -90,6 +90,7 @@ import org.apache.ambari.server.orm.dao.ResourceDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.MetainfoEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
 import org.apache.ambari.server.resources.ResourceManager;
 import org.apache.ambari.server.resources.api.rest.GetResource;
 import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
@@ -866,8 +867,16 @@ public class AmbariServer {
       LOG.info("Database init needed - creating default data");
       Users users = injector.getInstance(Users.class);
 
-      users.createUser("admin", "admin");
-      users.createUser("user", "user");
+      UserEntity userEntity;
+
+      // Create the admin user
+      userEntity = users.createUser("admin", "admin", "admin");
+      users.addLocalAuthentication(userEntity, "admin");
+      users.grantAdminPrivilege(userEntity);
+
+      // Create a normal user
+      userEntity = users.createUser("user", "user", "user");
+      users.addLocalAuthentication(userEntity, "user");
 
       MetainfoEntity schemaVersion = new MetainfoEntity();
       schemaVersion.setMetainfoName(Configuration.SERVER_VERSION_KEY);

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index f3c2ec8..25d12c7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -72,6 +72,7 @@ import org.apache.ambari.server.controller.internal.MemberResourceProvider;
 import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
 import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
+import org.apache.ambari.server.controller.internal.UserResourceProvider;
 import org.apache.ambari.server.controller.logging.LoggingRequestHelperFactory;
 import org.apache.ambari.server.controller.logging.LoggingRequestHelperFactoryImpl;
 import org.apache.ambari.server.controller.metrics.MetricPropertyProviderFactory;
@@ -464,6 +465,7 @@ public class ControllerModule extends AbstractModule {
         .implement(ResourceProvider.class, Names.named("member"), MemberResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("repositoryVersion"), RepositoryVersionResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("hostKerberosIdentity"), HostKerberosIdentityResourceProvider.class)
+        .implement(ResourceProvider.class, Names.named("user"), UserResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("credential"), CredentialResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("kerberosDescriptor"), KerberosDescriptorResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("upgrade"), UpgradeResourceProvider.class)

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
index 3912138..2454bf7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
@@ -51,6 +51,11 @@ public interface ResourceProviderFactory {
       Map<Type, String> keyPropertyIds,
       AmbariManagementController managementController);
 
+  @Named("user")
+  ResourceProvider getUserResourceProvider(Set<String> propertyIds,
+                                           Map<Type, String> keyPropertyIds,
+                                           AmbariManagementController managementController);
+
   @Named("hostKerberosIdentity")
   ResourceProvider getHostKerberosIdentityResourceProvider(AmbariManagementController managementController);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequest.java
index 40818c8..3011d01 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequest.java
@@ -31,15 +31,18 @@ public class UserRequest {
   private Boolean active;
   private Boolean admin;
 
-  @ApiModelProperty(name = "Users/user_name",hidden = true)
-  public String getUsername() {
-    return userName;
-  }
+  private String displayName;
+  private String localUserName;
 
   public UserRequest(String name) {
     this.userName = name;
   }
 
+  @ApiModelProperty(name = "Users/user_name",hidden = true)
+  public String getUsername() {
+    return userName;
+  }
+
   @ApiModelProperty(name = "Users/password")
   public String getPassword() {
     return password;
@@ -76,6 +79,24 @@ public class UserRequest {
     this.admin = admin;
   }
 
+  @ApiModelProperty(name = "Users/display_name")
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
+  }
+
+  @ApiModelProperty(name = "Users/local_user_name")
+  public String getLocalUserName() {
+    return localUserName;
+  }
+
+  public void setLocalUserName(String localUserName) {
+    this.localUserName = localUserName;
+  }
+
   @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/UserResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserResponse.java
index 5afacb7..bcb3aaf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserResponse.java
@@ -20,25 +20,26 @@ package org.apache.ambari.server.controller;
 import java.util.Collections;
 import java.util.Set;
 
-import org.apache.ambari.server.security.authorization.UserType;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
 
 import io.swagger.annotations.ApiModelProperty;
 
 /**
  * Represents a user maintenance request.
  */
-public class UserResponse implements ApiModel {
+public class
+UserResponse implements ApiModel {
 
   private final String userName;
-  private final UserType userType;
+  private final UserAuthenticationType authenticationType;
   private final boolean isLdapUser;
   private final boolean isActive;
   private final boolean isAdmin;
   private Set<String> groups = Collections.emptySet();
 
-  public UserResponse(String userName, UserType userType, boolean isLdapUser, boolean isActive, boolean isAdmin) {
+  public UserResponse(String userName, UserAuthenticationType userType, boolean isLdapUser, boolean isActive, boolean isAdmin) {
     this.userName = userName;
-    this.userType = userType;
+    this.authenticationType = userType;
     this.isLdapUser = isLdapUser;
     this.isActive = isActive;
     this.isAdmin = isAdmin;
@@ -49,7 +50,7 @@ public class UserResponse implements ApiModel {
     this.isLdapUser = isLdapUser;
     this.isActive = isActive;
     this.isAdmin = isAdmin;
-    this.userType = UserType.LOCAL;
+    this.authenticationType = UserAuthenticationType.LOCAL;
   }
 
   @ApiModelProperty(name = "Users/user_name",required = true)
@@ -84,9 +85,9 @@ public class UserResponse implements ApiModel {
     return isAdmin;
   }
 
-  @ApiModelProperty(name = "Users/user_type")
-  public UserType getUserType() {
-    return userType;
+  @ApiModelProperty(name = "Users/authentication_type")
+  public UserAuthenticationType getAuthenticationType() {
+    return authenticationType;
   }
 
   @Override
@@ -97,14 +98,14 @@ public class UserResponse implements ApiModel {
     UserResponse that = (UserResponse) o;
 
     if (userName != null ? !userName.equals(that.userName) : that.userName != null) return false;
-    return userType == that.userType;
+    return authenticationType == that.authenticationType;
 
   }
 
   @Override
   public int hashCode() {
     int result = userName != null ? userName.hashCode() : 0;
-    result = 31 * result + (userType != null ? userType.hashCode() : 0);
+    result = 31 * result + (authenticationType != null ? authenticationType.hashCode() : 0);
     return result;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index b35b2a8..595b7f9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -171,7 +171,7 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
       case Task:
         return new TaskResourceProvider(propertyIds, keyPropertyIds, managementController);
       case User:
-        return new UserResourceProvider(propertyIds, keyPropertyIds, managementController);
+        return resourceProviderFactory.getUserResourceProvider(propertyIds, keyPropertyIds, managementController);
       case Group:
         return new GroupResourceProvider(propertyIds, keyPropertyIds, managementController);
       case Member:

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProvider.java
index 389f0b2..a0a5e38 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProvider.java
@@ -160,7 +160,7 @@ public class ActiveWidgetLayoutResourceProvider extends AbstractControllerResour
       }
 
       java.lang.reflect.Type type = new TypeToken<Set<Map<String, String>>>(){}.getType();
-        Set<Map<String, String>> activeWidgetLayouts = gson.fromJson(userDAO.findSingleUserByName(userName).getActiveWidgetLayouts(), type);
+        Set<Map<String, String>> activeWidgetLayouts = gson.fromJson(userDAO.findUserByName(userName).getActiveWidgetLayouts(), type);
         if (activeWidgetLayouts != null) {
           for (Map<String, String> widgetLayoutId : activeWidgetLayouts) {
             layoutEntities.add(widgetLayoutDAO.findById(Long.parseLong(widgetLayoutId.get(ID))));

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
index 614f7ab..816767e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
@@ -51,7 +51,6 @@ import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
-import org.apache.ambari.server.security.authorization.UserType;
 import org.apache.ambari.server.security.authorization.Users;
 
 import com.google.common.cache.CacheBuilder;
@@ -187,14 +186,7 @@ public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
             @Override
             public UserEntity load(String key) throws Exception {
               //fallback mechanism, mostly for unit tests
-              UserEntity userEntity = userDAO.findLocalUserByName(key);
-              if (userEntity == null) {
-                userEntity = userDAO.findLdapUserByName(key);
-              }
-              if (userEntity == null) {
-                userEntity = userDAO.findUserByNameAndType(key, UserType.JWT);
-              }
-              return userEntity;
+              return userDAO.findUserByName(key);
             }
           };
 
@@ -281,9 +273,7 @@ public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
           Map<String, UserEntity> userNames = new TreeMap<>();
           for (UserEntity entity : userDAO.findAll()) {
             UserEntity existing = userNames.get(entity.getUserName());
-            if (existing == null ||
-                entity.getUserType() == UserType.LOCAL ||
-                existing.getUserType() == UserType.JWT) {
+            if (existing == null) {
               userNames.put(entity.getUserName(), entity);
             }
           }
@@ -292,10 +282,12 @@ public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
         }
 
         if (userEntity == null) {
-            userEntity = userDAO.findUserByNameAndType(userName, UserType.PAM);
+            userEntity = userDAO.findUserByName(userName);
         }
+
         if (userEntity == null) {
-          throw new SystemException("User " + userName + " was not found");
+          LOG.debug("User {} was not found", userName);
+          throw new SystemException("User was not found");
         }
 
         final Collection<PrivilegeEntity> privileges = users.getUserPrivileges(userEntity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java
index c5c36e9..45b733b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java
@@ -20,10 +20,12 @@ package org.apache.ambari.server.controller.internal;
 import java.util.Arrays;
 import java.util.EnumSet;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ObjectNotFoundException;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.UserRequest;
 import org.apache.ambari.server.controller.UserResponse;
@@ -39,8 +41,20 @@ import org.apache.ambari.server.controller.spi.ResourcePredicateEvaluator;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.entities.MemberEntity;
+import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
+import org.apache.ambari.server.security.authorization.Users;
+import org.apache.commons.lang.StringUtils;
+
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+import com.google.inject.assistedinject.AssistedInject;
 
 /**
  * Resource provider for user resources.
@@ -50,25 +64,31 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
   // ----- Property ID constants ---------------------------------------------
 
   // Users
-  public static final String USER_USERNAME_PROPERTY_ID     = PropertyHelper.getPropertyId("Users", "user_name");
-  public static final String USER_PASSWORD_PROPERTY_ID     = PropertyHelper.getPropertyId("Users", "password");
+  public static final String USER_USERNAME_PROPERTY_ID = PropertyHelper.getPropertyId("Users", "user_name");
+  public static final String USER_PASSWORD_PROPERTY_ID = PropertyHelper.getPropertyId("Users", "password");
   public static final String USER_OLD_PASSWORD_PROPERTY_ID = PropertyHelper.getPropertyId("Users", "old_password");
-  public static final String USER_LDAP_USER_PROPERTY_ID    = PropertyHelper.getPropertyId("Users", "ldap_user");
-  public static final String USER_TYPE_PROPERTY_ID         = PropertyHelper.getPropertyId("Users", "user_type");
-  public static final String USER_ACTIVE_PROPERTY_ID       = PropertyHelper.getPropertyId("Users", "active");
-  public static final String USER_GROUPS_PROPERTY_ID       = PropertyHelper.getPropertyId("Users", "groups");
-  public static final String USER_ADMIN_PROPERTY_ID        = PropertyHelper.getPropertyId("Users", "admin");
+  @Deprecated
+  public static final String USER_LDAP_USER_PROPERTY_ID = PropertyHelper.getPropertyId("Users", "ldap_user");
+  @Deprecated
+  public static final String USER_TYPE_PROPERTY_ID = PropertyHelper.getPropertyId("Users", "user_type");
+  public static final String USER_ACTIVE_PROPERTY_ID = PropertyHelper.getPropertyId("Users", "active");
+  public static final String USER_GROUPS_PROPERTY_ID = PropertyHelper.getPropertyId("Users", "groups");
+  public static final String USER_ADMIN_PROPERTY_ID = PropertyHelper.getPropertyId("Users", "admin");
 
   private static Set<String> pkPropertyIds =
-    new HashSet<>(Arrays.asList(new String[]{
-      USER_USERNAME_PROPERTY_ID}));
+      new HashSet<>(Arrays.asList(new String[]{
+          USER_USERNAME_PROPERTY_ID}));
+
+  @Inject
+  private Users users;
 
   /**
    * Create a new resource provider for the given management controller.
    */
-  UserResourceProvider(Set<String> propertyIds,
-                       Map<Resource.Type, String> keyPropertyIds,
-                       AmbariManagementController managementController) {
+  @AssistedInject
+  UserResourceProvider(@Assisted Set<String> propertyIds,
+                       @Assisted Map<Resource.Type, String> keyPropertyIds,
+                       @Assisted AmbariManagementController managementController) {
     super(propertyIds, keyPropertyIds, managementController);
 
     setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.AMBARI_MANAGE_USERS));
@@ -89,7 +109,7 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
     createResources(new Command<Void>() {
       @Override
       public Void invoke() throws AmbariException {
-        getManagementController().createUsers(requests);
+        createUsers(requests);
         return null;
       }
     });
@@ -114,7 +134,7 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
     Set<UserResponse> responses = getResources(new Command<Set<UserResponse>>() {
       @Override
       public Set<UserResponse> invoke() throws AmbariException, AuthorizationException {
-        return getManagementController().getUsers(requests);
+        return getUsers(requests);
       }
     });
 
@@ -122,8 +142,8 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
       LOG.debug("Found user responses matching get user request, userRequestSize={}, userResponseSize={}", requests.size(), responses.size());
     }
 
-    Set<String>   requestedIds = getRequestPropertyIds(request, predicate);
-    Set<Resource> resources    = new HashSet<>();
+    Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+    Set<Resource> resources = new HashSet<>();
 
     for (UserResponse userResponse : responses) {
       ResourceImpl resource = new ResourceImpl(Resource.Type.User);
@@ -131,11 +151,13 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
       setResourceProperty(resource, USER_USERNAME_PROPERTY_ID,
           userResponse.getUsername(), requestedIds);
 
+      // This is deprecated but here for backwards compatibility
       setResourceProperty(resource, USER_LDAP_USER_PROPERTY_ID,
           userResponse.isLdapUser(), requestedIds);
 
+      // This is deprecated but here for backwards compatibility
       setResourceProperty(resource, USER_TYPE_PROPERTY_ID,
-          userResponse.getUserType(), requestedIds);
+          userResponse.getAuthenticationType(), requestedIds);
 
       setResourceProperty(resource, USER_ACTIVE_PROPERTY_ID,
           userResponse.isActive(), requestedIds);
@@ -154,7 +176,7 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
 
   @Override
   public RequestStatus updateResources(Request request, Predicate predicate)
-    throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
     final Set<UserRequest> requests = new HashSet<>();
 
     for (Map<String, Object> propertyMap : getPropertyMaps(request.getProperties().iterator().next(), predicate)) {
@@ -166,7 +188,7 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
     modifyResources(new Command<Void>() {
       @Override
       public Void invoke() throws AmbariException, AuthorizationException {
-        getManagementController().updateUsers(requests);
+        updateUsers(requests);
         return null;
       }
     });
@@ -188,7 +210,7 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
     modifyResources(new Command<Void>() {
       @Override
       public Void invoke() throws AmbariException {
-        getManagementController().deleteUsers(requests);
+        deleteUsers(requests);
         return null;
       }
     });
@@ -201,15 +223,14 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
    * we do a case insensitive comparison so that we can return the retrieved
    * username when it differs only in case with respect to the requested username.
    *
-   * @param predicate  the predicate
-   * @param resource   the resource
-   *
-     * @return
-     */
+   * @param predicate the predicate
+   * @param resource  the resource
+   * @return
+   */
   @Override
   public boolean evaluate(Predicate predicate, Resource resource) {
     if (predicate instanceof EqualsPredicate) {
-      EqualsPredicate equalsPredicate = (EqualsPredicate)predicate;
+      EqualsPredicate equalsPredicate = (EqualsPredicate) predicate;
       String propertyId = equalsPredicate.getPropertyId();
       if (propertyId.equals(USER_USERNAME_PROPERTY_ID)) {
         return equalsPredicate.evaluateIgnoreCase(resource);
@@ -228,7 +249,7 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
       return new UserRequest(null);
     }
 
-    UserRequest request = new UserRequest ((String) properties.get(USER_USERNAME_PROPERTY_ID));
+    UserRequest request = new UserRequest((String) properties.get(USER_USERNAME_PROPERTY_ID));
 
     request.setPassword((String) properties.get(USER_PASSWORD_PROPERTY_ID));
     request.setOldPassword((String) properties.get(USER_OLD_PASSWORD_PROPERTY_ID));
@@ -243,4 +264,197 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp
 
     return request;
   }
+
+
+  /**
+   * Creates users.
+   *
+   * @param requests the request objects which define the user.
+   * @throws AmbariException when the user cannot be created.
+   */
+  private void createUsers(Set<UserRequest> requests) throws AmbariException {
+    for (UserRequest request : requests) {
+      String username = request.getUsername();
+      String password = request.getPassword();
+
+      if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
+        throw new AmbariException("Username and password must be supplied.");
+      }
+
+      String displayName = StringUtils.defaultIfEmpty(request.getDisplayName(), username);
+      String localUserName = StringUtils.defaultIfEmpty(request.getLocalUserName(), username);
+
+      UserEntity userEntity = users.createUser(username, localUserName, displayName, request.isActive());
+      if (userEntity != null) {
+        users.addLocalAuthentication(userEntity, password);
+
+        if (Boolean.TRUE.equals(request.isAdmin())) {
+          users.grantAdminPrivilege(userEntity);
+        }
+      }
+    }
+  }
+
+  /**
+   * Updates the users specified.
+   *
+   * @param requests the users to modify
+   * @throws AmbariException          if the resources cannot be updated
+   * @throws IllegalArgumentException if the authenticated user is not authorized to update all of
+   *                                  the requested properties
+   */
+  private void updateUsers(Set<UserRequest> requests) throws AmbariException, AuthorizationException {
+    boolean isUserAdministrator = AuthorizationHelper.isAuthorized(ResourceType.AMBARI, null,
+        RoleAuthorization.AMBARI_MANAGE_USERS);
+    String authenticatedUsername = AuthorizationHelper.getAuthenticatedName();
+
+    for (UserRequest request : requests) {
+      String requestedUsername = request.getUsername();
+
+      // An administrator can modify any user, else a user can only modify themself.
+      if (!isUserAdministrator && (!authenticatedUsername.equalsIgnoreCase(requestedUsername))) {
+        throw new AuthorizationException();
+      }
+
+      UserEntity userEntity = users.getUserEntity(requestedUsername);
+      if (null == userEntity) {
+        continue;
+      }
+
+      if (null != request.isActive()) {
+        // If this value is being set, make sure the authenticated user is an administrator before
+        // allowing to change it. Only administrators should be able to change a user's active state
+        if (!isUserAdministrator) {
+          throw new AuthorizationException("The authenticated user is not authorized to update the requested resource property");
+        }
+        users.setUserActive(userEntity, request.isActive());
+      }
+
+      if (null != request.isAdmin()) {
+        // If this value is being set, make sure the authenticated user is an administrator before
+        // allowing to change it. Only administrators should be able to change a user's administrative
+        // privileges
+        if (!isUserAdministrator) {
+          throw new AuthorizationException("The authenticated user is not authorized to update the requested resource property");
+        }
+
+        if (request.isAdmin()) {
+          users.grantAdminPrivilege(userEntity);
+        } else {
+          users.revokeAdminPrivilege(userEntity);
+        }
+      }
+
+      if (null != request.getOldPassword() && null != request.getPassword()) {
+        users.modifyPassword(userEntity, request.getOldPassword(), request.getPassword());
+      }
+    }
+  }
+
+  /**
+   * Deletes the users specified.
+   *
+   * @param requests the users to delete
+   * @throws AmbariException if the resources cannot be deleted
+   */
+  private void deleteUsers(Set<UserRequest> requests)
+      throws AmbariException {
+
+    for (UserRequest r : requests) {
+      String username = r.getUsername();
+      if (!StringUtils.isEmpty(username)) {
+
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Received a delete user request, username= {}", username);
+        }
+
+        users.removeUser(users.getUserEntity(username));
+      }
+    }
+  }
+
+  /**
+   * Gets the users identified by the given request objects.
+   *
+   * @param requests the request objects
+   * @return a set of user responses
+   * @throws AmbariException if the users could not be read
+   */
+  private Set<UserResponse> getUsers(Set<UserRequest> requests)
+      throws AmbariException, AuthorizationException {
+
+    Set<UserResponse> responses = new HashSet<>();
+
+    for (UserRequest r : requests) {
+
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Received a getUsers request, userRequest={}", r.toString());
+      }
+
+      String requestedUsername = r.getUsername();
+      String authenticatedUsername = AuthorizationHelper.getAuthenticatedName();
+
+      // A user resource may be retrieved by an administrator or the same user.
+      if (!AuthorizationHelper.isAuthorized(ResourceType.AMBARI, null, RoleAuthorization.AMBARI_MANAGE_USERS)) {
+        if (null == requestedUsername) {
+          // Since the authenticated user is not the administrator, force only that user's resource
+          // to be returned
+          requestedUsername = authenticatedUsername;
+        } else if (!requestedUsername.equalsIgnoreCase(authenticatedUsername)) {
+          // Since the authenticated user is not the administrator and is asking for a different user,
+          // throw an AuthorizationException
+          throw new AuthorizationException();
+        }
+      }
+
+      // get them all
+      if (null == requestedUsername) {
+        for (UserEntity u : users.getAllUserEntities()) {
+          responses.add(createUserResponse(u));
+        }
+      } else {
+
+        UserEntity u = users.getUserEntity(requestedUsername);
+        if (null == u) {
+          if (requests.size() == 1) {
+            // only throw exceptin if there is a single request
+            // if there are multiple requests, this indicates an OR predicate
+            throw new ObjectNotFoundException("Cannot find user '"
+                + requestedUsername + "'");
+          }
+        } else {
+          responses.add(createUserResponse(u));
+        }
+      }
+    }
+
+    return responses;
+  }
+
+  private UserResponse createUserResponse(UserEntity userEntity) {
+    List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+    boolean isLdapUser = false;
+    UserAuthenticationType userType = UserAuthenticationType.LOCAL;
+
+      for (UserAuthenticationEntity authenticationEntity : authenticationEntities) {
+        if (authenticationEntity.getAuthenticationType() == UserAuthenticationType.LDAP) {
+          isLdapUser = true;
+          userType = UserAuthenticationType.LDAP;
+        } else if (authenticationEntity.getAuthenticationType() == UserAuthenticationType.PAM) {
+          userType = UserAuthenticationType.PAM;
+        }
+    }
+
+    Set<String> groups = new HashSet<>();
+    for (MemberEntity memberEntity : userEntity.getMemberEntities()) {
+      groups.add(memberEntity.getGroup().getGroupName());
+    }
+
+    boolean isAdmin = users.hasAdminPrivilege(userEntity);
+
+    UserResponse userResponse = new UserResponse(userEntity.getUserName(), userType, isLdapUser, userEntity.getActive(), isAdmin);
+    userResponse.setGroups(groups);
+    return userResponse;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserAuthenticationDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserAuthenticationDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserAuthenticationDAO.java
new file mode 100644
index 0000000..5ecff52
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserAuthenticationDAO.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.orm.dao;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+
+@Singleton
+public class UserAuthenticationDAO {
+
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+  @Inject
+  DaoUtils daoUtils;
+
+  @RequiresSession
+  public UserAuthenticationEntity findByPK(Long pk) {
+    return entityManagerProvider.get().find(UserAuthenticationEntity.class, pk);
+  }
+
+  @RequiresSession
+  public List<UserAuthenticationEntity> findAll() {
+    TypedQuery<UserAuthenticationEntity> query = entityManagerProvider.get().createNamedQuery("UserAuthenticationEntity.findAll", UserAuthenticationEntity.class);
+    return daoUtils.selectList(query);
+  }
+
+  @Transactional
+  public void create(UserAuthenticationEntity entity) {
+    entityManagerProvider.get().persist(entity);
+  }
+
+  @Transactional
+  public void create(Set<UserAuthenticationEntity> entities) {
+    for (UserAuthenticationEntity entity : entities) {
+      entityManagerProvider.get().persist(entity);
+    }
+  }
+
+  @Transactional
+  public UserAuthenticationEntity merge(UserAuthenticationEntity entity) {
+    return entityManagerProvider.get().merge(entity);
+  }
+
+  @Transactional
+  public void merge(Set<UserAuthenticationEntity> entities) {
+    for (UserAuthenticationEntity entity : entities) {
+      entityManagerProvider.get().merge(entity);
+    }
+  }
+
+  @Transactional
+  public void remove(UserAuthenticationEntity entity) {
+    entityManagerProvider.get().remove(entity);
+  }
+
+  @Transactional
+  public void remove(Set<UserAuthenticationEntity> entities) {
+    for (UserAuthenticationEntity entity : entities) {
+      entityManagerProvider.get().remove(entity);
+    }
+  }
+
+  @Transactional
+  public void removeByPK(Long pk) {
+    remove(findByPK(pk));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
index ce47c4c..0e28e50 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
@@ -17,13 +17,11 @@
  */
 package org.apache.ambari.server.orm.dao;
 
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-import javax.annotation.Nullable;
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
@@ -31,9 +29,7 @@ import javax.persistence.TypedQuery;
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.PrincipalEntity;
 import org.apache.ambari.server.orm.entities.UserEntity;
-import org.apache.ambari.server.security.authorization.UserType;
 
-import com.google.common.collect.ImmutableMap;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -58,12 +54,7 @@ public class UserDAO {
     return daoUtils.selectList(query);
   }
 
-  /**
-   * Results in Exception if two users with same name but different types present in DB
-   * As such situation is valid, use {@link #findUserByNameAndType(String, UserType)} instead
-   */
   @RequiresSession
-  @Deprecated
   public UserEntity findUserByName(String userName) {
     TypedQuery<UserEntity> query = entityManagerProvider.get().createNamedQuery("userByName", UserEntity.class);
     query.setParameter("username", userName.toLowerCase());
@@ -75,81 +66,9 @@ public class UserDAO {
   }
 
   /**
-   * <p>Finds user by name. If duplicate users exists (with different type), the returned one will be chosen by this user
-   * type precedence: LOCAL -> LDAP -> JWT -> PAM</p>
-   * <p>In Ambari 3.0, user management will be rethought hence the deprecation</p>
-   * @param userName the user name
-   * @return The corresponding user or {@code null} if none is found. If multiple users exist with different types, user
-   *   type precedence (see above) will decide.
-   */
-   @RequiresSession
-   @Deprecated
-   @Nullable
-   public UserEntity findSingleUserByName(String userName) {
-     TypedQuery<UserEntity> query = entityManagerProvider.get().createNamedQuery("userByName", UserEntity.class);
-     query.setParameter("username", userName.toLowerCase());
-     List<UserEntity> resultList = query.getResultList();
-     switch (resultList.size()) {
-       case 0:
-         return null;
-       case 1:
-         return resultList.get(0);
-       default:
-         ImmutableMap.Builder<UserType, UserEntity> mapBuilder = ImmutableMap.builder();
-         for (UserEntity user: resultList) {
-           mapBuilder.put(user.getUserType(), user);
-         }
-         ImmutableMap<UserType, UserEntity> usersByType = mapBuilder.build();
-         UserEntity user =
-             usersByType.containsKey(UserType.LOCAL) ? usersByType.get(UserType.LOCAL) :
-                 usersByType.containsKey(UserType.LOCAL.LDAP) ? usersByType.get(UserType.LDAP) :
-                     usersByType.containsKey(UserType.JWT) ? usersByType.get(UserType.JWT) :
-                         usersByType.get(UserType.PAM);
-         return user;
-     }
-   }
-
-
-  @RequiresSession
-  public UserEntity findUserByNameAndType(String userName, UserType userType) {
-    TypedQuery<UserEntity> query = entityManagerProvider.get().createQuery("SELECT user FROM UserEntity user WHERE " +
-        "user.userType=:type AND lower(user.userName)=lower(:name)", UserEntity.class); // do case insensitive compare
-    query.setParameter("type", userType);
-    query.setParameter("name", userName);
-    try {
-      return query.getSingleResult();
-    } catch (NoResultException e) {
-      return null;
-    }
-  }
-
-  @RequiresSession
-  public UserEntity findLocalUserByName(String userName) {
-    TypedQuery<UserEntity> query = entityManagerProvider.get().createNamedQuery("localUserByName", UserEntity.class);
-    query.setParameter("username", userName.toLowerCase());
-    try {
-      return query.getSingleResult();
-    } catch (NoResultException e) {
-      return null;
-    }
-  }
-
-  @RequiresSession
-  public UserEntity findLdapUserByName(String userName) {
-    TypedQuery<UserEntity> query = entityManagerProvider.get().createNamedQuery("ldapUserByName", UserEntity.class);
-    query.setParameter("username", userName.toLowerCase());
-    try {
-      return query.getSingleResult();
-    } catch (NoResultException e) {
-      return null;
-    }
-  }
-
-  /**
    * Find the user entities for the given list of admin principal entities.
    *
-   * @param principalList  the list of principal entities
-   *
+   * @param principalList the list of principal entities
    * @return the matching list of user entities
    */
   @RequiresSession
@@ -166,7 +85,6 @@ public class UserDAO {
    * Find the user entity for the given admin principal entity.
    *
    * @param principal the principal entity
-   *
    * @return the matching user entity
    */
   @RequiresSession
@@ -182,27 +100,24 @@ public class UserDAO {
 
   @Transactional
   public void create(UserEntity user) {
-    create(new HashSet<>(Arrays.asList(user)));
+    create(new HashSet<>(Collections.singleton(user)));
   }
 
   @Transactional
   public void create(Set<UserEntity> users) {
     for (UserEntity user: users) {
-//      user.setUserName(user.getUserName().toLowerCase());
       entityManagerProvider.get().persist(user);
     }
   }
 
   @Transactional
   public UserEntity merge(UserEntity user) {
-//    user.setUserName(user.getUserName().toLowerCase());
     return entityManagerProvider.get().merge(user);
   }
 
   @Transactional
   public void merge(Set<UserEntity> users) {
-    for (UserEntity user: users) {
-//      user.setUserName(user.getUserName().toLowerCase());
+    for (UserEntity user : users) {
       entityManagerProvider.get().merge(user);
     }
   }
@@ -215,7 +130,7 @@ public class UserDAO {
 
   @Transactional
   public void remove(Set<UserEntity> users) {
-    for (UserEntity userEntity: users) {
+    for (UserEntity userEntity : users) {
       entityManagerProvider.get().remove(entityManagerProvider.get().merge(userEntity));
     }
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java
new file mode 100644
index 0000000..ffb8e6d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.orm.entities;
+
+import java.util.Date;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+@Table(name = "user_authentication")
+@Entity
+@NamedQueries({
+    @NamedQuery(name = "UserAuthenticationEntity.findAll", query = "SELECT entity FROM UserAuthenticationEntity entity")
+})
+@TableGenerator(name = "user_authentication_id_generator",
+    table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"
+    , pkColumnValue = "user_authentication_id_seq"
+    , initialValue = 2
+    , allocationSize = 500
+)
+public class UserAuthenticationEntity {
+
+  @Id
+  @Column(name = "user_authentication_id")
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "user_authentication_id_generator")
+  private Long userAuthenticationId;
+
+  @Column(name = "authentication_type", nullable = false)
+  @Enumerated(EnumType.STRING)
+  @Basic
+  private UserAuthenticationType authenticationType = UserAuthenticationType.LOCAL;
+
+  @Column(name = "authentication_key")
+  @Lob
+  @Basic
+  private byte[] authenticationKey;
+
+  @Column(name = "create_time", nullable = false)
+  @Basic
+  @Temporal(value = TemporalType.TIMESTAMP)
+  private Date createTime = new Date();
+
+  @Column(name = "update_time", nullable = false)
+  @Basic
+  @Temporal(value = TemporalType.TIMESTAMP)
+  private Date updateTime = new Date();
+
+  @ManyToOne(fetch = FetchType.LAZY)
+  @JoinColumn(name = "user_id", referencedColumnName = "user_id", nullable = false)
+  private UserEntity user;
+
+  public Long getUserAuthenticationId() {
+    return userAuthenticationId;
+  }
+
+  public void setUserAuthenticationId(Long userAuthenticationId) {
+    this.userAuthenticationId = userAuthenticationId;
+  }
+
+  public UserAuthenticationType getAuthenticationType() {
+    return authenticationType;
+  }
+
+  public void setAuthenticationType(UserAuthenticationType authenticationType) {
+    this.authenticationType = authenticationType;
+  }
+
+  public String getAuthenticationKey() {
+    return authenticationKey == null ? "" : new String(authenticationKey);
+  }
+
+  public void setAuthenticationKey(String authenticationKey) {
+    this.authenticationKey = (authenticationKey == null) ? null : authenticationKey.getBytes();
+  }
+
+  public Date getCreateTime() {
+    return createTime;
+  }
+
+  public Date getUpdateTime() {
+    return updateTime;
+  }
+
+  /**
+   * Get the relevant {@link UserEntity} associated with this {@link UserAuthenticationEntity}.
+   *
+   * @return a {@link UserEntity}
+   */
+  public UserEntity getUser() {
+    return user;
+  }
+
+  /**
+   * Set the relevant {@link UserEntity} associated with this {@link UserAuthenticationEntity}.
+   *
+   * @param user a {@link UserEntity}
+   */
+  public void setUser(UserEntity user) {
+    this.user = user;
+  }
+
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    } else if (o == null || getClass() != o.getClass()) {
+      return false;
+    } else {
+      UserAuthenticationEntity that = (UserAuthenticationEntity) o;
+
+      EqualsBuilder equalsBuilder = new EqualsBuilder();
+      equalsBuilder.append(userAuthenticationId, that.userAuthenticationId);
+      equalsBuilder.append(authenticationType, that.authenticationType);
+      equalsBuilder.append(authenticationKey, that.authenticationKey);
+      equalsBuilder.append(createTime, that.createTime);
+      equalsBuilder.append(updateTime, that.updateTime);
+      return equalsBuilder.isEquals();
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
+    hashCodeBuilder.append(userAuthenticationId);
+    hashCodeBuilder.append(authenticationType);
+    hashCodeBuilder.append(authenticationKey);
+    hashCodeBuilder.append(createTime);
+    hashCodeBuilder.append(updateTime);
+    return hashCodeBuilder.toHashCode();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
index 9011eae..66e9003 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
@@ -17,16 +17,17 @@
  */
 package org.apache.ambari.server.orm.entities;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 import javax.persistence.Basic;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
@@ -42,27 +43,21 @@ import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
 import javax.persistence.UniqueConstraint;
 
-import org.apache.ambari.server.security.authorization.UserName;
-import org.apache.ambari.server.security.authorization.UserType;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
 
-@Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_name", "user_type"})})
+@Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_name"})})
 @Entity
 @NamedQueries({
     @NamedQuery(name = "userByName", query = "SELECT user_entity from UserEntity user_entity " +
-        "where lower(user_entity.userName)=:username"),
-    @NamedQuery(name = "localUserByName", query = "SELECT user_entity FROM UserEntity user_entity " +
-        "where lower(user_entity.userName)=:username AND " +
-        "user_entity.userType=org.apache.ambari.server.security.authorization.UserType.LOCAL"),
-    @NamedQuery(name = "ldapUserByName", query = "SELECT user_entity FROM UserEntity user_entity " +
-        "where lower(user_entity.userName)=:username AND " +
-        "user_entity.userType=org.apache.ambari.server.security.authorization.UserType.LDAP")
+        "where lower(user_entity.userName)=lower(:username)")
 })
 @TableGenerator(name = "user_id_generator",
     table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"
     , pkColumnValue = "user_id_seq"
     , initialValue = 2
     , allocationSize = 500
-    )
+)
 public class UserEntity {
 
   @Id
@@ -70,40 +65,41 @@ public class UserEntity {
   @GeneratedValue(strategy = GenerationType.TABLE, generator = "user_id_generator")
   private Integer userId;
 
-  @Column(name = "user_name")
+  @Column(name = "user_name", nullable = false)
   private String userName;
 
-  @Column(name = "ldap_user")
-  private Integer ldapUser = 0;
-
-  @Column(name = "user_type")
-  @Enumerated(EnumType.STRING)
-  @Basic
-  private UserType userType = UserType.LOCAL;
-
-  @Column(name = "user_password")
-  @Basic
-  private String userPassword;
-
-  @Column(name = "create_time")
+  @Column(name = "create_time", nullable = false)
   @Basic
   @Temporal(value = TemporalType.TIMESTAMP)
   private Date createTime = new Date();
 
-  @Column(name = "active")
+  @Column(name = "active", nullable = false)
   private Integer active = 1;
 
+  @Column(name = "consecutive_failures", nullable = false)
+  private Integer consecutiveFailures = 0;
+
+  @Column(name = "display_name")
+  private String displayName;
+
+  @Column(name = "local_username")
+  private String localUsername;
+
   @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
   private Set<MemberEntity> memberEntities = new HashSet<>();
 
   @OneToOne
   @JoinColumns({
-      @JoinColumn(name = "principal_id", referencedColumnName = "principal_id", nullable = false),
+      @JoinColumn(name = "principal_id", referencedColumnName = "principal_id", nullable = false)
   })
   private PrincipalEntity principal;
 
   @Column(name = "active_widget_layouts")
   private String activeWidgetLayouts;
+
+  @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+  private List<UserAuthenticationEntity> authenticationEntities = new ArrayList<>();
+
   // ----- UserEntity --------------------------------------------------------
 
   public Integer getUserId() {
@@ -118,37 +114,96 @@ public class UserEntity {
     return userName;
   }
 
-  public void setUserName(UserName userName) {
-    this.userName = userName.toString();
+  public void setUserName(String userName) {
+    // Force the username to be lowercase
+    this.userName = (userName == null) ? null : userName.toLowerCase();
+  }
+
+  /**
+   * Returns the number of consecutive authentication failures since the last successful login.
+   * <p>
+   * This value may be used to throttle authentication attempts or lock out users. It is expected that
+   * this value is reset to <code>0</code> when a successful authentication attempt was made.
+   *
+   * @return the number of consecutive authentication failures since the last successful login
+   */
+  public Integer getConsecutiveFailures() {
+    return consecutiveFailures;
   }
 
-  public Boolean getLdapUser() {
-    return ldapUser == 0 ? Boolean.FALSE : Boolean.TRUE;
+  /**
+   * Sets the number of consecutive authentication failures since the last successful login.
+   * <p>
+   * This value may be used to throttle authentication attempts or lock out users. It is expected that
+   * this value is reset to <code>0</code> when a successful authentication attempt was made.
+   * <p>
+   * For each failed authentication attempt, {@link #incrementConsecutiveFailures()} should be called
+   * rather than explicitly setting an incremented value.
+   *
+   * @param consecutiveFailures a number of consecutive authentication failures since the last successful login
+   */
+  public void setConsecutiveFailures(Integer consecutiveFailures) {
+    this.consecutiveFailures = consecutiveFailures;
   }
 
-  public void setLdapUser(Boolean ldapUser) {
-    if (ldapUser == null) {
-      this.ldapUser = null;
-    } else {
-      this.ldapUser = ldapUser ? 1 : 0;
-      this.userType = ldapUser ? UserType.LDAP : UserType.LOCAL;
-    }
+  /**
+   * Increments the number of consecutive authentication failures since the last successful login.
+   * <p>
+   * This value may be used to throttle authentication attempts or lock out users. It is expected that
+   * this value is reset to <code>0</code> when a successful authentication attempt was made.
+   * <p>
+   * TODO: Ensure that this value is consistent when updating concurrently
+   */
+  public void incrementConsecutiveFailures() {
+    this.consecutiveFailures++;
   }
 
-  public UserType getUserType() {
-    return userType;
+  /**
+   * Returns the display name for this user.
+   * <p>
+   * This value may be used in user interfaces rather than the username to show who it logged in. If
+   * empty, it is expected that the user's {@link #userName} value would be used instead.
+   *
+   * @return the user's display name
+   */
+  public String getDisplayName() {
+    return displayName;
   }
 
-  public void setUserType(UserType userType) {
-    this.userType = userType;
+  /**
+   * Sets the display name for this user.
+   * <p>
+   * This value may be used in user interfaces rather than the username to show who it logged in. If
+   * empty, it is expected that the user's {@link #userName} value would be used instead.
+   *
+   * @param displayName the user's display name
+   */
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
   }
 
-  public String getUserPassword() {
-    return userPassword;
+  /**
+   * Gets the local username for this user.
+   * <p>
+   * This value is intended to be used when accessing services via Ambari Views. If
+   * empty, it is expected that the user's {@link #userName} value would be used instead.
+   *
+   * @return the user's local username
+   */
+  public String getLocalUsername() {
+    return localUsername;
   }
 
-  public void setUserPassword(String userPassword) {
-    this.userPassword = userPassword;
+  /**
+   * Sets the local username for this user.
+   * <p>
+   * This value is intended to be used when accessing services via Ambari Views. If
+   * empty, it is expected that the user's {@link #userName} value would be used instead.
+   *
+   * @param localUsername the user's local username
+   */
+  public void setLocalUsername(String localUsername) {
+    this.localUsername = localUsername;
   }
 
   public Date getCreateTime() {
@@ -191,7 +246,7 @@ public class UserEntity {
   /**
    * Set the admin principal entity.
    *
-   * @param principal  the principal entity
+   * @param principal the principal entity
    */
   public void setPrincipal(PrincipalEntity principal) {
     this.principal = principal;
@@ -205,35 +260,57 @@ public class UserEntity {
     this.activeWidgetLayouts = activeWidgetLayouts;
   }
 
-// ----- Object overrides --------------------------------------------------
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
+  public List<UserAuthenticationEntity> getAuthenticationEntities() {
+    return authenticationEntities;
+  }
 
-    UserEntity that = (UserEntity) o;
+  public void setAuthenticationEntities(List<UserAuthenticationEntity> authenticationEntities) {
+    // If the passed in value is not the same list that is stored internally, clear it and set the
+    // entries to the same set that the user passed in.
+    // If the passed in value is the same list, then do nothing since the internal value is already
+    // set.
+    if (this.authenticationEntities != authenticationEntities) {  // Tests to see if the Lists are the same object, not if they have the same content.
+      this.authenticationEntities.clear();
+
+      if (authenticationEntities != null) {
+        this.authenticationEntities.addAll(authenticationEntities);
+      }
+    }
+  }
 
-    if (userId != null ? !userId.equals(that.userId) : that.userId != null) return false;
-    if (createTime != null ? !createTime.equals(that.createTime) : that.createTime != null) return false;
-    if (ldapUser != null ? !ldapUser.equals(that.ldapUser) : that.ldapUser != null) return false;
-    if (userType != null ? !userType.equals(that.userType) : that.userType != null) return false;
-    if (userName != null ? !userName.equals(that.userName) : that.userName != null) return false;
-    if (userPassword != null ? !userPassword.equals(that.userPassword) : that.userPassword != null) return false;
-    if (active != null ? !active.equals(that.active) : that.active != null) return false;
+  // ----- Object overrides --------------------------------------------------
 
-    return true;
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    } else if (o == null || getClass() != o.getClass()) {
+      return false;
+    } else {
+      UserEntity that = (UserEntity) o;
+
+      EqualsBuilder equalsBuilder = new EqualsBuilder();
+      equalsBuilder.append(userId, that.userId);
+      equalsBuilder.append(userName, that.userName);
+      equalsBuilder.append(displayName, that.displayName);
+      equalsBuilder.append(localUsername, that.localUsername);
+      equalsBuilder.append(consecutiveFailures, that.consecutiveFailures);
+      equalsBuilder.append(active, that.active);
+      equalsBuilder.append(createTime, that.createTime);
+      return equalsBuilder.isEquals();
+    }
   }
 
   @Override
   public int hashCode() {
-    int result = userId != null ? userId.hashCode() : 0;
-    result = 31 * result + (userName != null ? userName.hashCode() : 0);
-    result = 31 * result + (userPassword != null ? userPassword.hashCode() : 0);
-    result = 31 * result + (ldapUser != null ? ldapUser.hashCode() : 0);
-    result = 31 * result + (userType != null ? userType.hashCode() : 0);
-    result = 31 * result + (createTime != null ? createTime.hashCode() : 0);
-    result = 31 * result + (active != null ? active.hashCode() : 0);
-    return result;
+    HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
+    hashCodeBuilder.append(userId);
+    hashCodeBuilder.append(userName);
+    hashCodeBuilder.append(displayName);
+    hashCodeBuilder.append(localUsername);
+    hashCodeBuilder.append(consecutiveFailures);
+    hashCodeBuilder.append(active);
+    hashCodeBuilder.append(createTime);
+    return hashCodeBuilder.toHashCode();
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariJWTAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariJWTAuthenticationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariJWTAuthenticationFilter.java
index 195c55a..fca8b29 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariJWTAuthenticationFilter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariJWTAuthenticationFilter.java
@@ -34,7 +34,6 @@ import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.security.authorization.PermissionHelper;
 import org.apache.ambari.server.security.authorization.Users;
-import org.apache.ambari.server.security.authorization.jwt.AuthenticationJwtUserNotFoundException;
 import org.apache.ambari.server.security.authorization.jwt.JwtAuthenticationFilter;
 import org.apache.ambari.server.utils.RequestUtils;
 import org.springframework.security.core.Authentication;
@@ -124,8 +123,8 @@ public class AmbariJWTAuthenticationFilter extends JwtAuthenticationFilter imple
   protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
     if (auditLogger.isEnabled()) {
       String username = null;
-      if (authException instanceof AuthenticationJwtUserNotFoundException) {
-        username = ((AuthenticationJwtUserNotFoundException) authException).getUsername();
+      if (authException instanceof UserNotFoundException) {
+        username = ((UserNotFoundException) authException).getUsername();
       }
 
       AuditEvent loginFailedAuditEvent = LoginAuditEvent.builder()

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AuthenticationMethodNotAllowedException.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AuthenticationMethodNotAllowedException.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AuthenticationMethodNotAllowedException.java
new file mode 100644
index 0000000..4c48dd7
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AuthenticationMethodNotAllowedException.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.security.authentication;
+
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
+import org.springframework.security.core.AuthenticationException;
+
+/**
+ * AuthenticationMethodNotAllowedException is an AuthenticationException implementation to be thrown
+ * when the specified authentication method is not allowed for the relevant user.
+ */
+public class AuthenticationMethodNotAllowedException extends AuthenticationException {
+  private final String username;
+  private final UserAuthenticationType userAuthenticationType;
+
+  public AuthenticationMethodNotAllowedException(String username, UserAuthenticationType authenticationType) {
+    this(username, authenticationType, createDefaultMessage(username, authenticationType));
+  }
+
+  public AuthenticationMethodNotAllowedException(String username, UserAuthenticationType authenticationType, Throwable cause) {
+    this(username, authenticationType, createDefaultMessage(username, authenticationType), cause);
+  }
+
+  public AuthenticationMethodNotAllowedException(String username, UserAuthenticationType authenticationType, String message) {
+    super(message);
+    this.username = username;
+    this.userAuthenticationType = authenticationType;
+  }
+
+  public AuthenticationMethodNotAllowedException(String username, UserAuthenticationType authenticationType, String message, Throwable cause) {
+    super(message, cause);
+    this.username = username;
+    this.userAuthenticationType = authenticationType;
+  }
+
+  public String getUsername() {
+    return username;
+  }
+
+  public UserAuthenticationType getUserAuthenticationType() {
+    return userAuthenticationType;
+  }
+
+  private static String createDefaultMessage(String username, UserAuthenticationType authenticationType) {
+    return String.format("%s is not authorized to authenticate using %s",
+        username,
+        (authenticationType == null) ? "null" : authenticationType.name());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/UserNotFoundException.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/UserNotFoundException.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/UserNotFoundException.java
new file mode 100644
index 0000000..f6c4bcf
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/UserNotFoundException.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.security.authentication;
+
+import org.springframework.security.core.AuthenticationException;
+
+/**
+ * AuthenticationUserNotFoundException is an AuthenticationException implementation to be thrown
+ * when the user specified in an authentication attempt is not found in the Ambari user database.
+ */
+public class UserNotFoundException extends AuthenticationException {
+  private final String username;
+
+  public UserNotFoundException(String username, String message) {
+    super(message);
+    this.username = username;
+  }
+
+  public UserNotFoundException(String username, String message, Throwable throwable) {
+    super(message, throwable);
+    this.username = username;
+  }
+
+  public String getUsername() {
+    return username;
+  }
+}