http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api-impl/src/main/java/org/apache/nifi/registry/authorization/file/IdentifierUtil.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api-impl/src/main/java/org/apache/nifi/registry/authorization/file/IdentifierUtil.java
 
b/nifi-registry-security-api-impl/src/main/java/org/apache/nifi/registry/authorization/file/IdentifierUtil.java
new file mode 100644
index 0000000..b698cd0
--- /dev/null
+++ 
b/nifi-registry-security-api-impl/src/main/java/org/apache/nifi/registry/authorization/file/IdentifierUtil.java
@@ -0,0 +1,35 @@
+/*
+ * 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.registry.authorization.file;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.nio.charset.StandardCharsets;
+import java.util.UUID;
+
+public final class IdentifierUtil {
+
+    static String getIdentifier(final String seed) {
+        if (StringUtils.isBlank(seed)) {
+            return null;
+        }
+
+        return 
UUID.nameUUIDFromBytes(seed.getBytes(StandardCharsets.UTF_8)).toString();
+    }
+
+    private IdentifierUtil() {}
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api-impl/src/main/java/org/apache/nifi/registry/authorization/file/UserGroupHolder.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api-impl/src/main/java/org/apache/nifi/registry/authorization/file/UserGroupHolder.java
 
b/nifi-registry-security-api-impl/src/main/java/org/apache/nifi/registry/authorization/file/UserGroupHolder.java
new file mode 100644
index 0000000..3055c19
--- /dev/null
+++ 
b/nifi-registry-security-api-impl/src/main/java/org/apache/nifi/registry/authorization/file/UserGroupHolder.java
@@ -0,0 +1,241 @@
+/*
+ * 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.registry.authorization.file;
+
+
+import org.apache.nifi.registry.authorization.file.tenants.generated.Groups;
+import org.apache.nifi.registry.authorization.file.tenants.generated.Tenants;
+import org.apache.nifi.registry.authorization.file.tenants.generated.Users;
+import org.apache.nifi.registry.authorization.Group;
+import org.apache.nifi.registry.authorization.User;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A holder to provide atomic access to user group data structures.
+ */
+public class UserGroupHolder {
+
+    private final Tenants tenants;
+
+    private final Set<User> allUsers;
+    private final Map<String,User> usersById;
+    private final Map<String,User> usersByIdentity;
+
+    private final Set<Group> allGroups;
+    private final Map<String,Group> groupsById;
+    private final Map<String, Set<Group>> groupsByUserIdentity;
+
+    /**
+     * Creates a new holder and populates all convenience data structures.
+     *
+     * @param tenants the current tenants instance
+     */
+    public UserGroupHolder(final Tenants tenants) {
+        this.tenants = tenants;
+
+        // load all users
+        final Users users = tenants.getUsers();
+        final Set<User> allUsers = 
Collections.unmodifiableSet(createUsers(users));
+
+        // load all groups
+        final Groups groups = tenants.getGroups();
+        final Set<Group> allGroups = 
Collections.unmodifiableSet(createGroups(groups, users));
+
+        // create a convenience map to retrieve a user by id
+        final Map<String, User> userByIdMap = 
Collections.unmodifiableMap(createUserByIdMap(allUsers));
+
+        // create a convenience map to retrieve a user by identity
+        final Map<String, User> userByIdentityMap = 
Collections.unmodifiableMap(createUserByIdentityMap(allUsers));
+
+        // create a convenience map to retrieve a group by id
+        final Map<String, Group> groupByIdMap = 
Collections.unmodifiableMap(createGroupByIdMap(allGroups));
+
+        // create a convenience map to retrieve the groups for a user identity
+        final Map<String, Set<Group>> groupsByUserIdentityMap = 
Collections.unmodifiableMap(createGroupsByUserIdentityMap(allGroups, allUsers));
+
+        // set all the holders
+        this.allUsers = allUsers;
+        this.allGroups = allGroups;
+        this.usersById = userByIdMap;
+        this.usersByIdentity = userByIdentityMap;
+        this.groupsById = groupByIdMap;
+        this.groupsByUserIdentity = groupsByUserIdentityMap;
+    }
+
+    /**
+     * Creates a set of Users from the JAXB Users.
+     *
+     * @param users the JAXB Users
+     * @return a set of API Users matching the provided JAXB Users
+     */
+    private Set<User> createUsers(Users users) {
+        Set<User> allUsers = new HashSet<>();
+        if (users == null || users.getUser() == null) {
+            return allUsers;
+        }
+
+        for 
(org.apache.nifi.registry.authorization.file.tenants.generated.User user : 
users.getUser()) {
+            final User.Builder builder = new User.Builder()
+                    .identity(user.getIdentity())
+                    .identifier(user.getIdentifier());
+
+            allUsers.add(builder.build());
+        }
+
+        return allUsers;
+    }
+
+    /**
+     * Creates a set of Groups from the JAXB Groups.
+     *
+     * @param groups the JAXB Groups
+     * @return a set of API Groups matching the provided JAXB Groups
+     */
+    private Set<Group> createGroups(Groups groups,
+                                    Users users) {
+        Set<Group> allGroups = new HashSet<>();
+        if (groups == null || groups.getGroup() == null) {
+            return allGroups;
+        }
+
+        for 
(org.apache.nifi.registry.authorization.file.tenants.generated.Group group : 
groups.getGroup()) {
+            final Group.Builder builder = new Group.Builder()
+                    .identifier(group.getIdentifier())
+                    .name(group.getName());
+
+            for 
(org.apache.nifi.registry.authorization.file.tenants.generated.Group.User 
groupUser : group.getUser()) {
+                builder.addUser(groupUser.getIdentifier());
+            }
+
+            allGroups.add(builder.build());
+        }
+
+        return allGroups;
+    }
+
+    /**
+     * Creates a Map from user identifier to User.
+     *
+     * @param users the set of all users
+     * @return the Map from user identifier to User
+     */
+    private Map<String,User> createUserByIdMap(final Set<User> users) {
+        Map<String,User> usersMap = new HashMap<>();
+        for (User user : users) {
+            usersMap.put(user.getIdentifier(), user);
+        }
+        return usersMap;
+    }
+
+    /**
+     * Creates a Map from user identity to User.
+     *
+     * @param users the set of all users
+     * @return the Map from user identity to User
+     */
+    private Map<String,User> createUserByIdentityMap(final Set<User> users) {
+        Map<String,User> usersMap = new HashMap<>();
+        for (User user : users) {
+            usersMap.put(user.getIdentity(), user);
+        }
+        return usersMap;
+    }
+
+    /**
+     * Creates a Map from group identifier to Group.
+     *
+     * @param groups the set of all groups
+     * @return the Map from group identifier to Group
+     */
+    private Map<String,Group> createGroupByIdMap(final Set<Group> groups) {
+        Map<String,Group> groupsMap = new HashMap<>();
+        for (Group group : groups) {
+            groupsMap.put(group.getIdentifier(), group);
+        }
+        return groupsMap;
+    }
+
+    /**
+     * Creates a Map from user identity to the set of Groups for that identity.
+     *
+     * @param groups all groups
+     * @param users all users
+     * @return a Map from User identity to the set of Groups for that identity
+     */
+    private Map<String, Set<Group>> createGroupsByUserIdentityMap(final 
Set<Group> groups, final Set<User> users) {
+        Map<String, Set<Group>> groupsByUserIdentity = new HashMap<>();
+
+        for (User user : users) {
+            Set<Group> userGroups = new HashSet<>();
+            for (Group group : groups) {
+                for (String groupUser : group.getUsers()) {
+                    if (groupUser.equals(user.getIdentifier())) {
+                        userGroups.add(group);
+                    }
+                }
+            }
+
+            groupsByUserIdentity.put(user.getIdentity(), userGroups);
+        }
+
+        return groupsByUserIdentity;
+    }
+
+    public Tenants getTenants() {
+        return tenants;
+    }
+
+    public Set<User> getAllUsers() {
+        return allUsers;
+    }
+
+    public Map<String, User> getUsersById() {
+        return usersById;
+    }
+
+    public Map<String, User> getUsersByIdentity() {
+        return usersByIdentity;
+    }
+
+    public Set<Group> getAllGroups() {
+        return allGroups;
+    }
+
+    public Map<String, Group> getGroupsById() {
+        return groupsById;
+    }
+
+    public User getUser(String identity) {
+        if (identity == null) {
+            throw new IllegalArgumentException("Identity cannot be null");
+        }
+        return usersByIdentity.get(identity);
+    }
+
+    public Set<Group> getGroups(String userIdentity) {
+        if (userIdentity == null) {
+            throw new IllegalArgumentException("User Identity cannot be null");
+        }
+        return groupsByUserIdentity.get(userIdentity);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api-impl/src/main/xsd/authorizations.xsd
----------------------------------------------------------------------
diff --git a/nifi-registry-security-api-impl/src/main/xsd/authorizations.xsd 
b/nifi-registry-security-api-impl/src/main/xsd/authorizations.xsd
new file mode 100644
index 0000000..0ab27a9
--- /dev/null
+++ b/nifi-registry-security-api-impl/src/main/xsd/authorizations.xsd
@@ -0,0 +1,86 @@
+<?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";>
+
+    <xs:complexType name="Policy">
+        <xs:sequence>
+            <xs:element name="group" minOccurs="0" maxOccurs="unbounded" >
+                <xs:complexType>
+                    <xs:attribute name="identifier">
+                        <xs:simpleType>
+                            <xs:restriction base="xs:string">
+                                <xs:minLength value="1"/>
+                                <xs:pattern value=".*[^\s].*"/>
+                            </xs:restriction>
+                        </xs:simpleType>
+                    </xs:attribute>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="user" minOccurs="0" maxOccurs="unbounded" >
+                <xs:complexType>
+                    <xs:attribute name="identifier">
+                        <xs:simpleType>
+                            <xs:restriction base="xs:string">
+                                <xs:minLength value="1"/>
+                                <xs:pattern value=".*[^\s].*"/>
+                            </xs:restriction>
+                        </xs:simpleType>
+                    </xs:attribute>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+        <xs:attribute name="identifier">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:minLength value="1"/>
+                    <xs:pattern value=".*[^\s].*"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="resource">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:minLength value="1"/>
+                    <xs:pattern value=".*[^\s].*"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="action">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="R"/>
+                    <xs:enumeration value="W"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="Policies">
+        <xs:sequence>
+            <xs:element name="policy" type="Policy" minOccurs="0" 
maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <!-- top-level authorizations element -->
+    <xs:element name="authorizations">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="policies" type="Policies" minOccurs="0" 
maxOccurs="1" />
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api-impl/src/main/xsd/tenants.xsd
----------------------------------------------------------------------
diff --git a/nifi-registry-security-api-impl/src/main/xsd/tenants.xsd 
b/nifi-registry-security-api-impl/src/main/xsd/tenants.xsd
new file mode 100644
index 0000000..c1193c3
--- /dev/null
+++ b/nifi-registry-security-api-impl/src/main/xsd/tenants.xsd
@@ -0,0 +1,96 @@
+<?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";>
+
+    <!-- group -->
+    <xs:complexType name="Group">
+        <xs:sequence>
+            <xs:element name="user" minOccurs="0" maxOccurs="unbounded" >
+                <xs:complexType>
+                    <xs:attribute name="identifier">
+                        <xs:simpleType>
+                            <xs:restriction base="xs:string">
+                                <xs:minLength value="1"/>
+                                <xs:pattern value=".*[^\s].*"/>
+                            </xs:restriction>
+                        </xs:simpleType>
+                    </xs:attribute>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+        <xs:attribute name="identifier">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:minLength value="1"/>
+                    <xs:pattern value=".*[^\s].*"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="name">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:minLength value="1"/>
+                    <xs:pattern value=".*[^\s].*"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+
+    <!-- groups -->
+    <xs:complexType name="Groups">
+        <xs:sequence>
+            <xs:element name="group" type="Group" minOccurs="0" 
maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <!-- user -->
+    <xs:complexType name="User">
+        <xs:attribute name="identifier">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:minLength value="1"/>
+                    <xs:pattern value=".*[^\s].*"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="identity">
+            <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:complexType name="Users">
+        <xs:sequence>
+            <xs:element name="user" type="User" minOccurs="0" 
maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <!-- top-level authorizations element -->
+    <xs:element name="tenants">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="groups" type="Groups" minOccurs="0" 
maxOccurs="1" />
+                <xs:element name="users" type="Users" minOccurs="0" 
maxOccurs="1" />
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-security-api/pom.xml 
b/nifi-registry-security-api/pom.xml
new file mode 100644
index 0000000..8bb9eb7
--- /dev/null
+++ b/nifi-registry-security-api/pom.xml
@@ -0,0 +1,38 @@
+<?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";>
+    <parent>
+        <artifactId>nifi-registry</artifactId>
+        <groupId>org.apache.nifi.registry</groupId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>nifi-registry-security-api</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi.registry</groupId>
+            <artifactId>nifi-registry-utils</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicy.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicy.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicy.java
new file mode 100644
index 0000000..7f2bfa4
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicy.java
@@ -0,0 +1,367 @@
+/*
+ * 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.registry.authorization;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Defines a policy for a set of userIdentifiers to perform a set of actions 
on a given resource.
+ */
+public class AccessPolicy {
+
+    private final String identifier;
+
+    private final String resource;
+
+    private final Set<String> users;
+
+    private final Set<String> groups;
+
+    private final RequestAction action;
+
+    private AccessPolicy(final Builder builder) {
+        this.identifier = builder.identifier;
+        this.resource = builder.resource;
+        this.action = builder.action;
+        this.users = Collections.unmodifiableSet(new HashSet<>(builder.users));
+        this.groups = Collections.unmodifiableSet(new 
HashSet<>(builder.groups));
+
+        if (this.identifier == null || this.identifier.trim().isEmpty()) {
+            throw new IllegalArgumentException("Identifier can not be null or 
empty");
+        }
+
+        if (this.resource == null) {
+            throw new IllegalArgumentException("Resource can not be null");
+        }
+
+        if (this.action == null) {
+            throw new IllegalArgumentException("Action can not be null");
+        }
+    }
+
+    /**
+     * @return the identifier for this policy
+     */
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    /**
+     * @return the resource for this policy
+     */
+    public String getResource() {
+        return resource;
+    }
+
+    /**
+     * @return an unmodifiable set of user ids for this policy
+     */
+    public Set<String> getUsers() {
+        return users;
+    }
+
+    /**
+     * @return an unmodifiable set of group ids for this policy
+     */
+    public Set<String> getGroups() {
+        return groups;
+    }
+
+    /**
+     * @return the action for this policy
+     */
+    public RequestAction getAction() {
+        return action;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        final AccessPolicy other = (AccessPolicy) obj;
+        return Objects.equals(this.identifier, other.identifier);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(this.identifier);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("identifier[%s], resource[%s], users[%s], 
groups[%s], action[%s]",
+                getIdentifier(), getResource(), getUsers(), getGroups(), 
getAction());
+    }
+
+    /**
+     * Builder for Access Policies.
+     */
+    public static class Builder {
+
+        private String identifier;
+        private String resource;
+        private RequestAction action;
+        private Set<String> users = new HashSet<>();
+        private Set<String> groups = new HashSet<>();
+        private final boolean fromPolicy;
+
+        /**
+         * Default constructor for building a new AccessPolicy.
+         */
+        public Builder() {
+            this.fromPolicy = false;
+        }
+
+        /**
+         * Initializes the builder with the state of the provided policy. When 
using this constructor
+         * the identifier field of the builder can not be changed and will 
result in an IllegalStateException
+         * if attempting to do so.
+         *
+         * @param other the existing access policy to initialize from
+         */
+        public Builder(final AccessPolicy other) {
+            if (other == null) {
+                throw new IllegalArgumentException("Can not initialize builder 
with a null access policy");
+            }
+
+            this.identifier = other.getIdentifier();
+            this.resource = other.getResource();
+            this.action = other.getAction();
+            this.users.clear();
+            this.users.addAll(other.getUsers());
+            this.groups.clear();
+            this.groups.addAll(other.getGroups());
+            this.fromPolicy = true;
+        }
+
+        /**
+         * Sets the identifier of the builder.
+         *
+         * @param identifier the identifier to set
+         * @return the builder
+         * @throws IllegalStateException if this method is called when this 
builder was constructed from an existing Policy
+         */
+        public Builder identifier(final String identifier) {
+            if (fromPolicy) {
+                throw new IllegalStateException(
+                        "Identifier can not be changed when initialized from 
an existing policy");
+            }
+
+            this.identifier = identifier;
+            return this;
+        }
+
+        /**
+         * Sets the identifier of the builder to a random UUID.
+         *
+         * @return the builder
+         * @throws IllegalStateException if this method is called when this 
builder was constructed from an existing Policy
+         */
+        public Builder identifierGenerateRandom() {
+            if (fromPolicy) {
+                throw new IllegalStateException(
+                        "Identifier can not be changed when initialized from 
an existing policy");
+            }
+
+            this.identifier = UUID.randomUUID().toString();
+            return this;
+        }
+
+        /**
+         * Sets the identifier of the builder with a UUID generated from the 
specified seed string.
+         *
+         * @return the builder
+         * @throws IllegalStateException if this method is called when this 
builder was constructed from an existing Policy
+         */
+        public Builder identifierGenerateFromSeed(final String seed) {
+            if (fromPolicy) {
+                throw new IllegalStateException(
+                        "Identifier can not be changed when initialized from 
an existing policy");
+            }
+            if (seed == null) {
+                throw new IllegalArgumentException("Cannot seed the policy 
identifier with a null value.");
+            }
+
+            this.identifier = 
UUID.nameUUIDFromBytes(seed.getBytes(StandardCharsets.UTF_8)).toString();
+            return this;
+        }
+
+        /**
+         * Sets the resource of the builder.
+         *
+         * @param resource the resource to set
+         * @return the builder
+         */
+        public Builder resource(final String resource) {
+            this.resource = resource;
+            return this;
+        }
+
+        /**
+         * Adds all the users from the provided set to the builder's set of 
users.
+         *
+         * @param users the users to add
+         * @return the builder
+         */
+        public Builder addUsers(final Set<String> users) {
+            if (users != null) {
+                this.users.addAll(users);
+            }
+            return this;
+        }
+
+        /**
+         * Adds the given user to the builder's set of users.
+         *
+         * @param user the user to add
+         * @return the builder
+         */
+        public Builder addUser(final String user) {
+            if (user != null) {
+                this.users.add(user);
+            }
+            return this;
+        }
+
+        /**
+         * Removes all users in the provided set from the builder's set of 
users.
+         *
+         * @param users the users to remove
+         * @return the builder
+         */
+        public Builder removeUsers(final Set<String> users) {
+            if (users != null) {
+                this.users.removeAll(users);
+            }
+            return this;
+        }
+
+        /**
+         * Removes the provided user from the builder's set of users.
+         *
+         * @param user the user to remove
+         * @return the builder
+         */
+        public Builder removeUser(final String user) {
+            if (user != null) {
+                this.users.remove(user);
+            }
+            return this;
+        }
+
+        /**
+         * Clears the builder's set of users so that it is non-null and size 
== 0.
+         *
+         * @return the builder
+         */
+        public Builder clearUsers() {
+            this.users.clear();
+            return this;
+        }
+
+        /**
+         * Adds all the groups from the provided set to the builder's set of 
groups.
+         *
+         * @param groups the groups to add
+         * @return the builder
+         */
+        public Builder addGroups(final Set<String> groups) {
+            if (groups != null) {
+                this.groups.addAll(groups);
+            }
+            return this;
+        }
+
+        /**
+         * Adds the given group to the builder's set of groups.
+         *
+         * @param group the group to add
+         * @return the builder
+         */
+        public Builder addGroup(final String group) {
+            if (group != null) {
+                this.groups.add(group);
+            }
+            return this;
+        }
+
+        /**
+         * Removes all groups in the provided set from the builder's set of 
groups.
+         *
+         * @param groups the groups to remove
+         * @return the builder
+         */
+        public Builder removeGroups(final Set<String> groups) {
+            if (groups != null) {
+                this.groups.removeAll(groups);
+            }
+            return this;
+        }
+
+        /**
+         * Removes the provided groups from the builder's set of groups.
+         *
+         * @param group the group to remove
+         * @return the builder
+         */
+        public Builder removeGroup(final String group) {
+            if (group != null) {
+                this.groups.remove(group);
+            }
+            return this;
+        }
+
+        /**
+         * Clears the builder's set of groups so that it is non-null and size 
== 0.
+         *
+         * @return the builder
+         */
+        public Builder clearGroups() {
+            this.groups.clear();
+            return this;
+        }
+
+        /**
+         * Sets the action for this builder.
+         *
+         * @param action the action to set
+         * @return the builder
+         */
+        public Builder action(final RequestAction action) {
+            this.action = action;
+            return this;
+        }
+
+        /**
+         * @return a new AccessPolicy constructed from the state of the builder
+         */
+        public AccessPolicy build() {
+            return new AccessPolicy(this);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProvider.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProvider.java
new file mode 100644
index 0000000..d7e44b2
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProvider.java
@@ -0,0 +1,90 @@
+/*
+ * 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.registry.authorization;
+
+import 
org.apache.nifi.registry.authorization.exception.AuthorizationAccessException;
+import 
org.apache.nifi.registry.authorization.exception.AuthorizerCreationException;
+import 
org.apache.nifi.registry.authorization.exception.AuthorizerDestructionException;
+
+import java.util.Set;
+
+/**
+ * Provides access to AccessPolicies and the configured UserGroupProvider.
+ *
+ * NOTE: Extensions will be called often and frequently. Because of this, if 
the underlying implementation needs to
+ * make remote calls or expensive calculations those should probably be done 
asynchronously and/or cache the results.
+ *
+ * Additionally, extensions need to be thread safe.
+ */
+public interface AccessPolicyProvider {
+
+    /**
+     * Retrieves all access policies. Must be non null
+     *
+     * @return a list of policies
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    Set<AccessPolicy> getAccessPolicies() throws AuthorizationAccessException;
+
+    /**
+     * Retrieves the policy with the given identifier.
+     *
+     * @param identifier the id of the policy to retrieve
+     * @return the policy with the given id, or null if no matching policy 
exists
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    AccessPolicy getAccessPolicy(String identifier) throws 
AuthorizationAccessException;
+
+    /**
+     * Gets the access policies for the specified resource identifier and 
request action.
+     *
+     * @param resourceIdentifier the resource identifier
+     * @param action the request action
+     * @return the policy matching the resouce and action, or null if no 
matching policy exists
+     * @throws AuthorizationAccessException if there was any unexpected error 
performing the operation
+     */
+    AccessPolicy getAccessPolicy(String resourceIdentifier, RequestAction 
action) throws AuthorizationAccessException;
+
+    /**
+     * Returns the UserGroupProvider for this managed Authorizer. Must be non 
null
+     *
+     * @return the UserGroupProvider
+     */
+    UserGroupProvider getUserGroupProvider();
+
+    /**
+     * Called immediately after instance creation for implementers to perform 
additional setup
+     *
+     * @param initializationContext in which to initialize
+     */
+    void initialize(AccessPolicyProviderInitializationContext 
initializationContext) throws AuthorizerCreationException;
+
+    /**
+     * Called to configure the Authorizer.
+     *
+     * @param configurationContext at the time of configuration
+     * @throws AuthorizerCreationException for any issues configuring the 
provider
+     */
+    void onConfigured(AuthorizerConfigurationContext configurationContext) 
throws AuthorizerCreationException;
+
+    /**
+     * Called immediately before instance destruction for implementers to 
release resources.
+     *
+     * @throws AuthorizerDestructionException If pre-destruction fails.
+     */
+    void preDestruction() throws AuthorizerDestructionException;
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProviderInitializationContext.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProviderInitializationContext.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProviderInitializationContext.java
new file mode 100644
index 0000000..756bf32
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProviderInitializationContext.java
@@ -0,0 +1,30 @@
+/*
+ * 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.registry.authorization;
+
+/**
+ * Initialization content for AccessPolicyProviders.
+ */
+public interface AccessPolicyProviderInitializationContext extends 
UserGroupProviderInitializationContext {
+
+    /**
+     * The lookup for accessing other configured AccessPolicyProviders.
+     *
+     * @return  The AccessPolicyProvider lookup
+     */
+    AccessPolicyProviderLookup getAccessPolicyProviderLookup();
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProviderLookup.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProviderLookup.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProviderLookup.java
new file mode 100644
index 0000000..ff5b9d4
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AccessPolicyProviderLookup.java
@@ -0,0 +1,31 @@
+/*
+ * 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.registry.authorization;
+
+/**
+ *
+ */
+public interface AccessPolicyProviderLookup {
+
+    /**
+     * Looks up the AccessPolicyProvider with the specified identifier
+     *
+     * @param identifier        The identifier of the AccessPolicyProvider
+     * @return                  The AccessPolicyProvider
+     */
+    AccessPolicyProvider getAccessPolicyProvider(String identifier);
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationAuditor.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationAuditor.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationAuditor.java
new file mode 100644
index 0000000..4f017c5
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationAuditor.java
@@ -0,0 +1,30 @@
+/*
+ * 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.registry.authorization;
+
+public interface AuthorizationAuditor {
+
+    /**
+     * Audits an authorization request. Will be invoked for any Approved or 
Denied results. ResourceNotFound
+     * will either re-attempt authorization using a parent resource or will 
generate a failure result and
+     * audit that.
+     *
+     * @param request the request for authorization
+     * @param result the authorization result
+     */
+    void auditAccessAttempt(final AuthorizationRequest request, final 
AuthorizationResult result);
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationRequest.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationRequest.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationRequest.java
new file mode 100644
index 0000000..5c506ef
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationRequest.java
@@ -0,0 +1,245 @@
+/*
+ * 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.registry.authorization;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * Represents an authorization request for a given user/entity performing an 
action against a resource within some userContext.
+ */
+public class AuthorizationRequest {
+
+    public static final String DEFAULT_EXPLANATION = "Unable to perform the 
desired action.";
+
+    private final Resource resource;
+    private final Resource requestedResource;
+    private final String identity;
+    private final Set<String> groups;
+    private final RequestAction action;
+    private final boolean isAccessAttempt;
+    private final boolean isAnonymous;
+    private final Map<String, String> userContext;
+    private final Map<String, String> resourceContext;
+    private final Supplier<String> explanationSupplier;
+
+    private AuthorizationRequest(final Builder builder) {
+        Objects.requireNonNull(builder.resource, "The resource is required 
when creating an authorization request");
+        Objects.requireNonNull(builder.action, "The action is required when 
creating an authorization request");
+        Objects.requireNonNull(builder.isAccessAttempt, "Whether this request 
is an access attempt is request");
+        Objects.requireNonNull(builder.isAnonymous, "Whether this request is 
being performed by an anonymous user is required");
+
+        this.resource = builder.resource;
+        this.identity = builder.identity;
+        this.groups = builder.groups == null ? null : 
Collections.unmodifiableSet(builder.groups);
+        this.action = builder.action;
+        this.isAccessAttempt = builder.isAccessAttempt;
+        this.isAnonymous = builder.isAnonymous;
+        this.userContext = builder.userContext == null ? null : 
Collections.unmodifiableMap(builder.userContext);
+        this.resourceContext = builder.resourceContext == null ? null : 
Collections.unmodifiableMap(builder.resourceContext);
+        this.explanationSupplier = () -> {
+            final String explanation = builder.explanationSupplier.get();
+
+            // ensure the specified supplier returns non null
+            if (explanation == null) {
+                return DEFAULT_EXPLANATION;
+            } else {
+                return explanation;
+            }
+        };
+
+        if (builder.requestedResource == null) {
+            this.requestedResource = builder.resource;
+        } else {
+            this.requestedResource = builder.requestedResource;
+        }
+    }
+
+    /**
+     * The Resource being authorized. Not null.
+     *
+     * @return The resource
+     */
+    public Resource getResource() {
+        return resource;
+    }
+
+    /**
+     * The original Resource being requested. In cases with inherited 
policies, this will be a ancestor resource of
+     * of the current resource. The initial request, and cases without 
inheritance, the requested resource will be
+     * the same as the current resource.
+     *
+     * @return The requested resource
+     */
+    public Resource getRequestedResource() {
+        return requestedResource;
+    }
+
+    /**
+     * The identity accessing the Resource. May be null if the user could not 
authenticate.
+     *
+     * @return The identity
+     */
+    public String getIdentity() {
+        return identity;
+    }
+
+    /**
+     * The groups the user making this request belongs to. May be null if this 
NiFi is not configured to load user
+     * groups or empty if the user has no groups
+     *
+     * @return The groups
+     */
+    public Set<String> getGroups() {
+        return groups;
+    }
+
+    /**
+     * Whether this is a direct access attempt of the Resource if if it's 
being checked as part of another response.
+     *
+     * @return if this is a direct access attempt
+     */
+    public boolean isAccessAttempt() {
+        return isAccessAttempt;
+    }
+
+    /**
+     * Whether the entity accessing is anonymous.
+     *
+     * @return whether the entity is anonymous
+     */
+    public boolean isAnonymous() {
+        return isAnonymous;
+    }
+
+    /**
+     * The action being taken against the Resource. Not null.
+     *
+     * @return The action
+     */
+    public RequestAction getAction() {
+        return action;
+    }
+
+    /**
+     * The userContext of the user request to make additional access 
decisions. May be null.
+     *
+     * @return  The userContext of the user request
+     */
+    public Map<String, String> getUserContext() {
+        return userContext;
+    }
+
+    /**
+     * The event attributes to make additional access decisions for provenance 
events. May be null.
+     *
+     * @return  The event attributes
+     */
+    public Map<String, String> getResourceContext() {
+        return resourceContext;
+    }
+
+    /**
+     * A supplier for the explanation if access is denied. Non null.
+     *
+     * @return The explanation supplier if access is denied
+     */
+    public Supplier<String> getExplanationSupplier() {
+        return explanationSupplier;
+    }
+
+    /**
+     * AuthorizationRequest builder.
+     */
+    public static final class Builder {
+
+        private Resource resource;
+        private Resource requestedResource;
+        private String identity;
+        private Set<String> groups;
+        private Boolean isAnonymous;
+        private Boolean isAccessAttempt;
+        private RequestAction action;
+        private Map<String, String> userContext;
+        private Map<String, String> resourceContext;
+        private Supplier<String> explanationSupplier = () -> 
DEFAULT_EXPLANATION;
+
+        public Builder resource(final Resource resource) {
+            this.resource = resource;
+            return this;
+        }
+
+        public Builder requestedResource(final Resource requestedResource) {
+            this.requestedResource = requestedResource;
+            return this;
+        }
+
+        public Builder identity(final String identity) {
+            this.identity = identity;
+            return this;
+        }
+
+        public Builder groups(final Set<String> groups) {
+            this.groups = groups;
+            return this;
+        }
+
+        public Builder anonymous(final Boolean isAnonymous) {
+            this.isAnonymous = isAnonymous;
+            return this;
+        }
+
+        public Builder accessAttempt(final Boolean isAccessAttempt) {
+            this.isAccessAttempt = isAccessAttempt;
+            return this;
+        }
+
+        public Builder action(final RequestAction action) {
+            this.action = action;
+            return this;
+        }
+
+        public Builder userContext(final Map<String, String> userContext) {
+            if (userContext != null) {
+                this.userContext = new HashMap<>(userContext);
+            }
+            return this;
+        }
+
+        public Builder resourceContext(final Map<String, String> 
resourceContext) {
+            if (resourceContext != null) {
+                this.resourceContext = new HashMap<>(resourceContext);
+            }
+            return this;
+        }
+
+        public Builder explanationSupplier(final Supplier<String> 
explanationSupplier) {
+            if (explanationSupplier != null) {
+                this.explanationSupplier = explanationSupplier;
+            }
+            return this;
+        }
+
+        public AuthorizationRequest build() {
+            return new AuthorizationRequest(this);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationResult.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationResult.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationResult.java
new file mode 100644
index 0000000..3cfd056
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizationResult.java
@@ -0,0 +1,103 @@
+/*
+ * 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.registry.authorization;
+
+/**
+ * Represents a decision whether authorization is granted.
+ */
+public class AuthorizationResult {
+
+    public enum Result {
+        Approved,
+        Denied,
+        ResourceNotFound
+    }
+
+    private static final AuthorizationResult APPROVED = new 
AuthorizationResult(Result.Approved, null);
+    private static final AuthorizationResult RESOURCE_NOT_FOUND = new 
AuthorizationResult(Result.ResourceNotFound, "Not authorized for the requested 
resource.");
+
+    private final Result result;
+    private final String explanation;
+
+    /**
+     * Creates a new AuthorizationResult with the specified result and 
explanation.
+     *
+     * @param result of the authorization
+     * @param explanation for the authorization attempt
+     */
+    private AuthorizationResult(Result result, String explanation) {
+        if (Result.Denied.equals(result) && explanation == null) {
+            throw new IllegalArgumentException("An explanation is required 
when the authorization request is denied.");
+        }
+
+        if (Result.ResourceNotFound.equals(result) && explanation == null) {
+            throw new IllegalArgumentException("An explanation is required 
when the authorization request is resource not found.");
+        }
+
+        this.result = result;
+        this.explanation = explanation;
+    }
+
+    /**
+     * @return Whether or not the request is approved
+     */
+    public Result getResult() {
+        return result;
+    }
+
+    /**
+     * @return If the request is denied, the reason why. Null otherwise
+     */
+    public String getExplanation() {
+        return explanation;
+    }
+
+    /**
+     * @return a new approved AuthorizationResult
+     */
+    public static AuthorizationResult approved() {
+        return APPROVED;
+    }
+
+    /**
+     * Resource not found will indicate that there are no specific 
authorization rules for this resource.
+     * @return a new resource not found AuthorizationResult
+     */
+    public static AuthorizationResult resourceNotFound() {
+        return RESOURCE_NOT_FOUND;
+    }
+
+    /**
+     * Creates a new denied AuthorizationResult with a message indicating 
'Access is denied'.
+     *
+     * @return a new denied AuthorizationResult
+     */
+    public static AuthorizationResult denied() {
+        return denied(AuthorizationRequest.DEFAULT_EXPLANATION);
+    }
+
+    /**
+     * Creates a new denied AuthorizationResult with the specified explanation.
+     *
+     * @param explanation for why it was denied
+     * @return a new denied AuthorizationResult with the specified explanation
+     * @throws IllegalArgumentException if explanation is null
+     */
+    public static AuthorizationResult denied(String explanation) {
+        return new AuthorizationResult(Result.Denied, explanation);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/Authorizer.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/Authorizer.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/Authorizer.java
new file mode 100644
index 0000000..3f805d5
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/Authorizer.java
@@ -0,0 +1,63 @@
+/*
+ * 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.registry.authorization;
+
+import 
org.apache.nifi.registry.authorization.exception.AuthorizationAccessException;
+import 
org.apache.nifi.registry.authorization.exception.AuthorizerCreationException;
+import 
org.apache.nifi.registry.authorization.exception.AuthorizerDestructionException;
+
+/**
+ * Authorizes user requests.
+ */
+public interface Authorizer {
+
+    /**
+     * Determines if the specified user/entity is authorized to access the 
specified resource within the given context.
+     * These details are all contained in the AuthorizationRequest.
+     *
+     * NOTE: This method will be called often and frequently. Because of this, 
if the underlying implementation needs to
+     * make remote calls or expensive calculations those should probably be 
done asynchronously and/or cache the results.
+     *
+     * @param   request The authorization request
+     * @return  the authorization result
+     * @throws  AuthorizationAccessException if unable to access the policies
+     */
+    AuthorizationResult authorize(AuthorizationRequest request) throws 
AuthorizationAccessException;
+
+    /**
+     * Called immediately after instance creation for implementers to perform 
additional setup
+     *
+     * @param initializationContext in which to initialize
+     */
+    void initialize(AuthorizerInitializationContext initializationContext) 
throws AuthorizerCreationException;
+
+    /**
+     * Called to configure the Authorizer.
+     *
+     * @param configurationContext at the time of configuration
+     * @throws AuthorizerCreationException for any issues configuring the 
provider
+     */
+    void onConfigured(AuthorizerConfigurationContext configurationContext) 
throws AuthorizerCreationException;
+
+    /**
+     * Called immediately before instance destruction for implementers to 
release resources.
+     *
+     * @throws AuthorizerDestructionException If pre-destruction fails.
+     */
+    void preDestruction() throws AuthorizerDestructionException;
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerConfigurationContext.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerConfigurationContext.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerConfigurationContext.java
new file mode 100644
index 0000000..fb1b206
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerConfigurationContext.java
@@ -0,0 +1,48 @@
+/*
+ * 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.registry.authorization;
+
+import org.apache.nifi.registry.util.PropertyValue;
+
+import java.util.Map;
+
+/**
+ *
+ */
+public interface AuthorizerConfigurationContext {
+
+    /**
+     * @return identifier for the authorizer
+     */
+    String getIdentifier();
+
+    /**
+     * Retrieves all properties the component currently understands regardless
+     * of whether a value has been set for them or not. If no value is present
+     * then its value is null and thus any registered default for the property
+     * descriptor applies.
+     *
+     * @return Map of all properties
+     */
+    Map<String, String> getProperties();
+
+    /**
+     * @param property to lookup the descriptor and value of
+     * @return the value the component currently understands for the given 
PropertyDescriptor
+     */
+    PropertyValue getProperty(String property);
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerInitializationContext.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerInitializationContext.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerInitializationContext.java
new file mode 100644
index 0000000..c4ef14f
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerInitializationContext.java
@@ -0,0 +1,30 @@
+/*
+ * 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.registry.authorization;
+
+/**
+ * Initialization content for Authorizers.
+ */
+public interface AuthorizerInitializationContext extends 
AccessPolicyProviderInitializationContext {
+
+    /**
+     * The lookup for accessing other configured Authorizers.
+     *
+     * @return  The Authorizer lookup
+     */
+    AuthorizerLookup getAuthorizerLookup();
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerLookup.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerLookup.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerLookup.java
new file mode 100644
index 0000000..4d7641b
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/AuthorizerLookup.java
@@ -0,0 +1,31 @@
+/*
+ * 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.registry.authorization;
+
+/**
+ *
+ */
+public interface AuthorizerLookup {
+
+    /**
+     * Looks up the Authorizer with the specified identifier
+     *
+     * @param identifier        The identifier of the Authorizer
+     * @return                  The Authorizer
+     */
+    Authorizer getAuthorizer(String identifier);
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/ConfigurableAccessPolicyProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/ConfigurableAccessPolicyProvider.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/ConfigurableAccessPolicyProvider.java
new file mode 100644
index 0000000..b563c40
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/ConfigurableAccessPolicyProvider.java
@@ -0,0 +1,108 @@
+/*
+ * 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.registry.authorization;
+
+import 
org.apache.nifi.registry.authorization.exception.AuthorizationAccessException;
+import 
org.apache.nifi.registry.authorization.exception.UninheritableAuthorizationsException;
+
+/**
+ * Provides support for configuring AccessPolicies.
+ *
+ * NOTE: Extensions will be called often and frequently. Because of this, if 
the underlying implementation needs to
+ * make remote calls or expensive calculations those should probably be done 
asynchronously and/or cache the results.
+ *
+ * Additionally, extensions need to be thread safe.
+ */
+public interface ConfigurableAccessPolicyProvider extends AccessPolicyProvider 
{
+
+    /**
+     * Returns a fingerprint representing the authorizations managed by this 
authorizer. The fingerprint will be
+     * used for comparison to determine if two policy-based authorizers 
represent a compatible set of policies.
+     *
+     * @return the fingerprint for this Authorizer
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    String getFingerprint() throws AuthorizationAccessException;
+
+    /**
+     * Parses the fingerprint and adds any policies to the current 
AccessPolicyProvider.
+     *
+     * @param fingerprint the fingerprint that was obtained from calling 
getFingerprint() on another Authorizer.
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    void inheritFingerprint(final String fingerprint) throws 
AuthorizationAccessException;
+
+    /**
+     * When the fingerprints are not equal, this method will check if the 
proposed fingerprint is inheritable.
+     * If the fingerprint is an exact match, this method will not be invoked 
as there is nothing to inherit.
+     *
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     * @throws UninheritableAuthorizationsException if the proposed 
fingerprint was uninheritable
+     */
+    void checkInheritability(final String proposedFingerprint) throws 
AuthorizationAccessException, UninheritableAuthorizationsException;
+
+    /**
+     * Adds the given policy ensuring that multiple policies can not be added 
for the same resource and action.
+     *
+     * @param accessPolicy the policy to add
+     * @return the policy that was added
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    AccessPolicy addAccessPolicy(AccessPolicy accessPolicy) throws 
AuthorizationAccessException;
+
+    /**
+     * Determines whether the specified access policy is configurable. 
Provides the opportunity for a ConfigurableAccessPolicyProvider to prevent
+     * editing of a specific access policy. By default, all known access 
policies are configurable.
+     *
+     * @param accessPolicy the access policy
+     * @return is configurable
+     */
+    default boolean isConfigurable(AccessPolicy accessPolicy) {
+        if (accessPolicy == null) {
+            throw new IllegalArgumentException("Access policy cannot be null");
+        }
+
+        return getAccessPolicy(accessPolicy.getIdentifier()) != null;
+    }
+
+    /**
+     * The policy represented by the provided instance will be updated based 
on the provided instance.
+     *
+     * @param accessPolicy an updated policy
+     * @return the updated policy, or null if no matching policy was found
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    AccessPolicy updateAccessPolicy(AccessPolicy accessPolicy) throws 
AuthorizationAccessException;
+
+    /**
+     * Deletes the given policy.
+     *
+     * @param accessPolicy the policy to delete
+     * @return the deleted policy, or null if no matching policy was found
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    AccessPolicy deleteAccessPolicy(AccessPolicy accessPolicy) throws 
AuthorizationAccessException;
+
+    /**
+     * Deletes the policy with the specified identifier.
+     *
+     * @param accessPolicyIdentifier the policy to delete
+     * @return the deleted policy, or null if no matching policy was found
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    AccessPolicy deleteAccessPolicy(String accessPolicyIdentifier) throws 
AuthorizationAccessException;
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/785cb81f/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/ConfigurableUserGroupProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/ConfigurableUserGroupProvider.java
 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/ConfigurableUserGroupProvider.java
new file mode 100644
index 0000000..83a7124
--- /dev/null
+++ 
b/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/authorization/ConfigurableUserGroupProvider.java
@@ -0,0 +1,163 @@
+/*
+ * 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.registry.authorization;
+
+import 
org.apache.nifi.registry.authorization.exception.AuthorizationAccessException;
+import 
org.apache.nifi.registry.authorization.exception.UninheritableAuthorizationsException;
+
+/**
+ * Provides support for configuring Users and Groups.
+ *
+ * NOTE: Extensions will be called often and frequently. Because of this, if 
the underlying implementation needs to
+ * make remote calls or expensive calculations those should probably be done 
asynchronously and/or cache the results.
+ *
+ * Additionally, extensions need to be thread safe.
+ */
+public interface ConfigurableUserGroupProvider extends UserGroupProvider {
+
+    /**
+     * Returns a fingerprint representing the authorizations managed by this 
authorizer. The fingerprint will be
+     * used for comparison to determine if two policy-based authorizers 
represent a compatible set of users and/or groups.
+     *
+     * @return the fingerprint for this Authorizer
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    String getFingerprint() throws AuthorizationAccessException;
+
+    /**
+     * Parses the fingerprint and adds any users and groups to the current 
Authorizer.
+     *
+     * @param fingerprint the fingerprint that was obtained from calling 
getFingerprint() on another Authorizer.
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    void inheritFingerprint(final String fingerprint) throws 
AuthorizationAccessException;
+
+    /**
+     * When the fingerprints are not equal, this method will check if the 
proposed fingerprint is inheritable.
+     * If the fingerprint is an exact match, this method will not be invoked 
as there is nothing to inherit.
+     *
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     * @throws UninheritableAuthorizationsException if the proposed 
fingerprint was uninheritable
+     */
+    void checkInheritability(final String proposedFingerprint) throws 
AuthorizationAccessException, UninheritableAuthorizationsException;
+
+    /**
+     * Adds the given user.
+     *
+     * @param user the user to add
+     * @return the user that was added
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     * @throws IllegalStateException if there is already a user with the same 
identity
+     */
+    User addUser(User user) throws AuthorizationAccessException;
+
+    /**
+     * Determines whether the specified user is configurable. Provides the 
opportunity for a ConfigurableUserGroupProvider to prevent
+     * editing of a specific user. By default, all known users are 
configurable.
+     *
+     * @param user the user
+     * @return is configurable
+     */
+    default boolean isConfigurable(User user) {
+        if (user == null) {
+            throw new IllegalArgumentException("User cannot be null");
+        }
+
+        return getUser(user.getIdentifier()) != null;
+    }
+
+    /**
+     * The user represented by the provided instance will be updated based on 
the provided instance.
+     *
+     * @param user an updated user instance
+     * @return the updated user instance, or null if no matching user was found
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     * @throws IllegalStateException if there is already a user with the same 
identity
+     */
+    User updateUser(final User user) throws AuthorizationAccessException;
+
+    /**
+     * Deletes the given user.
+     *
+     * @param user the user to delete
+     * @return the user that was deleted, or null if no matching user was found
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    User deleteUser(User user) throws AuthorizationAccessException;
+
+    /**
+     * Deletes the user for the given ID.
+     *
+     * @param userIdentifier the user to delete
+     * @return the user that was deleted, or null if no matching user was found
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    User deleteUser(String userIdentifier) throws AuthorizationAccessException;
+
+    /**
+     * Adds a new group.
+     *
+     * @param group the Group to add
+     * @return the added Group
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     * @throws IllegalStateException if a group with the same name already 
exists
+     */
+    Group addGroup(Group group) throws AuthorizationAccessException;
+
+    /**
+     * Determines whether the specified group is configurable. Provides the 
opportunity for a ConfigurableUserGroupProvider to prevent
+     * editing of a specific group. By default, all known groups are 
configurable.
+     *
+     * @param group the group
+     * @return is configurable
+     */
+    default boolean isConfigurable(Group group) {
+        if (group == null) {
+            throw new IllegalArgumentException("Group cannot be null");
+        }
+
+        return getGroup(group.getIdentifier()) != null;
+    }
+
+    /**
+     * The group represented by the provided instance will be updated based on 
the provided instance.
+     *
+     * @param group an updated group instance
+     * @return the updated group instance, or null if no matching group was 
found
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     * @throws IllegalStateException if there is already a group with the same 
name
+     */
+    Group updateGroup(Group group) throws AuthorizationAccessException;
+
+    /**
+     * Deletes the given group.
+     *
+     * @param group the group to delete
+     * @return the deleted group, or null if no matching group was found
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    Group deleteGroup(Group group) throws AuthorizationAccessException;
+
+    /**
+     * Deletes the given group.
+     *
+     * @param groupIdentifier the group to delete
+     * @return the deleted group, or null if no matching group was found
+     * @throws AuthorizationAccessException if there was an unexpected error 
performing the operation
+     */
+    Group deleteGroup(String groupIdentifier) throws 
AuthorizationAccessException;
+}

Reply via email to