http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java
index 9c2cad5..02a5e75 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java
@@ -16,38 +16,33 @@
  */
 package org.apache.nifi.authorization;
 
-import java.io.File;
 import java.io.IOException;
-import java.util.Collection;
+import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import javax.xml.XMLConstants;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
 import org.apache.nifi.authorization.annotation.AuthorityProviderContext;
 import org.apache.nifi.authorization.exception.AuthorityAccessException;
 import org.apache.nifi.authorization.exception.IdentityAlreadyExistsException;
 import org.apache.nifi.authorization.exception.ProviderCreationException;
 import org.apache.nifi.authorization.exception.UnknownIdentityException;
-import org.apache.nifi.util.file.FileUtils;
 import org.apache.nifi.user.generated.ObjectFactory;
 import org.apache.nifi.user.generated.Role;
 import org.apache.nifi.user.generated.User;
-import org.apache.nifi.user.generated.Users;
 import org.apache.nifi.util.NiFiProperties;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.authorized.users.AuthorizedUsers;
+import org.apache.nifi.authorized.users.AuthorizedUsers.CreateUser;
+import org.apache.nifi.authorized.users.AuthorizedUsers.FindUser;
+import org.apache.nifi.authorized.users.AuthorizedUsers.FindUsers;
+import org.apache.nifi.authorized.users.AuthorizedUsers.HasUser;
+import org.apache.nifi.authorized.users.AuthorizedUsers.UpdateUser;
+import org.apache.nifi.authorized.users.AuthorizedUsers.UpdateUsers;
+import org.apache.nifi.user.generated.NiFiUser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.xml.sax.SAXException;
 
 /**
  * Provides identity checks and grants authorities.
@@ -55,84 +50,26 @@ import org.xml.sax.SAXException;
 public class FileAuthorizationProvider implements AuthorityProvider {
 
     private static final Logger logger = 
LoggerFactory.getLogger(FileAuthorizationProvider.class);
-    private static final String USERS_XSD = "/users.xsd";
-    private static final String JAXB_GENERATED_PATH = 
"org.apache.nifi.user.generated";
-    private static final JAXBContext JAXB_CONTEXT = initializeJaxbContext();
-
-    /**
-     * Load the JAXBContext.
-     */
-    private static JAXBContext initializeJaxbContext() {
-        try {
-            return JAXBContext.newInstance(JAXB_GENERATED_PATH, 
FileAuthorizationProvider.class.getClassLoader());
-        } catch (JAXBException e) {
-            throw new RuntimeException("Unable to create JAXBContext.");
-        }
-    }
 
     private NiFiProperties properties;
-    private File usersFile;
-    private File restoreUsersFile;
-    private Users users;
     private final Set<String> defaultAuthorities = new HashSet<>();
 
+    private AuthorizedUsers authorizedUsers;
+
     @Override
     public void initialize(final AuthorityProviderInitializationContext 
initializationContext) throws ProviderCreationException {
     }
 
     @Override
     public void onConfigured(final AuthorityProviderConfigurationContext 
configurationContext) throws ProviderCreationException {
-        try {
-            final String usersFilePath = 
configurationContext.getProperty("Authorized Users File");
-            if (usersFilePath == null || usersFilePath.trim().isEmpty()) {
-                throw new ProviderCreationException("The authorized users file 
must be specified.");
-            }
-
-            // the users file instance will never be null because a default is 
used
-            usersFile = new File(usersFilePath);
-            final File usersFileDirectory = usersFile.getParentFile();
-
-            // the restore directory is optional and may be null
-            final File restoreDirectory = properties.getRestoreDirectory();
-
-            if (restoreDirectory != null) {
-
-                // sanity check that restore directory is a directory, 
creating it if necessary
-                FileUtils.ensureDirectoryExistAndCanAccess(restoreDirectory);
-
-                // check that restore directory is not the same as the primary 
directory
-                if 
(usersFileDirectory.getAbsolutePath().equals(restoreDirectory.getAbsolutePath()))
 {
-                    throw new 
ProviderCreationException(String.format("Authorized User's directory '%s' is 
the same as restore directory '%s' ",
-                            usersFileDirectory.getAbsolutePath(), 
restoreDirectory.getAbsolutePath()));
-                }
-
-                // the restore copy will have same file name, but reside in a 
different directory
-                restoreUsersFile = new File(restoreDirectory, 
usersFile.getName());
-
-                // sync the primary copy with the restore copy
-                try {
-                    FileUtils.syncWithRestore(usersFile, restoreUsersFile, 
logger);
-                } catch (final IOException | IllegalStateException ioe) {
-                    throw new ProviderCreationException(ioe);
-                }
-
-            }
+        final String usersFilePath = 
configurationContext.getProperty("Authorized Users File");
+        if (usersFilePath == null || usersFilePath.trim().isEmpty()) {
+            throw new ProviderCreationException("The authorized users file 
must be specified.");
+        }
 
-            // load the users from the specified file
-            if (usersFile.exists()) {
-                // find the schema
-                final SchemaFactory schemaFactory = 
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-                final Schema schema = 
schemaFactory.newSchema(FileAuthorizationProvider.class.getResource(USERS_XSD));
-
-                // attempt to unmarshal
-                final Unmarshaller unmarshaller = 
JAXB_CONTEXT.createUnmarshaller();
-                unmarshaller.setSchema(schema);
-                final JAXBElement<Users> element = unmarshaller.unmarshal(new 
StreamSource(usersFile), Users.class);
-                users = element.getValue();
-            } else {
-                final ObjectFactory objFactory = new ObjectFactory();
-                users = objFactory.createUsers();
-            }
+        try {
+            // initialize the authorized users
+            authorizedUsers = AuthorizedUsers.getInstance(usersFilePath, 
properties);
 
             // attempt to load a default roles
             final String rawDefaultAuthorities = 
configurationContext.getProperty("Default User Roles");
@@ -157,10 +94,9 @@ public class FileAuthorizationProvider implements 
AuthorityProvider {
                             StringUtils.join(invalidDefaultAuthorities, ", "), 
StringUtils.join(Authority.getRawAuthorities(), ", ")));
                 }
             }
-        } catch (IOException | ProviderCreationException | SAXException | 
JAXBException e) {
+        } catch (IOException | IllegalStateException | 
ProviderCreationException e) {
             throw new ProviderCreationException(e);
         }
-
     }
 
     @Override
@@ -172,67 +108,78 @@ public class FileAuthorizationProvider implements 
AuthorityProvider {
     }
 
     @Override
-    public boolean doesDnExist(String dn) throws AuthorityAccessException {
+    public boolean doesDnExist(final String dn) throws 
AuthorityAccessException {
         if (hasDefaultRoles()) {
             return true;
         }
 
-        final User user = getUser(dn);
-        return user != null;
+        return authorizedUsers.hasUser(new HasUser() {
+            @Override
+            public boolean hasUser(List<NiFiUser> users) {
+                // attempt to get the user and ensure it was located
+                NiFiUser desiredUser = null;
+                for (final NiFiUser user : users) {
+                    if 
(dn.equalsIgnoreCase(authorizedUsers.getUserIdentity(user))) {
+                        desiredUser = user;
+                        break;
+                    }
+                }
+
+                return desiredUser != null;
+            }
+        });
     }
 
     @Override
-    public synchronized Set<Authority> getAuthorities(String dn) throws 
UnknownIdentityException, AuthorityAccessException {
+    public Set<Authority> getAuthorities(final String dn) throws 
UnknownIdentityException, AuthorityAccessException {
         final Set<Authority> authorities = EnumSet.noneOf(Authority.class);
 
         // get the user
-        final User user = getUser(dn);
-
-        // ensure the user was located
-        if (user == null) {
-            if (hasDefaultRoles()) {
-                logger.debug(String.format("User DN not found: %s. Creating 
new user with default roles.", dn));
-
-                // create the user (which will automatically add any default 
authorities)
-                addUser(dn, null);
+        final NiFiUser user = authorizedUsers.getUser(new FindUser() {
+            @Override
+            public NiFiUser findUser(List<NiFiUser> users) {
+                final FindUser byDn = new FindUserByIdentity(dn);
+                NiFiUser user = byDn.findUser(users);
+
+                // if the user is not found, add them and locate them
+                if (user == null) {
+                    if (hasDefaultRoles()) {
+                        logger.debug(String.format("User identity not found: 
%s. Creating new user with default roles.", dn));
+
+                        // create the user (which will automatically add any 
default authorities)
+                        addUser(dn, null);
+
+                        // find the user that was just added
+                        user = byDn.findUser(users);
+                    } else {
+                        throw new UnknownIdentityException(String.format("User 
identity not found: %s.", dn));
+                    }
+                }
 
-                // get the authorities for the newly created user
-                authorities.addAll(getAuthorities(dn));
-            } else {
-                throw new UnknownIdentityException(String.format("User DN not 
found: %s.", dn));
-            }
-        } else {
-            // create the authorities that this user has
-            for (final Role role : user.getRole()) {
-                authorities.add(Authority.valueOfAuthority(role.getName()));
+                return user;
             }
+        });
+
+        // create the authorities that this user has
+        for (final Role role : user.getRole()) {
+            authorities.add(Authority.valueOfAuthority(role.getName()));
         }
 
         return authorities;
     }
 
     @Override
-    public synchronized void setAuthorities(String dn, Set<Authority> 
authorities) throws UnknownIdentityException, AuthorityAccessException {
-        // get the user
-        final User user = getUser(dn);
-
-        // ensure the user was located
-        if (user == null) {
-            throw new UnknownIdentityException(String.format("User DN not 
found: %s.", dn));
-        }
-
-        // add the user authorities
-        setUserAuthorities(user, authorities);
-
-        try {
-            // save the file
-            save();
-        } catch (Exception e) {
-            throw new AuthorityAccessException(e.getMessage(), e);
-        }
+    public void setAuthorities(final String dn, final Set<Authority> 
authorities) throws UnknownIdentityException, AuthorityAccessException {
+        authorizedUsers.updateUser(new FindUserByIdentity(dn), new 
UpdateUser() {
+            @Override
+            public void updateUser(NiFiUser user) {
+                // add the user authorities
+                setUserAuthorities(user, authorities);
+            }
+        });
     }
 
-    private void setUserAuthorities(final User user, final Set<Authority> 
authorities) {
+    private void setUserAuthorities(final NiFiUser user, final Set<Authority> 
authorities) {
         // clear the existing rules
         user.getRole().clear();
 
@@ -248,186 +195,118 @@ public class FileAuthorizationProvider implements 
AuthorityProvider {
     }
 
     @Override
-    public synchronized void addUser(String dn, String group) throws 
IdentityAlreadyExistsException, AuthorityAccessException {
-        final User user = getUser(dn);
+    public void addUser(final String dn, final String group) throws 
IdentityAlreadyExistsException, AuthorityAccessException {
+        authorizedUsers.createUser(new CreateUser() {
+            @Override
+            public NiFiUser createUser() {
+                final NiFiUser user = authorizedUsers.getUser(new 
FindUserByIdentity(dn));
+
+                // ensure the user doesn't already exist
+                if (user != null) {
+                    throw new 
IdentityAlreadyExistsException(String.format("User identity already exists: 
%s", dn));
+                }
 
-        // ensure the user doesn't already exist
-        if (user != null) {
-            throw new IdentityAlreadyExistsException(String.format("User DN 
already exists: %s", dn));
-        }
+                // only support adding PreAuthenticatedUser's via this API - 
LoginUser's are added
+                // via the LoginIdentityProvider
+                final ObjectFactory objFactory = new ObjectFactory();
+                final User newUser = objFactory.createUser();
 
-        // create the new user
-        final ObjectFactory objFactory = new ObjectFactory();
-        final User newUser = objFactory.createUser();
+                // set the user properties
+                newUser.setDn(dn);
+                newUser.setGroup(group);
 
-        // set the user properties
-        newUser.setDn(dn);
-        newUser.setGroup(group);
+                // add default roles if appropriate
+                if (hasDefaultRoles()) {
+                    for (final String authority : defaultAuthorities) {
+                        Role role = objFactory.createRole();
+                        role.setName(authority);
 
-        // add default roles if appropriate
-        if (hasDefaultRoles()) {
-            for (final String authority : defaultAuthorities) {
-                Role role = objFactory.createRole();
-                role.setName(authority);
+                        // add the role
+                        newUser.getRole().add(role);
+                    }
+                }
 
-                // add the role
-                newUser.getRole().add(role);
+                return newUser;
             }
-        }
-
-        // add the user
-        users.getUser().add(newUser);
-
-        try {
-            // save the file
-            save();
-        } catch (Exception e) {
-            throw new AuthorityAccessException(e.getMessage(), e);
-        }
+        });
     }
 
     @Override
-    public synchronized Set<String> getUsers(Authority authority) throws 
AuthorityAccessException {
-        final Set<String> userSet = new HashSet<>();
-        for (final User user : users.getUser()) {
-            for (final Role role : user.getRole()) {
-                if (role.getName().equals(authority.toString())) {
-                    userSet.add(user.getDn());
+    public Set<String> getUsers(final Authority authority) throws 
AuthorityAccessException {
+        final List<NiFiUser> matchingUsers = authorizedUsers.getUsers(new 
FindUsers() {
+            @Override
+            public List<NiFiUser> findUsers(List<NiFiUser> users) throws 
UnknownIdentityException {
+                final List<NiFiUser> matchingUsers = new ArrayList<>();
+                for (final NiFiUser user : users) {
+                    for (final Role role : user.getRole()) {
+                        if (role.getName().equals(authority.toString())) {
+                            matchingUsers.add(user);
+                        }
+                    }
                 }
+                return matchingUsers;
             }
+        });
+
+        final Set<String> userSet = new HashSet<>();
+        for (final NiFiUser user : matchingUsers) {
+            userSet.add(authorizedUsers.getUserIdentity(user));
         }
+
         return userSet;
     }
 
     @Override
-    public synchronized void revokeUser(String dn) throws 
UnknownIdentityException, AuthorityAccessException {
-        // get the user
-        final User user = getUser(dn);
-
-        // ensure the user was located
-        if (user == null) {
-            throw new UnknownIdentityException(String.format("User DN not 
found: %s.", dn));
-        }
-
-        // remove the specified user
-        users.getUser().remove(user);
-
-        try {
-            // save the file
-            save();
-        } catch (Exception e) {
-            throw new AuthorityAccessException(e.getMessage(), e);
-        }
+    public void revokeUser(final String dn) throws UnknownIdentityException, 
AuthorityAccessException {
+        authorizedUsers.removeUser(new FindUserByIdentity(dn));
     }
 
     @Override
-    public void setUsersGroup(Set<String> dns, String group) throws 
UnknownIdentityException, AuthorityAccessException {
-        final Collection<User> groupedUsers = new HashSet<>();
-
-        // get the specified users
-        for (final String dn : dns) {
-            // get the user
-            final User user = getUser(dn);
-
-            // ensure the user was located
-            if (user == null) {
-                throw new UnknownIdentityException(String.format("User DN not 
found: %s.", dn));
+    public void setUsersGroup(final Set<String> dns, final String group) 
throws UnknownIdentityException, AuthorityAccessException {
+        authorizedUsers.updateUsers(new FindUsersByIdentity(dns), new 
UpdateUsers() {
+            @Override
+            public void updateUsers(List<NiFiUser> users) {
+                // update each user group
+                for (final NiFiUser user : users) {
+                    user.setGroup(group);
+                }
             }
-
-            groupedUsers.add(user);
-        }
-
-        // update each user group
-        for (final User user : groupedUsers) {
-            user.setGroup(group);
-        }
-
-        try {
-            // save the file
-            save();
-        } catch (Exception e) {
-            throw new AuthorityAccessException(e.getMessage(), e);
-        }
+        });
     }
 
     @Override
     public void ungroupUser(String dn) throws UnknownIdentityException, 
AuthorityAccessException {
-        // get the user
-        final User user = getUser(dn);
-
-        // ensure the user was located
-        if (user == null) {
-            throw new UnknownIdentityException(String.format("User DN not 
found: %s.", dn));
-        }
-
-        // remove the users group
-        user.setGroup(null);
-
-        try {
-            // save the file
-            save();
-        } catch (Exception e) {
-            throw new AuthorityAccessException(e.getMessage(), e);
-        }
+        authorizedUsers.updateUser(new FindUserByIdentity(dn), new 
UpdateUser() {
+            @Override
+            public void updateUser(NiFiUser user) {
+                // remove the users group
+                user.setGroup(null);
+            }
+        });
     }
 
     @Override
-    public void ungroup(String group) throws AuthorityAccessException {
-        // get the user group
-        final Collection<User> userGroup = getUserGroup(group);
-
-        // ensure the user group was located
-        if (userGroup == null) {
-            return;
-        }
-
-        // update each user group
-        for (final User user : userGroup) {
-            user.setGroup(null);
-        }
-
-        try {
-            // save the file
-            save();
-        } catch (Exception e) {
-            throw new AuthorityAccessException(e.getMessage(), e);
-        }
+    public void ungroup(final String group) throws AuthorityAccessException {
+        authorizedUsers.updateUsers(new FindUsersByGroup(group), new 
UpdateUsers() {
+            @Override
+            public void updateUsers(List<NiFiUser> users) {
+                // update each user group
+                for (final NiFiUser user : users) {
+                    user.setGroup(null);
+                }
+            }
+        });
     }
 
     @Override
-    public String getGroupForUser(String dn) throws UnknownIdentityException, 
AuthorityAccessException {
-        // get the user
-        final User user = getUser(dn);
-
-        // ensure the user was located
-        if (user == null) {
-            throw new UnknownIdentityException(String.format("User DN not 
found: %s.", dn));
-        }
-
+    public String getGroupForUser(final String dn) throws 
UnknownIdentityException, AuthorityAccessException {
+        final NiFiUser user = authorizedUsers.getUser(new 
FindUserByIdentity(dn));
         return user.getGroup();
     }
 
     @Override
     public void revokeGroup(String group) throws UnknownIdentityException, 
AuthorityAccessException {
-        // get the user group
-        final Collection<User> userGroup = getUserGroup(group);
-
-        // ensure the user group was located
-        if (userGroup == null) {
-            throw new UnknownIdentityException(String.format("User group not 
found: %s.", group));
-        }
-
-        // remove each user in the group
-        for (final User user : userGroup) {
-            users.getUser().remove(user);
-        }
-
-        try {
-            // save the file
-            save();
-        } catch (Exception e) {
-            throw new AuthorityAccessException(e.getMessage(), e);
-        }
+        authorizedUsers.removeUsers(new FindUsersByGroup(group));
     }
 
     /**
@@ -438,59 +317,108 @@ public class FileAuthorizationProvider implements 
AuthorityProvider {
         return DownloadAuthorization.approved();
     }
 
-    private User getUser(String dn) throws UnknownIdentityException {
-        // ensure the DN was specified
-        if (dn == null) {
-            throw new UnknownIdentityException("User DN not specified.");
-        }
+    @AuthorityProviderContext
+    public void setNiFiProperties(NiFiProperties properties) {
+        this.properties = properties;
+    }
 
-        // attempt to get the user and ensure it was located
-        User desiredUser = null;
-        for (final User user : users.getUser()) {
-            if (dn.equalsIgnoreCase(user.getDn())) {
-                desiredUser = user;
-                break;
+    public class FindUserByIdentity implements FindUser {
+
+        private final String identity;
+
+        public FindUserByIdentity(String identity) {
+            // ensure the identity was specified
+            if (identity == null) {
+                throw new UnknownIdentityException("User identity not 
specified.");
             }
+
+            this.identity = identity;
         }
 
-        return desiredUser;
+        @Override
+        public NiFiUser findUser(List<NiFiUser> users) {
+            // attempt to get the user and ensure it was located
+            NiFiUser desiredUser = null;
+            for (final NiFiUser user : users) {
+                if 
(identity.equalsIgnoreCase(authorizedUsers.getUserIdentity(user))) {
+                    desiredUser = user;
+                    break;
+                }
+            }
+
+            if (desiredUser == null) {
+                throw new UnknownIdentityException(String.format("User 
identity not found: %s.", identity));
+            }
+
+            return desiredUser;
+        }
     }
 
-    private Collection<User> getUserGroup(String group) throws 
UnknownIdentityException {
-        // ensure the DN was specified
-        if (group == null) {
-            throw new UnknownIdentityException("User group not specified.");
+    public static class FindUsersByGroup implements FindUsers {
+
+        private final String group;
+
+        public FindUsersByGroup(String group) {
+            // ensure the group was specified
+            if (group == null) {
+                throw new UnknownIdentityException("User group not 
specified.");
+            }
+
+            this.group = group;
         }
 
-        // get all users with this group
-        Collection<User> userGroup = null;
-        for (final User user : users.getUser()) {
-            if (group.equals(user.getGroup())) {
-                if (userGroup == null) {
-                    userGroup = new HashSet<>();
+        @Override
+        public List<NiFiUser> findUsers(List<NiFiUser> users) throws 
UnknownIdentityException {
+            // get all users with this group
+            List<NiFiUser> userGroup = new ArrayList<>();
+            for (final NiFiUser user : users) {
+                if (group.equals(user.getGroup())) {
+                    userGroup.add(user);
                 }
-                userGroup.add(user);
             }
-        }
 
-        return userGroup;
+            // ensure the user group was located
+            if (userGroup.isEmpty()) {
+                throw new UnknownIdentityException(String.format("User group 
not found: %s.", group));
+            }
+
+            return userGroup;
+        }
     }
 
-    private void save() throws Exception {
-        final Marshaller marshaller = JAXB_CONTEXT.createMarshaller();
-        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+    public class FindUsersByIdentity implements FindUsers {
+
+        private final Set<String> identities;
 
-        // save users to restore directory before primary directory
-        if (restoreUsersFile != null) {
-            marshaller.marshal(users, restoreUsersFile);
+        public FindUsersByIdentity(Set<String> identities) {
+            // ensure the group was specified
+            if (identities == null) {
+                throw new UnknownIdentityException("User identities not 
specified.");
+            }
+
+            this.identities = identities;
         }
 
-        // save users to primary directory
-        marshaller.marshal(users, usersFile);
-    }
+        @Override
+        public List<NiFiUser> findUsers(List<NiFiUser> users) throws 
UnknownIdentityException {
+            final Set<String> copy = new HashSet<>(identities);
+
+            // get all users with this group
+            List<NiFiUser> userList = new ArrayList<>();
+            for (final NiFiUser user : users) {
+                final String userIdentity = 
authorizedUsers.getUserIdentity(user);
+                if (copy.contains(userIdentity)) {
+                    copy.remove(userIdentity);
+                    userList.add(user);
+                }
+            }
 
-    @AuthorityProviderContext
-    public void setNiFiProperties(NiFiProperties properties) {
-        this.properties = properties;
+            if (!copy.isEmpty()) {
+                throw new UnknownIdentityException("Unable to find users with 
identities: " + StringUtils.join(copy, ", "));
+            }
+
+            return userList;
+        }
     }
+
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/xsd/users.xsd
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/xsd/users.xsd
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/xsd/users.xsd
deleted file mode 100644
index 4ee1e17..0000000
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/xsd/users.xsd
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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.
--->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";>
-    <!-- role -->
-    <xs:complexType name="Role">
-        <xs:attribute name="name">
-            <xs:simpleType>
-                <xs:restriction base="xs:string">
-                    <xs:enumeration value="ROLE_MONITOR"/>
-                    <xs:enumeration value="ROLE_PROVENANCE"/>
-                    <xs:enumeration value="ROLE_DFM"/>
-                    <xs:enumeration value="ROLE_ADMIN"/>
-                    <xs:enumeration value="ROLE_PROXY"/>
-                    <xs:enumeration value="ROLE_NIFI"/>
-                </xs:restriction>
-            </xs:simpleType>
-        </xs:attribute>
-    </xs:complexType>
-
-    <!-- user -->
-    <xs:complexType name="User">
-        <xs:sequence>
-            <xs:element name="role" type="Role" minOccurs="0" 
maxOccurs="unbounded"/>
-        </xs:sequence>
-        <xs:attribute name="dn">
-            <xs:simpleType>
-                <xs:restriction base="xs:string">
-                    <xs:minLength value="1"/>
-                    <xs:pattern value=".*[^\s].*"/>
-                </xs:restriction>
-            </xs:simpleType>
-        </xs:attribute>
-        <xs:attribute name="group">
-            <xs:simpleType>
-                <xs:restriction base="xs:string">
-                    <xs:minLength value="1"/>
-                    <xs:pattern value=".*[^\s].*"/>
-                </xs:restriction>
-            </xs:simpleType>
-        </xs:attribute>
-    </xs:complexType>
-
-    <!-- users -->
-    <xs:element name="users">
-        <xs:complexType>
-            <xs:sequence>
-                <xs:element name="user" type="User" minOccurs="0" 
maxOccurs="unbounded"/>
-            </xs:sequence>
-        </xs:complexType>
-    </xs:element>
-</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/pom.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/pom.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/pom.xml
new file mode 100644
index 0000000..9dc5d02
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-framework</artifactId>
+        <version>0.3.1-SNAPSHOT</version>
+    </parent>
+    <artifactId>nifi-file-identity-provider</artifactId>
+    <packaging>jar</packaging>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-properties</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-authorized-users</artifactId>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/java/org/apache/nifi/authentication/FileLoginIdentityProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/java/org/apache/nifi/authentication/FileLoginIdentityProvider.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/java/org/apache/nifi/authentication/FileLoginIdentityProvider.java
new file mode 100644
index 0000000..6e72880
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/java/org/apache/nifi/authentication/FileLoginIdentityProvider.java
@@ -0,0 +1,101 @@
+/*
+ * 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.nifi.authentication;
+
+import java.io.IOException;
+import java.util.List;
+import org.apache.nifi.authentication.annotation.LoginIdentityProviderContext;
+import org.apache.nifi.authorization.exception.ProviderCreationException;
+import org.apache.nifi.authorization.exception.ProviderDestructionException;
+import org.apache.nifi.authorized.users.AuthorizedUsers;
+import org.apache.nifi.authorized.users.AuthorizedUsers.HasUser;
+import org.apache.nifi.user.generated.LoginUser;
+import org.apache.nifi.user.generated.NiFiUser;
+import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.util.StringUtils;
+
+/**
+ *
+ */
+public class FileLoginIdentityProvider implements LoginIdentityProvider {
+
+    private AuthorizedUsers authorizedUsers;
+    private NiFiProperties properties;
+
+    @Override
+    public void initialize(LoginIdentityProviderInitializationContext 
initializationContext) throws ProviderCreationException {
+    }
+
+    @Override
+    public void onConfigured(LoginIdentityProviderConfigurationContext 
configurationContext) throws ProviderCreationException {
+        final String usersFilePath = 
configurationContext.getProperty("Authenticated Users File");
+        if (usersFilePath == null || usersFilePath.trim().isEmpty()) {
+            throw new ProviderCreationException("The authorized users file 
must be specified.");
+        }
+
+        try {
+            // initialize the authorized users
+            authorizedUsers = AuthorizedUsers.getInstance(usersFilePath, 
properties);
+        } catch (IOException | IllegalStateException e) {
+            throw new ProviderCreationException(e);
+        }
+    }
+
+    @Override
+    public boolean supportsRegistration() {
+        return false;
+    }
+
+    @Override
+    public void register(LoginCredentials credentials) {
+    }
+
+    @Override
+    public boolean authenticate(final LoginCredentials credentials) {
+        if (StringUtils.isBlank(credentials.getUsername()) || 
StringUtils.isBlank(credentials.getPassword())) {
+            return false;
+        }
+
+        return authorizedUsers.hasUser(new HasUser() {
+            @Override
+            public boolean hasUser(List<NiFiUser> users) {
+                for (final NiFiUser user : users) {
+                    // only consider LoginUsers
+                    if (LoginUser.class.isAssignableFrom(user.getClass())) {
+                        final LoginUser loginUser = (LoginUser) user;
+
+                        // TODO - need to properly encrypt and hash password
+                        final String loginUserPassword = 
loginUser.getPassword();
+                        if 
(credentials.getUsername().equals(loginUser.getUsername()) && 
credentials.getPassword().equals(loginUserPassword)) {
+                            return true;
+                        }
+                    }
+                }
+                return false;
+            }
+        });
+    }
+
+    @Override
+    public void preDestruction() throws ProviderDestructionException {
+    }
+
+    @LoginIdentityProviderContext
+    public void setNiFiProperties(NiFiProperties properties) {
+        this.properties = properties;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider
new file mode 100644
index 0000000..3dc6354
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider
@@ -0,0 +1,15 @@
+# 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.
+org.apache.nifi.authentication.FileLoginIdentityProvider

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
index 9bbc3a3..489b80e 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
@@ -22,6 +22,7 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.ServiceLoader;
 import java.util.Set;
+import org.apache.nifi.authentication.LoginIdentityProvider;
 
 import org.apache.nifi.authorization.AuthorityProvider;
 import org.apache.nifi.controller.ControllerService;
@@ -65,6 +66,7 @@ public class ExtensionManager {
         definitionMap.put(FlowFileRepository.class, new HashSet<Class>());
         definitionMap.put(FlowFileSwapManager.class, new HashSet<Class>());
         definitionMap.put(ContentRepository.class, new HashSet<Class>());
+        definitionMap.put(LoginIdentityProvider.class, new HashSet<Class>());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/login-identity-providers.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/login-identity-providers.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/login-identity-providers.xml
new file mode 100644
index 0000000..5b4cf88
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/login-identity-providers.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  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.
+-->
+<!--
+    This file lists the login identity providers to use when running securely. 
In order
+    to use a specific provider it must be configured here and it's identifier
+    must be specified in the nifi.properties file.
+-->
+<loginIdentityProviders>
+    <provider>
+        <identifier>file-provider</identifier>
+        <class>org.apache.nifi.authentication.FileLoginIdentityProvider</class>
+        <property name="Authenticated Users 
File">./conf/authorized-users.xml</property>
+    </provider>
+</loginIdentityProviders>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties
index 54b5283..b25d05a 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties
@@ -25,6 +25,7 @@ 
nifi.administrative.yield.duration=${nifi.administrative.yield.duration}
 nifi.bored.yield.duration=${nifi.bored.yield.duration}
 
 
nifi.authority.provider.configuration.file=${nifi.authority.provider.configuration.file}
+nifi.login.identity.provider.configuration.file=${nifi.login.identity.provider.configuration.file}
 nifi.templates.directory=${nifi.templates.directory}
 nifi.ui.banner.text=${nifi.ui.banner.text}
 nifi.ui.autorefresh.interval=${nifi.ui.autorefresh.interval}
@@ -124,7 +125,9 @@ 
nifi.security.truststorePasswd=${nifi.security.truststorePasswd}
 nifi.security.needClientAuth=${nifi.security.needClientAuth}
 
nifi.security.user.credential.cache.duration=${nifi.security.user.credential.cache.duration}
 nifi.security.user.authority.provider=${nifi.security.user.authority.provider}
+nifi.security.user.login.identity.provider=${nifi.security.user.login.identity.provider}
 
nifi.security.support.new.account.requests=${nifi.security.support.new.account.requests}
+nifi.security.anonymous.authorities=${nifi.security.anonymous.authorities}
 nifi.security.ocsp.responder.url=${nifi.security.ocsp.responder.url}
 
nifi.security.ocsp.responder.certificate=${nifi.security.ocsp.responder.certificate}
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
index 99c11a8..b2b3013 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
@@ -614,8 +614,9 @@ public class JettyServer implements NiFiServer {
     private SslContextFactory createSslContextFactory() {
         final SslContextFactory contextFactory = new SslContextFactory();
 
-        // need client auth
-        contextFactory.setNeedClientAuth(props.getNeedClientAuth());
+        // client auth
+        contextFactory.setWantClientAuth(true);
+        contextFactory.setNeedClientAuth(false);
 
         /* below code sets JSSE system properties when values are provided */
         // keystore properties

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
index c98b1e4..f4d5821 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
@@ -1236,6 +1236,13 @@ public interface NiFiServiceFacade {
     Collection<UserDTO> getUsers(Boolean grouped);
 
     /**
+     * Creates a new account request.
+     *
+     * @return user
+     */
+    UserDTO createUser();
+
+    /**
      * Updates the specified user accordingly.
      *
      * @param user The user to update

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java
new file mode 100644
index 0000000..58b0af8
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java
@@ -0,0 +1,40 @@
+/*
+ * 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.nifi.web;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.ImportResource;
+
+/**
+ *
+ */
+@Configuration
+@Import({NiFiWebApiSecurityConfiguration.class})
+@ImportResource({"classpath:nifi-context.xml",
+    "classpath:nifi-administration-context.xml",
+    "classpath:nifi-cluster-manager-context.xml",
+    "classpath:nifi-cluster-protocol-context.xml",
+    "classpath:nifi-web-security-context.xml",
+    "classpath:nifi-web-api-context.xml"})
+public class NiFiWebApiConfiguration {
+
+    public NiFiWebApiConfiguration() {
+        super();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
new file mode 100644
index 0000000..7aeb105
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
@@ -0,0 +1,192 @@
+/*
+ * 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.nifi.web;
+
+import javax.servlet.Filter;
+import org.apache.nifi.admin.service.UserService;
+import org.apache.nifi.authentication.LoginIdentityProvider;
+import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.web.security.NiFiAuthenticationProvider;
+import org.apache.nifi.web.security.anonymous.NiFiAnonymousUserFilter;
+import org.apache.nifi.web.security.NiFiAuthenticationEntryPoint;
+import org.apache.nifi.web.security.form.LoginAuthenticationFilter;
+import org.apache.nifi.web.security.form.LoginAuthenticationProvider;
+import org.apache.nifi.web.security.jwt.JwtAuthenticationFilter;
+import org.apache.nifi.web.security.jwt.JwtAuthenticationProvider;
+import org.apache.nifi.web.security.jwt.JwtService;
+import org.apache.nifi.web.security.node.NodeAuthorizedUserFilter;
+import org.apache.nifi.web.security.x509.SubjectDnX509PrincipalExtractor;
+import org.apache.nifi.web.security.x509.X509AuthenticationFilter;
+import org.apache.nifi.web.security.x509.X509AuthenticationProvider;
+import org.apache.nifi.web.security.x509.X509CertificateExtractor;
+import org.apache.nifi.web.security.x509.ocsp.OcspCertificateValidator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.AuthenticationProvider;
+import 
org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import 
org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import 
org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import 
org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import 
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import 
org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
+import 
org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
+import 
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+/**
+ * NiFi Web Api Spring security
+ */
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class NiFiWebApiSecurityConfiguration extends 
WebSecurityConfigurerAdapter {
+
+    private NiFiProperties properties;
+    private UserService userService;
+    private AuthenticationUserDetailsService userDetailsService;
+    private JwtService jwtService;
+    private LoginIdentityProvider loginIdentityProvider;
+
+    public NiFiWebApiSecurityConfiguration() {
+        super(true); // disable defaults
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http
+                .rememberMe().disable()
+                .exceptionHandling()
+                .authenticationEntryPoint(new NiFiAuthenticationEntryPoint())
+                .and()
+                .authorizeRequests()
+                .anyRequest().fullyAuthenticated()
+                .and()
+                .sessionManagement()
+                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+
+        // verify that login authentication is enabled
+        if (loginIdentityProvider != null) {
+            // login authentication for /token - exchanges for JWT for 
subsequent API usage
+            http.addFilterBefore(buildLoginFilter("/token"), 
UsernamePasswordAuthenticationFilter.class);
+
+            // login registration
+            if (loginIdentityProvider.supportsRegistration()) {
+                http.addFilterBefore(buildRegistrationFilter("/registration"), 
UsernamePasswordAuthenticationFilter.class);
+            }
+        }
+
+        // cluster authorized user
+        http.addFilterBefore(buildNodeAuthorizedUserFilter(), 
AnonymousAuthenticationFilter.class);
+
+        // x509
+        http.addFilterBefore(buildX509Filter(), 
AnonymousAuthenticationFilter.class);
+
+        // jwt
+        http.addFilterBefore(buildJwtFilter(), 
AnonymousAuthenticationFilter.class);
+
+        // anonymous
+        http.anonymous().authenticationFilter(buildAnonymousFilter());
+    }
+
+    @Bean
+    @Override
+    public AuthenticationManager authenticationManagerBean() throws Exception {
+        // override xxxBean method so the authentication manager is available 
in app context (necessary for the method level security)
+        return super.authenticationManagerBean();
+    }
+
+    @Override
+    protected void configure(AuthenticationManagerBuilder auth) throws 
Exception {
+        final LoginAuthenticationProvider baseLoginAuthenticationProvider = 
new LoginAuthenticationProvider();
+        
baseLoginAuthenticationProvider.setLoginIdentityProvider(loginIdentityProvider);
+
+        final AuthenticationProvider loginAuthenticationProvider = new 
NiFiAuthenticationProvider(baseLoginAuthenticationProvider, userDetailsService);
+        final AuthenticationProvider x509AuthenticationProvider = new 
NiFiAuthenticationProvider(new X509AuthenticationProvider(), 
userDetailsService);
+        final AuthenticationProvider jwtAuthenticationProvider = new 
NiFiAuthenticationProvider(new JwtAuthenticationProvider(), userDetailsService);
+
+        auth
+                .authenticationProvider(loginAuthenticationProvider)
+                .authenticationProvider(x509AuthenticationProvider)
+                .authenticationProvider(jwtAuthenticationProvider);
+    }
+
+    private LoginAuthenticationFilter buildLoginFilter(final String url) {
+        final LoginAuthenticationFilter loginFilter = new 
LoginAuthenticationFilter(url);
+        loginFilter.setJwtService(jwtService);
+        loginFilter.setLoginIdentityProvider(loginIdentityProvider);
+        loginFilter.setPrincipalExtractor(new 
SubjectDnX509PrincipalExtractor());
+        loginFilter.setCertificateExtractor(new X509CertificateExtractor());
+        return loginFilter;
+    }
+
+    private Filter buildRegistrationFilter(final String url) {
+        return null;
+    }
+
+    private NodeAuthorizedUserFilter buildNodeAuthorizedUserFilter() {
+        return new NodeAuthorizedUserFilter(properties);
+    }
+
+    private JwtAuthenticationFilter buildJwtFilter() throws Exception {
+        final JwtAuthenticationFilter jwtFilter = new 
JwtAuthenticationFilter();
+        jwtFilter.setJwtService(jwtService);
+        jwtFilter.setAuthenticationManager(authenticationManager());
+        return jwtFilter;
+    }
+
+    private X509AuthenticationFilter buildX509Filter() throws Exception {
+        final X509AuthenticationFilter x509Filter = new 
X509AuthenticationFilter();
+        x509Filter.setPrincipalExtractor(new 
SubjectDnX509PrincipalExtractor());
+        x509Filter.setCertificateExtractor(new X509CertificateExtractor());
+        x509Filter.setCertificateValidator(new 
OcspCertificateValidator(properties));
+        x509Filter.setAuthenticationManager(authenticationManager());
+        return x509Filter;
+    }
+
+    private AnonymousAuthenticationFilter buildAnonymousFilter() {
+        final NiFiAnonymousUserFilter anonymousFilter = new 
NiFiAnonymousUserFilter();
+        anonymousFilter.setUserService(userService);
+        return anonymousFilter;
+    }
+
+    @Autowired
+    public void setUserDetailsService(AuthenticationUserDetailsService 
userDetailsService) {
+        this.userDetailsService = userDetailsService;
+    }
+
+    @Autowired
+    public void setUserService(UserService userService) {
+        this.userService = userService;
+    }
+
+    @Autowired
+    public void setProperties(NiFiProperties properties) {
+        this.properties = properties;
+    }
+
+    @Autowired
+    public void setJwtService(JwtService jwtService) {
+        this.jwtService = jwtService;
+    }
+
+    @Autowired
+    public void setLoginIdentityProvider(LoginIdentityProvider 
loginIdentityProvider) {
+        this.loginIdentityProvider = loginIdentityProvider;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index 39426c0..75cd140 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -169,6 +169,7 @@ import 
org.apache.nifi.web.api.dto.status.ClusterProcessGroupStatusDTO;
 import org.apache.nifi.web.api.dto.status.NodeProcessGroupStatusDTO;
 import org.apache.nifi.web.dao.ControllerServiceDAO;
 import org.apache.nifi.web.dao.ReportingTaskDAO;
+import org.apache.nifi.web.security.user.NewAccountRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.access.AccessDeniedException;
@@ -1809,6 +1810,23 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
     }
 
     @Override
+    public UserDTO createUser() {
+        NewAccountRequest newAccountRequest = 
NiFiUserUtils.getNewAccountRequest();
+
+        // log the new user account request
+        logger.info("Requesting new user account for " + 
newAccountRequest.getUsername());
+
+        // get the justification
+        String justification = newAccountRequest.getJustification();
+        if (justification == null) {
+            justification = StringUtils.EMPTY;
+        }
+
+        // create the pending user account
+        return 
dtoFactory.createUserDTO(userService.createPendingUserAccount(newAccountRequest.getUsername(),
 justification));
+    }
+
+    @Override
     public UserDTO updateUser(UserDTO userDto) {
         NiFiUser user;
 
@@ -3437,8 +3455,7 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
     }
 
     /**
-     * Utility method for extracting component counts from the specified group
-     * status.
+     * Utility method for extracting component counts from the specified group 
status.
      */
     private ProcessGroupCounts extractProcessGroupCounts(ProcessGroupStatus 
groupStatus) {
         int running = 0;

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java
index 3bad5e3..2e15d30 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java
@@ -23,7 +23,6 @@ import 
com.sun.jersey.server.impl.model.method.dispatch.FormDispatchProvider;
 import java.io.Serializable;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.security.cert.X509Certificate;
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -45,9 +44,8 @@ import org.apache.nifi.action.Operation;
 import org.apache.nifi.cluster.context.ClusterContext;
 import org.apache.nifi.cluster.context.ClusterContextThreadLocal;
 import org.apache.nifi.cluster.manager.impl.WebClusterManager;
-import org.apache.nifi.web.security.DnUtils;
+import org.apache.nifi.web.security.ProxiedEntitiesUtils;
 import org.apache.nifi.web.security.user.NiFiUserDetails;
-import org.apache.nifi.web.security.x509.X509CertificateExtractor;
 import org.apache.nifi.util.NiFiProperties;
 import org.apache.nifi.web.api.entity.Entity;
 import org.apache.nifi.web.api.request.ClientIdParameter;
@@ -362,12 +360,10 @@ public abstract class ApplicationResource {
             result.put(PROXY_SCHEME_HTTP_HEADER, 
httpServletRequest.getScheme());
         }
 
-        // if this is a secure request, add the custom headers for proxying 
user requests
-        final X509Certificate cert = new 
X509CertificateExtractor().extractClientCertificate(httpServletRequest);
-        if (cert != null) {
+        if (httpServletRequest.isSecure()) {
 
             // add the certificate DN to the proxy chain
-            final String xProxiedEntitiesChain = 
DnUtils.getXProxiedEntitiesChain(httpServletRequest);
+            final String xProxiedEntitiesChain = 
ProxiedEntitiesUtils.getXProxiedEntitiesChain(httpServletRequest);
             if (StringUtils.isNotBlank(xProxiedEntitiesChain)) {
                 result.put(PROXIED_ENTITIES_CHAIN_HTTP_HEADER, 
xProxiedEntitiesChain);
             }

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
index 4883721..31b256e 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
@@ -79,6 +79,7 @@ import org.apache.nifi.web.api.request.IntegerParameter;
 import org.apache.nifi.web.api.request.LongParameter;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.web.api.entity.ControllerServiceTypesEntity;
+import org.apache.nifi.web.api.entity.IdentityEntity;
 import org.apache.nifi.web.api.entity.ReportingTaskTypesEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
 
@@ -239,7 +240,7 @@ public class ControllerResource extends ApplicationResource 
{
     public ProcessGroupResource getGroupResource(
             @ApiParam(
                     value = "The id of the process group that is the parent of 
the requested resource(s). If the desired process group is "
-                            + "the root group an alias 'root' may be used as 
the process-group-id.",
+                    + "the root group an alias 'root' may be used as the 
process-group-id.",
                     required = true
             )
             @PathParam("process-group-id") String groupId) {
@@ -454,13 +455,13 @@ public class ControllerResource extends 
ApplicationResource {
     @ApiOperation(
             value = "Gets the current revision of this NiFi",
             notes = "NiFi employs an optimistic locking strategy where the 
client must include a revision in their request when "
-                    + "performing an update. If the specified revision does 
not match the current base revision a 409 status code "
-                    + "is returned. The revision is comprised of a clientId 
and a version number. The version is a simple integer "
-                    + "value that is incremented with each change. Including 
the most recent version tells NiFi that your working "
-                    + "with the most recent flow. In addition to the version 
the client who is performing the updates is recorded. "
-                    + "This allows the same client to submit multiple requests 
without having to wait for the previously ones to "
-                    + "return. Invoking this endpoint will return the current 
base revision. It is also available when retrieving "
-                    + "a process group and in the response of all mutable 
requests.",
+            + "performing an update. If the specified revision does not match 
the current base revision a 409 status code "
+            + "is returned. The revision is comprised of a clientId and a 
version number. The version is a simple integer "
+            + "value that is incremented with each change. Including the most 
recent version tells NiFi that your working "
+            + "with the most recent flow. In addition to the version the 
client who is performing the updates is recorded. "
+            + "This allows the same client to submit multiple requests without 
having to wait for the previously ones to "
+            + "return. Invoking this endpoint will return the current base 
revision. It is also available when retrieving "
+            + "a process group and in the response of all mutable requests.",
             response = Entity.class,
             authorizations = {
                 @Authorization(value = "Read Only", type = "ROLE_MONITOR"),
@@ -845,6 +846,47 @@ public class ControllerResource extends 
ApplicationResource {
     }
 
     /**
+     * Retrieves the identity of the user making the request.
+     *
+     * @param clientId Optional client id. If the client id is not specified, 
a new one will be generated. This value (whether specified or generated) is 
included in the response.
+     * @return An identityEntity
+     */
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    @Path("/identity")
+    @ApiOperation(
+            value = "Retrieves the user identity of the user making the 
request",
+            response = IdentityEntity.class
+    )
+    public Response getIdentity(
+            @ApiParam(
+                    value = "If the client id is not specified, new one will 
be generated. This value (whether specified or generated) is included in the 
response.",
+                    required = false
+            )
+            @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) 
ClientIdParameter clientId) {
+
+        // note that the cluster manager will handle this request directly
+        final NiFiUser user = NiFiUserUtils.getNiFiUser();
+        if (user == null) {
+            throw new WebApplicationException(new Throwable("Unable to access 
details for current user."));
+        }
+
+        // create the revision
+        final RevisionDTO revision = new RevisionDTO();
+        revision.setClientId(clientId.getClientId());
+
+        // create the response entity
+        IdentityEntity entity = new IdentityEntity();
+        entity.setRevision(revision);
+        entity.setUserId(user.getId());
+        entity.setIdentity(user.getDn());
+
+        // generate the response
+        return clusterContext(generateOkResponse(entity)).build();
+    }
+
+    /**
      * Retrieves the user details, including the authorities, about the user 
making the request.
      *
      * @param clientId Optional client id. If the client id is not specified, 
a new one will be generated. This value (whether specified or generated) is 
included in the response.

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/UserResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/UserResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/UserResource.java
index 4a61ef4..8999f71 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/UserResource.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/UserResource.java
@@ -16,12 +16,14 @@
  */
 package org.apache.nifi.web.api;
 
+import com.sun.jersey.api.Responses;
 import com.wordnik.swagger.annotations.Api;
 import com.wordnik.swagger.annotations.ApiOperation;
 import com.wordnik.swagger.annotations.ApiParam;
 import com.wordnik.swagger.annotations.ApiResponse;
 import com.wordnik.swagger.annotations.ApiResponses;
 import com.wordnik.swagger.annotations.Authorization;
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -39,6 +41,7 @@ import javax.ws.rs.DefaultValue;
 import javax.ws.rs.FormParam;
 import javax.ws.rs.GET;
 import javax.ws.rs.HttpMethod;
+import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
@@ -59,9 +62,11 @@ import 
org.apache.nifi.web.api.entity.UserSearchResultsEntity;
 import org.apache.nifi.web.api.entity.UsersEntity;
 import org.apache.nifi.web.api.request.ClientIdParameter;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.user.NiFiUser;
 import org.apache.nifi.web.NiFiServiceFacade;
 import static org.apache.nifi.web.api.ApplicationResource.CLIENT_ID;
 import org.apache.nifi.web.api.dto.RevisionDTO;
+import org.apache.nifi.web.security.user.NiFiUserUtils;
 import org.springframework.security.access.prepost.PreAuthorize;
 
 /**
@@ -83,12 +88,35 @@ public class UserResource extends ApplicationResource {
     private NiFiProperties properties;
     private NiFiServiceFacade serviceFacade;
 
+    @POST
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.TEXT_PLAIN)
+    @Path("") // necessary due to a bug in swagger
+    @ApiOperation(
+            value = "Creates a user",
+            response = String.class
+    )
+    public Response createUser() {
+        if (!properties.getSupportNewAccountRequests()) {
+            return Responses.notFound().entity("This NiFi does not support new 
account requests.").build();
+        }
+
+        final NiFiUser nifiUser = NiFiUserUtils.getNiFiUser();
+        if (nifiUser != null) {
+            throw new IllegalArgumentException("User account already created " 
+ nifiUser.getDn());
+        }
+
+        // create an account request for the current user
+        final UserDTO user = serviceFacade.createUser();
+
+        final String uri = generateResourceUri("controller", "templates", 
user.getId());
+        return generateCreatedResponse(URI.create(uri), "Not authorized. User 
account created. Authorization pending.").build();
+    }
+
     /**
      * Gets all users that are registered within this Controller.
      *
-     * @param clientId Optional client id. If the client id is not specified, a
-     * new one will be generated. This value (whether specified or generated) 
is
-     * included in the response.
+     * @param clientId Optional client id. If the client id is not specified, 
a new one will be generated. This value (whether specified or generated) is 
included in the response.
      * @param grouped Whether to return the users in their groups.
      * @return A usersEntity.
      */
@@ -144,9 +172,7 @@ public class UserResource extends ApplicationResource {
     /**
      * Gets the details for the specified user.
      *
-     * @param clientId Optional client id. If the client id is not specified, a
-     * new one will be generated. This value (whether specified or generated) 
is
-     * included in the response.
+     * @param clientId Optional client id. If the client id is not specified, 
a new one will be generated. This value (whether specified or generated) is 
included in the response.
      * @param id The user id.
      * @return A userEntity.
      */
@@ -315,12 +341,9 @@ public class UserResource extends ApplicationResource {
      * Updates the specified user.
      *
      * @param httpServletRequest request
-     * @param clientId Optional client id. If the client id is not specified, a
-     * new one will be generated. This value (whether specified or generated) 
is
-     * included in the response.
+     * @param clientId Optional client id. If the client id is not specified, 
a new one will be generated. This value (whether specified or generated) is 
included in the response.
      * @param id The id of the user to update.
-     * @param rawAuthorities Array of authorities to assign to the specified
-     * user.
+     * @param rawAuthorities Array of authorities to assign to the specified 
user.
      * @param status The status of the specified users account.
      * @param formParams form params
      * @return A userEntity
@@ -491,9 +514,7 @@ public class UserResource extends ApplicationResource {
      *
      * @param httpServletRequest request
      * @param id The user id
-     * @param clientId Optional client id. If the client id is not specified, a
-     * new one will be generated. This value (whether specified or generated) 
is
-     * included in the response.
+     * @param clientId Optional client id. If the client id is not specified, 
a new one will be generated. This value (whether specified or generated) is 
included in the response.
      * @return A userEntity.
      */
     @DELETE

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
index 8bf5553..3bc8120 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
@@ -113,6 +113,7 @@ import org.apache.nifi.authorization.DownloadAuthorization;
 import org.apache.nifi.processor.DataUnit;
 import org.apache.nifi.reporting.BulletinQuery;
 import org.apache.nifi.reporting.ComponentType;
+import org.apache.nifi.web.security.ProxiedEntitiesUtils;
 import org.apache.nifi.web.security.user.NiFiUserUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -822,17 +823,7 @@ public class ControllerFacade {
             final Map<String, String> attributes = event.getAttributes();
 
             // calculate the dn chain
-            final List<String> dnChain = new ArrayList<>();
-
-            // build the dn chain
-            NiFiUser chainedUser = user;
-            do {
-                // add the entry for this user
-                dnChain.add(chainedUser.getDn());
-
-                // go to the next user in the chain
-                chainedUser = chainedUser.getChain();
-            } while (chainedUser != null);
+            final List<String> dnChain = 
ProxiedEntitiesUtils.getXProxiedEntitiesChain(user);
 
             // ensure the users in this chain are allowed to download this 
content
             final DownloadAuthorization downloadAuthorization = 
userService.authorizeDownload(dnChain, attributes);

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/webapp/WEB-INF/web.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/webapp/WEB-INF/web.xml
index 4ce319e..b57998d 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/webapp/WEB-INF/web.xml
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/webapp/WEB-INF/web.xml
@@ -16,15 +16,12 @@
 <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd";>
     <display-name>nifi-api</display-name>
     <context-param>
+        <param-name>contextClass</param-name>
+        
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
+    </context-param>
+    <context-param>
         <param-name>contextConfigLocation</param-name>
-        <param-value>
-            classpath:nifi-context.xml
-            classpath:nifi-web-api-context.xml
-            classpath:nifi-web-security-context.xml
-            classpath:nifi-administration-context.xml
-            classpath:nifi-cluster-manager-context.xml
-            classpath:nifi-cluster-protocol-context.xml
-        </param-value>
+        <param-value>org.apache.nifi.web</param-value>
     </context-param>
     <listener>
         
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestUser.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestUser.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestUser.java
index 52f4522..c0e9246 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestUser.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestUser.java
@@ -22,8 +22,7 @@ import com.sun.jersey.api.client.WebResource;
 import com.sun.jersey.core.util.MultivaluedMapImpl;
 import java.util.Map;
 import javax.ws.rs.core.MediaType;
-import org.apache.nifi.web.security.DnUtils;
-import org.apache.nifi.web.security.x509.X509AuthenticationFilter;
+import org.apache.nifi.web.security.ProxiedEntitiesUtils;
 
 /**
  *
@@ -37,7 +36,7 @@ public class NiFiTestUser {
 
     public NiFiTestUser(Client client, String dn) {
         this.client = client;
-        this.proxyDn = DnUtils.formatProxyDn(dn);
+        this.proxyDn = ProxiedEntitiesUtils.formatProxyDn(dn);
     }
 
     /**
@@ -70,7 +69,7 @@ public class NiFiTestUser {
         }
 
         // perform the query
-        return 
resource.accept(MediaType.APPLICATION_JSON).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN,
 proxyDn).get(ClientResponse.class);
+        return 
resource.accept(MediaType.APPLICATION_JSON).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN,
 proxyDn).get(ClientResponse.class);
     }
 
     /**
@@ -94,7 +93,7 @@ public class NiFiTestUser {
      */
     public ClientResponse testPost(String url, Object entity) throws Exception 
{
         // get the resource
-        WebResource.Builder resourceBuilder = 
client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN,
 proxyDn);
+        WebResource.Builder resourceBuilder = 
client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN,
 proxyDn);
 
         // include the request entity
         if (entity != null) {
@@ -115,7 +114,7 @@ public class NiFiTestUser {
      */
     public ClientResponse testPostMultiPart(String url, Object entity) throws 
Exception {
         // get the resource
-        WebResource.Builder resourceBuilder = 
client.resource(url).accept(MediaType.APPLICATION_XML).type(MediaType.MULTIPART_FORM_DATA).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN,
 proxyDn);
+        WebResource.Builder resourceBuilder = 
client.resource(url).accept(MediaType.APPLICATION_XML).type(MediaType.MULTIPART_FORM_DATA).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN,
 proxyDn);
 
         // include the request entity
         if (entity != null) {
@@ -143,7 +142,7 @@ public class NiFiTestUser {
 
         // get the resource
         WebResource.Builder resourceBuilder
-                = 
client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN,
 proxyDn);
+                = 
client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN,
 proxyDn);
 
         // add the form data if necessary
         if (!entity.isEmpty()) {
@@ -164,7 +163,7 @@ public class NiFiTestUser {
      */
     public ClientResponse testPut(String url, Object entity) throws Exception {
         // get the resource
-        WebResource.Builder resourceBuilder = 
client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN,
 proxyDn);
+        WebResource.Builder resourceBuilder = 
client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN,
 proxyDn);
 
         // include the request entity
         if (entity != null) {
@@ -192,7 +191,7 @@ public class NiFiTestUser {
 
         // get the resource
         WebResource.Builder resourceBuilder
-                = 
client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN,
 proxyDn);
+                = 
client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN,
 proxyDn);
 
         // add the form data if necessary
         if (!entity.isEmpty()) {
@@ -224,7 +223,7 @@ public class NiFiTestUser {
      */
     public ClientResponse testDelete(String url, Object entity) throws 
Exception {
         // get the resource
-        WebResource.Builder resourceBuilder = 
client.resource(url).accept(MediaType.APPLICATION_JSON).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN,
 proxyDn);
+        WebResource.Builder resourceBuilder = 
client.resource(url).accept(MediaType.APPLICATION_JSON).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN,
 proxyDn);
 
         // append any query parameters
         if (entity != null) {
@@ -255,7 +254,7 @@ public class NiFiTestUser {
         }
 
         // perform the request
-        return 
resource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN,
 proxyDn).delete(ClientResponse.class);
+        return 
resource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN,
 proxyDn).delete(ClientResponse.class);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties
index 0aa5a14..fc20d78 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties
@@ -93,6 +93,7 @@ nifi.security.truststoreType=JKS
 nifi.security.truststorePasswd=localtest
 nifi.security.needClientAuth=true
 nifi.security.user.authority.provider=test-provider
+nifi.security.user.login.identity.provider=
 nifi.security.authorizedUsers.file=target/test-classes/access-control/users.xml
 nifi.security.user.credential.cache.duration=1 hr
 nifi.security.support.new.account.requests=

Reply via email to