You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by pv...@apache.org on 2020/10/27 12:45:04 UTC

[nifi] branch main updated: NIFI-7719 Initial refactoring to NiFiClient in CLI to support additional authentication mechanisms

This is an automated email from the ASF dual-hosted git repository.

pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 6e9bef1  NIFI-7719 Initial refactoring to NiFiClient in CLI to support additional authentication mechanisms
6e9bef1 is described below

commit 6e9bef14287267b5d28129c0fb68fbc7a3e218d8
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Wed Aug 5 15:17:07 2020 -0400

    NIFI-7719 Initial refactoring to NiFiClient in CLI to support additional authentication mechanisms
    
    Added command options for basic auth and bearer token and updated NiFiClientFactory to create the appropriate RequestConfig
    
    Added get-token command for NiFi
    
    Update NiFi Registry CLI commands based on nifi-registry-client 0.8.0-SNAPSHOT
    
    Implementing commands for NiFi and NiFi Registry to obtain a token via SPNEGO and to logout a given token
    
    Add Keberos JAAS classes for using the ticket cache, update GetAccessTokenSpnego methods to fallback to ticket cache when no keytab or password is specified
    
    Use released 0.8.0 version of registry client
    
    Signed-off-by: Pierre Villard <pi...@gmail.com>
    
    This closes #4461.
---
 .../nifi/security/krb/KerberosTicketCacheUser.java |  43 +++
 .../security/krb/TicketCacheConfiguration.java     |  68 +++++
 .../impl/client/ExtendedNiFiRegistryClient.java    |  61 -----
 .../client/JerseyExtendedNiFiRegistryClient.java   | 299 ---------------------
 .../toolkit/cli/impl/client/NiFiClientFactory.java | 243 +++++++----------
 .../cli/impl/client/NiFiRegistryClientFactory.java | 231 ++++++++++++----
 .../toolkit/cli/impl/client/nifi/AccessClient.java |  29 ++
 .../toolkit/cli/impl/client/nifi/NiFiClient.java   | 104 ++-----
 .../cli/impl/client/nifi/RequestConfig.java        |  32 +++
 .../client/nifi/impl/AbstractJerseyClient.java     |  17 +-
 .../impl/client/nifi/impl/CRUDJerseyClient.java    |   7 +-
 .../impl/client/nifi/impl/JerseyAccessClient.java  |  87 ++++++
 .../client/nifi/impl/JerseyConnectionClient.java   |   9 +-
 .../client/nifi/impl/JerseyControllerClient.java   |   9 +-
 .../nifi/impl/JerseyControllerServicesClient.java  |   9 +-
 .../client/nifi/impl/JerseyCountersClient.java     |   9 +-
 .../impl/client/nifi/impl/JerseyFlowClient.java    |   9 +-
 .../client/nifi/impl/JerseyInputPortClient.java    |   9 +-
 .../impl/client/nifi/impl/JerseyNiFiClient.java    | 227 +++-------------
 .../client/nifi/impl/JerseyOutputPortClient.java   |   9 +-
 .../client/nifi/impl/JerseyParamContextClient.java |   9 +-
 .../client/nifi/impl/JerseyPoliciesClient.java     |  11 +-
 .../client/nifi/impl/JerseyProcessGroupClient.java |   9 +-
 .../client/nifi/impl/JerseyProcessorClient.java    |   9 +-
 .../client/nifi/impl/JerseyProvenanceClient.java   |   9 +-
 .../nifi/impl/JerseyRemoteProcessGroupClient.java  |   9 +-
 .../nifi/impl/JerseyReportingTasksClient.java      |  11 +-
 .../client/nifi/impl/JerseyTemplatesClient.java    |  11 +-
 .../impl/client/nifi/impl/JerseyTenantsClient.java |  11 +-
 .../client/nifi/impl/JerseyVersionsClient.java     |   9 +-
 .../nifi/impl/request/BasicAuthRequestConfig.java  |  55 ++++
 .../impl/request/BearerTokenRequestConfig.java     |  45 ++++
 .../impl/request/ProxiedEntityRequestConfig.java   |  62 +++++
 .../cli/impl/client/registry/PoliciesClient.java   |  65 -----
 .../cli/impl/client/registry/TenantsClient.java    | 122 ---------
 .../registry/impl/AbstractCRUDJerseyClient.java    |  91 -------
 .../client/registry/impl/JerseyPoliciesClient.java |  62 -----
 .../client/registry/impl/JerseyTenantsClient.java  |  91 -------
 .../toolkit/cli/impl/command/AbstractCommand.java  |   5 +
 .../toolkit/cli/impl/command/CommandOption.java    |  12 +
 .../cli/impl/command/nifi/NiFiCommandGroup.java    |   6 +
 .../impl/command/nifi/access/GetAccessToken.java   |  59 ++++
 .../command/nifi/access/GetAccessTokenSpnego.java  |  94 +++++++
 .../command/nifi/access/LogoutAccessToken.java     |  54 ++++
 .../registry/AbstractNiFiRegistryCommand.java      |   2 +-
 .../command/registry/NiFiRegistryCommandGroup.java |   6 +
 .../CreateUser.java => access/GetAccessToken.java} |  39 +--
 .../registry/access/GetAccessTokenSpnego.java      |  96 +++++++
 .../command/registry/access/LogoutAccessToken.java |  55 ++++
 .../registry/bucket/UpdateBucketPolicy.java        |  15 +-
 .../policy/CreateOrUpdateAccessPolicy.java         |  14 +-
 .../command/registry/policy/GetAccessPolicy.java   |  10 +-
 .../registry/tenant/AbstractListTenants.java       |  10 +-
 .../impl/command/registry/tenant/CreateUser.java   |  10 +-
 .../command/registry/tenant/CreateUserGroup.java   |  10 +-
 .../command/registry/tenant/ListUserGroups.java    |   2 +-
 .../impl/command/registry/tenant/ListUsers.java    |   2 +-
 .../impl/command/registry/tenant/UpdateUser.java   |  10 +-
 .../command/registry/tenant/UpdateUserGroup.java   |   9 +-
 pom.xml                                            |   3 +-
 60 files changed, 1281 insertions(+), 1444 deletions(-)

diff --git a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosTicketCacheUser.java b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosTicketCacheUser.java
new file mode 100644
index 0000000..adcb046
--- /dev/null
+++ b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosTicketCacheUser.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.security.krb;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+/**
+ * Used to perform actions as a Subject that already has a ticket in the ticket cache.
+ */
+public class KerberosTicketCacheUser extends AbstractKerberosUser {
+
+    public KerberosTicketCacheUser(final String principal) {
+        super(principal);
+    }
+
+    @Override
+    protected LoginContext createLoginContext(Subject subject) throws LoginException {
+        final Configuration config = new TicketCacheConfiguration(principal);
+        return new LoginContext("TicketCacheConf", subject, null, config);
+    }
+
+    // Visible for testing
+    Subject getSubject() {
+        return this.subject;
+    }
+}
diff --git a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/TicketCacheConfiguration.java b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/TicketCacheConfiguration.java
new file mode 100644
index 0000000..3336b80
--- /dev/null
+++ b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/TicketCacheConfiguration.java
@@ -0,0 +1,68 @@
+/*
+ * 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.security.krb;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Custom JAAS Configuration object for a provided principal that already has a ticket in the ticket cache.
+ */
+public class TicketCacheConfiguration extends Configuration {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(TicketCacheConfiguration.class);
+
+    private final String principal;
+
+    private final AppConfigurationEntry ticketCacheConfigEntry;
+
+    public TicketCacheConfiguration(final String principal) {
+        if (StringUtils.isBlank(principal)) {
+            throw new IllegalArgumentException("Principal cannot be null");
+        }
+
+        this.principal = principal;
+
+        final Map<String, String> options = new HashMap<>();
+        options.put("principal", principal);
+        options.put("refreshKrb5Config", "true");
+        options.put("useTicketCache", "true");
+
+        final String krbLoginModuleName = ConfigurationUtil.IS_IBM
+                ? ConfigurationUtil.IBM_KRB5_LOGIN_MODULE : ConfigurationUtil.SUN_KRB5_LOGIN_MODULE;
+
+        LOGGER.debug("krbLoginModuleName: {}, configuration options: {}", krbLoginModuleName, options);
+        this.ticketCacheConfigEntry = new AppConfigurationEntry(
+                krbLoginModuleName, AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+    }
+
+    @Override
+    public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+        return new AppConfigurationEntry[] {ticketCacheConfigEntry};
+    }
+
+    public String getPrincipal() {
+        return principal;
+    }
+
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/ExtendedNiFiRegistryClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/ExtendedNiFiRegistryClient.java
deleted file mode 100644
index cecce2e..0000000
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/ExtendedNiFiRegistryClient.java
+++ /dev/null
@@ -1,61 +0,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.
- */
-package org.apache.nifi.toolkit.cli.impl.client;
-
-import org.apache.nifi.registry.client.NiFiRegistryClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.PoliciesClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
-
-/**
- * Extends NiFiRegistry client with additional exposed service.
- *
- * Note: in longer term the functionality of this should be merged into the NiFiRegistryClient.
- */
-public interface ExtendedNiFiRegistryClient extends NiFiRegistryClient {
-
-    /**
-     * Returns client for interacting with tenants.
-     *
-     * @return the client for interacting with tenants
-     */
-    TenantsClient getTenantsClient();
-
-    /**
-     * Returns client for interacting with tenants.
-     *
-     * @param proxiedEntity The given proxied entities.
-     *
-     * @return the client for interacting with tenants on behalf of the given proxied entities.
-     */
-    TenantsClient getTenantsClient(String ... proxiedEntity);
-
-    /**
-     * Returns client for interacting with access policies.
-     *
-     * @return the client for interacting with access policies
-     */
-    PoliciesClient getPoliciesClient();
-
-    /**
-     * Returns client for interacting with access policies.
-     *
-     * @param proxiedEntity The given proxied entities.
-     *
-     * @return the client for interacting with access policies on behalf of the given proxied entities.
-     */
-    PoliciesClient getPoliciesClient(String ... proxiedEntity);
-}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/JerseyExtendedNiFiRegistryClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/JerseyExtendedNiFiRegistryClient.java
deleted file mode 100644
index 589ac97..0000000
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/JerseyExtendedNiFiRegistryClient.java
+++ /dev/null
@@ -1,299 +0,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.
- */
-package org.apache.nifi.toolkit.cli.impl.client;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.registry.bucket.BucketItem;
-import org.apache.nifi.registry.client.BucketClient;
-import org.apache.nifi.registry.client.BundleClient;
-import org.apache.nifi.registry.client.BundleVersionClient;
-import org.apache.nifi.registry.client.ExtensionClient;
-import org.apache.nifi.registry.client.ExtensionRepoClient;
-import org.apache.nifi.registry.client.FlowClient;
-import org.apache.nifi.registry.client.FlowSnapshotClient;
-import org.apache.nifi.registry.client.ItemsClient;
-import org.apache.nifi.registry.client.NiFiRegistryClient;
-import org.apache.nifi.registry.client.NiFiRegistryClientConfig;
-import org.apache.nifi.registry.client.UserClient;
-import org.apache.nifi.registry.client.impl.BucketItemDeserializer;
-import org.apache.nifi.registry.security.util.ProxiedEntitiesUtils;
-import org.apache.nifi.toolkit.cli.impl.client.registry.PoliciesClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.impl.JerseyPoliciesClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.impl.JerseyTenantsClient;
-import org.glassfish.jersey.client.ClientConfig;
-import org.glassfish.jersey.client.ClientProperties;
-import org.glassfish.jersey.client.RequestEntityProcessing;
-import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJaxbJsonProvider;
-import org.glassfish.jersey.media.multipart.MultiPartFeature;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLContext;
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.WebTarget;
-import java.io.IOException;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * Decorator around (Jersey based) NiFiRegistryClient in order to extend it's capabilities without
- * actually changing it.
- */
-public class JerseyExtendedNiFiRegistryClient implements ExtendedNiFiRegistryClient {
-    // Copied from JerseyNiFiRegistryClient!
-    static final String NIFI_REGISTRY_CONTEXT = "nifi-registry-api";
-    static final int DEFAULT_CONNECT_TIMEOUT = 10000;
-    static final int DEFAULT_READ_TIMEOUT = 10000;
-
-    private final NiFiRegistryClient delegate;
-    private final Client client;
-    private final WebTarget baseTarget;
-    private final TenantsClient tenantsClient;
-    private final PoliciesClient policiesClient;
-
-    public JerseyExtendedNiFiRegistryClient(final NiFiRegistryClient delegate, final NiFiRegistryClientConfig registryClientConfig) {
-        this.delegate = delegate;
-
-        // Copied from JerseyNiFiRegistryClient!
-        if (registryClientConfig == null) {
-            throw new IllegalArgumentException("NiFiRegistryClientConfig cannot be null");
-        }
-
-        String baseUrl = registryClientConfig.getBaseUrl();
-        if (StringUtils.isBlank(baseUrl)) {
-            throw new IllegalArgumentException("Base URL cannot be blank");
-        }
-
-        if (baseUrl.endsWith("/")) {
-            baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
-        }
-
-        if (!baseUrl.endsWith(NIFI_REGISTRY_CONTEXT)) {
-            baseUrl = baseUrl + "/" + NIFI_REGISTRY_CONTEXT;
-        }
-
-        try {
-            new URI(baseUrl);
-        } catch (final Exception e) {
-            throw new IllegalArgumentException("Invalid base URL: " + e.getMessage(), e);
-        }
-
-        final SSLContext sslContext = registryClientConfig.getSslContext();
-        final HostnameVerifier hostnameVerifier = registryClientConfig.getHostnameVerifier();
-
-        final ClientBuilder clientBuilder = ClientBuilder.newBuilder();
-        if (sslContext != null) {
-            clientBuilder.sslContext(sslContext);
-        }
-        if (hostnameVerifier != null) {
-            clientBuilder.hostnameVerifier(hostnameVerifier);
-        }
-
-        final int connectTimeout = registryClientConfig.getConnectTimeout() == null ? DEFAULT_CONNECT_TIMEOUT : registryClientConfig.getConnectTimeout();
-        final int readTimeout = registryClientConfig.getReadTimeout() == null ? DEFAULT_READ_TIMEOUT : registryClientConfig.getReadTimeout();
-
-        final ClientConfig clientConfig = new ClientConfig();
-        clientConfig.property(ClientProperties.CONNECT_TIMEOUT, connectTimeout);
-        clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeout);
-        clientConfig.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED);
-        clientConfig.register(jacksonJaxbJsonProvider());
-        clientBuilder.withConfig(clientConfig);
-
-        this.client = clientBuilder
-                .register(MultiPartFeature.class)
-                .build();
-
-        this.baseTarget = client.target(baseUrl);
-
-        this.tenantsClient = new JerseyTenantsClient(baseTarget);
-        this.policiesClient = new JerseyPoliciesClient(baseTarget);
-    }
-
-    @Override
-    public TenantsClient getTenantsClient() {
-        return tenantsClient;
-    }
-
-    @Override
-    public TenantsClient getTenantsClient(final String... proxiedEntity) {
-        final Map<String,String> headers = getHeaders(proxiedEntity);
-        return new JerseyTenantsClient(baseTarget, headers);
-    }
-
-    @Override
-    public PoliciesClient getPoliciesClient() {
-        return policiesClient;
-    }
-
-    @Override
-    public PoliciesClient getPoliciesClient(final String... proxiedEntity) {
-        final Map<String,String> headers = getHeaders(proxiedEntity);
-        return new JerseyPoliciesClient(baseTarget, headers);
-    }
-
-    @Override
-    public BucketClient getBucketClient() {
-        return delegate.getBucketClient();
-    }
-
-    @Override
-    public BucketClient getBucketClient(final String... proxiedEntity) {
-        return delegate.getBucketClient(proxiedEntity);
-    }
-
-    @Override
-    public FlowClient getFlowClient() {
-        return delegate.getFlowClient();
-    }
-
-    @Override
-    public FlowClient getFlowClient(final String... proxiedEntity) {
-        return delegate.getFlowClient(proxiedEntity);
-    }
-
-    @Override
-    public FlowSnapshotClient getFlowSnapshotClient() {
-        return delegate.getFlowSnapshotClient();
-    }
-
-    @Override
-    public FlowSnapshotClient getFlowSnapshotClient(final String... proxiedEntity) {
-        return delegate.getFlowSnapshotClient(proxiedEntity);
-    }
-
-    @Override
-    public ItemsClient getItemsClient() {
-        return delegate.getItemsClient();
-    }
-
-    @Override
-    public ItemsClient getItemsClient(final String... proxiedEntity) {
-        return delegate.getItemsClient(proxiedEntity);
-    }
-
-    @Override
-    public UserClient getUserClient() {
-        return delegate.getUserClient();
-    }
-
-    @Override
-    public UserClient getUserClient(final String... proxiedEntity) {
-        return delegate.getUserClient(proxiedEntity);
-    }
-
-    @Override
-    public BundleClient getBundleClient() {
-        return delegate.getBundleClient();
-    }
-
-    @Override
-    public BundleClient getBundleClient(final String... proxiedEntity) {
-        return delegate.getBundleClient(proxiedEntity);
-    }
-
-    @Override
-    public BundleVersionClient getBundleVersionClient() {
-        return delegate.getBundleVersionClient();
-    }
-
-    @Override
-    public BundleVersionClient getBundleVersionClient(final String... proxiedEntity) {
-        return delegate.getBundleVersionClient(proxiedEntity);
-    }
-
-    @Override
-    public ExtensionRepoClient getExtensionRepoClient() {
-        return delegate.getExtensionRepoClient();
-    }
-
-    @Override
-    public ExtensionRepoClient getExtensionRepoClient(final String... proxiedEntity) {
-        return delegate.getExtensionRepoClient(proxiedEntity);
-    }
-
-    @Override
-    public ExtensionClient getExtensionClient() {
-        return delegate.getExtensionClient();
-    }
-
-    @Override
-    public ExtensionClient getExtensionClient(final String... proxiedEntity) {
-        return delegate.getExtensionClient(proxiedEntity);
-    }
-
-    @Override
-    public void close() throws IOException {
-        delegate.close();
-
-        if (this.client != null) {
-            try {
-                this.client.close();
-            } catch (Exception e) {
-
-            }
-        }
-    }
-
-    // Copied from JerseyNiFiRegistryClient!
-    private Map<String,String> getHeaders(String[] proxiedEntities) {
-        final String proxiedEntitiesValue = getProxiedEntitesValue(proxiedEntities);
-
-        final Map<String,String> headers = new HashMap<>();
-        if (proxiedEntitiesValue != null) {
-            headers.put(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxiedEntitiesValue);
-        }
-        return headers;
-    }
-
-    // Copied from JerseyNiFiRegistryClient!
-    private String getProxiedEntitesValue(String[] proxiedEntities) {
-        if (proxiedEntities == null) {
-            return null;
-        }
-
-        final List<String> proxiedEntityChain = Arrays.stream(proxiedEntities).map(ProxiedEntitiesUtils::formatProxyDn).collect(Collectors.toList());
-        return StringUtils.join(proxiedEntityChain, "");
-    }
-
-    // Copied from JerseyNiFiRegistryClient!
-    private static JacksonJaxbJsonProvider jacksonJaxbJsonProvider() {
-        JacksonJaxbJsonProvider jacksonJaxbJsonProvider = new JacksonJaxbJsonProvider();
-
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.setPropertyInclusion(JsonInclude.Value.construct(JsonInclude.Include.NON_NULL, JsonInclude.Include.NON_NULL));
-        mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector(mapper.getTypeFactory()));
-        // Ignore unknown properties so that deployed client remain compatible with future versions of NiFi Registry that add new fields
-        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
-
-        SimpleModule module = new SimpleModule();
-        module.addDeserializer(BucketItem[].class, new BucketItemDeserializer());
-        mapper.registerModule(module);
-
-        jacksonJaxbJsonProvider.setMapper(mapper);
-        return jacksonJaxbJsonProvider;
-    }
-}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/NiFiClientFactory.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/NiFiClientFactory.java
index 876ee4f..d9d6ded 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/NiFiClientFactory.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/NiFiClientFactory.java
@@ -18,8 +18,10 @@ package org.apache.nifi.toolkit.cli.impl.client;
 
 import org.apache.commons.cli.MissingOptionException;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
 import org.apache.nifi.registry.security.util.KeystoreType;
 import org.apache.nifi.toolkit.cli.api.ClientFactory;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.AccessClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ConnectionClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerServicesClient;
@@ -36,10 +38,14 @@ import org.apache.nifi.toolkit.cli.impl.client.nifi.ProcessorClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ProvenanceClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.RemoteProcessGroupClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ReportingTasksClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.TemplatesClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.VersionsClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.impl.JerseyNiFiClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.impl.request.BasicAuthRequestConfig;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.impl.request.BearerTokenRequestConfig;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.impl.request.ProxiedEntityRequestConfig;
 import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
 
 import java.io.IOException;
@@ -72,6 +78,11 @@ public class NiFiClientFactory implements ClientFactory<NiFiClient> {
         final String proxiedEntity = properties.getProperty(CommandOption.PROXIED_ENTITY.getLongName());
         final String protocol = properties.getProperty(CommandOption.PROTOCOL.getLongName());
 
+        final String basicAuthUsername = properties.getProperty(CommandOption.BASIC_AUTH_USER.getLongName());
+        final String basicAuthPassword = properties.getProperty(CommandOption.BASIC_AUTH_PASSWORD.getLongName());
+
+        final String bearerToken = properties.getProperty(CommandOption.BEARER_TOKEN.getLongName());
+
         final boolean secureUrl = url.startsWith("https");
 
         if (secureUrl && (StringUtils.isBlank(truststore)
@@ -82,6 +93,29 @@ public class NiFiClientFactory implements ClientFactory<NiFiClient> {
                     + ", and " + CommandOption.TRUSTSTORE_PASSWORD.getLongName() + " are required when using an https url");
         }
 
+        if (!StringUtils.isBlank(proxiedEntity) && (!StringUtils.isBlank(basicAuthUsername) || !StringUtils.isBlank(basicAuthPassword))) {
+            throw new IllegalStateException(CommandOption.PROXIED_ENTITY.getLongName() + " and basic authentication can not be used together");
+        }
+
+        if (!StringUtils.isBlank(proxiedEntity) && !StringUtils.isBlank(bearerToken)) {
+            throw new IllegalStateException(CommandOption.PROXIED_ENTITY.getLongName() + " and "
+                    + CommandOption.BEARER_TOKEN.getLongName() + " can not be used together");
+        }
+
+        if (!StringUtils.isBlank(bearerToken) && (!StringUtils.isBlank(basicAuthUsername) || !StringUtils.isBlank(basicAuthPassword))) {
+            throw new IllegalStateException(CommandOption.BEARER_TOKEN.getLongName() + " and basic authentication can not be used together");
+        }
+
+        if (!StringUtils.isBlank(basicAuthUsername) && StringUtils.isBlank(basicAuthPassword)) {
+            throw new MissingOptionException(CommandOption.BASIC_AUTH_PASSWORD.getLongName()
+                    + " is required when specifying " + CommandOption.BASIC_AUTH_USER.getLongName());
+        }
+
+        if (!StringUtils.isBlank(basicAuthPassword) && StringUtils.isBlank(basicAuthUsername)) {
+            throw new MissingOptionException(CommandOption.BASIC_AUTH_USER.getLongName()
+                    + " is required when specifying " + CommandOption.BASIC_AUTH_PASSWORD.getLongName());
+        }
+
         final NiFiClientConfig.Builder clientConfigBuilder = new NiFiClientConfig.Builder()
                 .baseUrl(url);
 
@@ -112,7 +146,6 @@ public class NiFiClientFactory implements ClientFactory<NiFiClient> {
             }
         }
 
-
         if (!StringUtils.isBlank(connectionTimeout)) {
             try {
                 Integer timeout = Integer.valueOf(connectionTimeout);
@@ -133,9 +166,17 @@ public class NiFiClientFactory implements ClientFactory<NiFiClient> {
 
         final NiFiClient client = new JerseyNiFiClient.Builder().config(clientConfigBuilder.build()).build();
 
-        // if a proxied entity was specified then return a wrapped client, otherwise return the regular client
+        // return a wrapped client based which arguments were provided, otherwise return the regular client
+
         if (!StringUtils.isBlank(proxiedEntity)) {
-            return new NiFiClientFactory.ProxiedNiFiClient(client, proxiedEntity);
+            final RequestConfig proxiedEntityConfig = new ProxiedEntityRequestConfig(proxiedEntity);
+            return new NiFiClientWithRequestConfig(client, proxiedEntityConfig);
+        } else if (!StringUtils.isBlank(bearerToken)) {
+            final RequestConfig bearerTokenConfig = new BearerTokenRequestConfig(bearerToken);
+            return new NiFiClientWithRequestConfig(client, bearerTokenConfig);
+        } else if (!StringUtils.isBlank(basicAuthUsername) && !StringUtils.isBlank(basicAuthPassword)) {
+            final RequestConfig basicAuthConfig = new BasicAuthRequestConfig(basicAuthUsername, basicAuthPassword);
+            return new NiFiClientWithRequestConfig(client, basicAuthConfig);
         } else {
             return client;
         }
@@ -143,271 +184,191 @@ public class NiFiClientFactory implements ClientFactory<NiFiClient> {
 
     /**
      * Wraps a NiFiClient and ensures that all methods to obtain a more specific client will
-     * call the proxied-entity variation so that callers don't have to care if proxying is taking place.
+     * call the RequestConfig variation so that callers don't have to pass in the config on every call.
      */
-    private static class ProxiedNiFiClient implements NiFiClient {
+    private static class NiFiClientWithRequestConfig implements NiFiClient {
 
-        private final String proxiedEntity;
         private final NiFiClient wrappedClient;
+        private final RequestConfig requestConfig;
 
-        public ProxiedNiFiClient(final NiFiClient wrappedClient, final String proxiedEntity) {
-            this.proxiedEntity = proxiedEntity;
+        public NiFiClientWithRequestConfig(final NiFiClient wrappedClient, final RequestConfig requestConfig) {
             this.wrappedClient = wrappedClient;
+            this.requestConfig = Validate.notNull(requestConfig);
         }
 
         @Override
         public ControllerClient getControllerClient() {
-            return wrappedClient.getControllerClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getControllerClient(requestConfig);
         }
 
         @Override
-        public ControllerClient getControllerClientForProxiedEntities(String... proxiedEntity) {
-            return wrappedClient.getControllerClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public ControllerClient getControllerClientForToken(String token) {
-            return wrappedClient.getControllerClientForToken(token);
+        public ControllerClient getControllerClient(RequestConfig requestConfig) {
+            return wrappedClient.getControllerClient(requestConfig);
         }
 
         @Override
         public ControllerServicesClient getControllerServicesClient() {
-            return wrappedClient.getControllerServicesClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public ControllerServicesClient getControllerServicesClientForProxiedEntities(String... proxiedEntity) {
-            return wrappedClient.getControllerServicesClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getControllerServicesClient(requestConfig);
         }
 
         @Override
-        public ControllerServicesClient getControllerServicesClientForToken(String token) {
-            return wrappedClient.getControllerServicesClientForToken(token);
+        public ControllerServicesClient getControllerServicesClient(RequestConfig requestConfig) {
+            return wrappedClient.getControllerServicesClient(requestConfig);
         }
 
         @Override
         public FlowClient getFlowClient() {
-            return wrappedClient.getFlowClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getFlowClient(requestConfig);
         }
 
         @Override
-        public FlowClient getFlowClientForProxiedEntities(String... proxiedEntity) {
-            return wrappedClient.getFlowClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public FlowClient getFlowClientForToken(String token) {
-            return wrappedClient.getFlowClientForToken(token);
+        public FlowClient getFlowClient(RequestConfig requestConfig) {
+            return wrappedClient.getFlowClient(requestConfig);
         }
 
         @Override
         public ProcessGroupClient getProcessGroupClient() {
-            return wrappedClient.getProcessGroupClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getProcessGroupClient(requestConfig);
         }
 
         @Override
-        public ProcessGroupClient getProcessGroupClientForProxiedEntities(String... proxiedEntity) {
-            return wrappedClient.getProcessGroupClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public ProcessGroupClient getProcessGroupClientForToken(String token) {
-            return wrappedClient.getProcessGroupClientForToken(token);
+        public ProcessGroupClient getProcessGroupClient(RequestConfig requestConfig) {
+            return wrappedClient.getProcessGroupClient(requestConfig);
         }
 
         @Override
         public ProcessorClient getProcessorClient() {
-            return wrappedClient.getProcessorClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getProcessorClient(requestConfig);
         }
 
         @Override
-        public ProcessorClient getProcessorClientForProxiedEntities(final String... proxiedEntity) {
-            return wrappedClient.getProcessorClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public ProcessorClient getProcessorClientForToken(final String token) {
-            return wrappedClient.getProcessorClientForToken(token);
+        public ProcessorClient getProcessorClient(RequestConfig requestConfig) {
+            return wrappedClient.getProcessorClient(requestConfig);
         }
 
         @Override
         public VersionsClient getVersionsClient() {
-            return wrappedClient.getVersionsClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public VersionsClient getVersionsClientForProxiedEntities(String... proxiedEntity) {
-            return wrappedClient.getVersionsClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getVersionsClient(requestConfig);
         }
 
         @Override
-        public VersionsClient getVersionsClientForToken(String token) {
-            return wrappedClient.getVersionsClientForToken(token);
+        public VersionsClient getVersionsClient(RequestConfig requestConfig) {
+            return wrappedClient.getVersionsClient(requestConfig);
         }
 
         @Override
         public TenantsClient getTenantsClient() {
-            return wrappedClient.getTenantsClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public TenantsClient getTenantsClientForProxiedEntities(String... proxiedEntity) {
-            return wrappedClient.getTenantsClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getTenantsClient(requestConfig);
         }
 
         @Override
-        public TenantsClient getTenantsClientForToken(String token) {
-            return wrappedClient.getTenantsClientForToken(token);
+        public TenantsClient getTenantsClient(RequestConfig requestConfig) {
+            return wrappedClient.getTenantsClient(requestConfig);
         }
 
         @Override
         public PoliciesClient getPoliciesClient() {
-            return wrappedClient.getPoliciesClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getPoliciesClient(requestConfig);
         }
 
         @Override
-        public PoliciesClient getPoliciesClientForProxiedEntities(String... proxiedEntity) {
-            return wrappedClient.getPoliciesClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public PoliciesClient getPoliciesClientForToken(String token) {
-            return wrappedClient.getPoliciesClientForToken(token);
+        public PoliciesClient getPoliciesClient(RequestConfig requestConfig) {
+            return wrappedClient.getPoliciesClient(requestConfig);
         }
 
         @Override
         public TemplatesClient getTemplatesClient() {
-            return wrappedClient.getTemplatesClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public TemplatesClient getTemplatesClientForProxiedEntities(String... proxiedEntity) {
-            return wrappedClient.getTemplatesClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getTemplatesClient(requestConfig);
         }
 
         @Override
-        public TemplatesClient getTemplatesClientForToken(String token) {
-            return wrappedClient.getTemplatesClientForToken(token);
+        public TemplatesClient getTemplatesClient(RequestConfig requestConfig) {
+            return wrappedClient.getTemplatesClient(requestConfig);
         }
 
         @Override
         public ReportingTasksClient getReportingTasksClient() {
-            return wrappedClient.getReportingTasksClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public ReportingTasksClient getReportingTasksClientForProxiedEntities(String... proxiedEntity) {
-            return wrappedClient.getReportingTasksClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getReportingTasksClient(requestConfig);
         }
 
         @Override
-        public ReportingTasksClient getReportingTasksClientForToken(String token) {
-            return wrappedClient.getReportingTasksClientForToken(token);
+        public ReportingTasksClient getReportingTasksClient(RequestConfig requestConfig) {
+            return wrappedClient.getReportingTasksClient(requestConfig);
         }
 
         @Override
         public ParamContextClient getParamContextClient() {
-            return wrappedClient.getParamContextClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public ParamContextClient getParamContextClientForProxiedEntities(String... proxiedEntity) {
-            return wrappedClient.getParamContextClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getParamContextClient(requestConfig);
         }
 
         @Override
-        public ParamContextClient getParamContextClientForToken(String token) {
-            return wrappedClient.getParamContextClientForToken(token);
+        public ParamContextClient getParamContextClient(RequestConfig requestConfig) {
+            return wrappedClient.getParamContextClient(requestConfig);
         }
 
         @Override
         public CountersClient getCountersClient() {
-            return wrappedClient.getCountersClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getCountersClient(requestConfig);
         }
 
         @Override
-        public CountersClient getCountersClientForProxiedEntities(final String... proxiedEntity) {
-            return wrappedClient.getCountersClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public CountersClient getCountersClientForToken(final String token) {
-            return wrappedClient.getCountersClientForToken(token);
+        public CountersClient getCountersClient(RequestConfig requestConfig) {
+            return wrappedClient.getCountersClient(requestConfig);
         }
 
         @Override
         public ConnectionClient getConnectionClient() {
-            return wrappedClient.getConnectionClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public ConnectionClient getConnectionClientForProxiedEntities(final String... proxiedEntity) {
-            return wrappedClient.getConnectionClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getConnectionClient(requestConfig);
         }
 
         @Override
-        public ConnectionClient getConnectionClientForToken(final String token) {
-            return wrappedClient.getConnectionClientForToken(token);
+        public ConnectionClient getConnectionClient(RequestConfig requestConfig) {
+            return wrappedClient.getConnectionClient(requestConfig);
         }
 
         @Override
         public RemoteProcessGroupClient getRemoteProcessGroupClient() {
-            return wrappedClient.getRemoteProcessGroupClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getRemoteProcessGroupClient(requestConfig);
         }
 
         @Override
-        public RemoteProcessGroupClient getRemoteProcessGroupClientForProxiedEntities(final String... proxiedEntity) {
-            return wrappedClient.getRemoteProcessGroupClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public RemoteProcessGroupClient getRemoteProcessGroupClientForToken(final String token) {
-            return wrappedClient.getRemoteProcessGroupClientForToken(token);
+        public RemoteProcessGroupClient getRemoteProcessGroupClient(RequestConfig requestConfig) {
+            return wrappedClient.getRemoteProcessGroupClient(requestConfig);
         }
 
         @Override
         public InputPortClient getInputPortClient() {
-            return wrappedClient.getInputPortClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public InputPortClient getInputPortClientForProxiedEntities(final String... proxiedEntity) {
-            return wrappedClient.getInputPortClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getInputPortClient(requestConfig);
         }
 
         @Override
-        public InputPortClient getInputPortClientForToken(final String token) {
-            return wrappedClient.getInputPortClientForToken(proxiedEntity);
+        public InputPortClient getInputPortClient(RequestConfig requestConfig) {
+            return wrappedClient.getInputPortClient(requestConfig);
         }
 
         @Override
         public OutputPortClient getOutputPortClient() {
-            return wrappedClient.getOutputPortClientForProxiedEntities(proxiedEntity);
-        }
-
-        @Override
-        public OutputPortClient getOutputPortClientForProxiedEntities(final String... proxiedEntity) {
-            return wrappedClient.getOutputPortClientForProxiedEntities(proxiedEntity);
+            return wrappedClient.getOutputPortClient(requestConfig);
         }
 
         @Override
-        public OutputPortClient getOutputPortClientForToken(final String token) {
-            return wrappedClient.getOutputPortClientForToken(proxiedEntity);
+        public OutputPortClient getOutputPortClient(RequestConfig requestConfig) {
+            return wrappedClient.getOutputPortClient(requestConfig);
         }
 
         @Override
         public ProvenanceClient getProvenanceClient() {
-            return wrappedClient.getProvenanceClient();
+            return wrappedClient.getProvenanceClient(requestConfig);
         }
 
         @Override
-        public ProvenanceClient getProvenanceClientForProxiedEntities(final String... proxiedEntity) {
-            return wrappedClient.getProvenanceClientForProxiedEntities(proxiedEntity);
+        public ProvenanceClient getProvenanceClient(RequestConfig requestConfig) {
+            return wrappedClient.getProvenanceClient(requestConfig);
         }
 
         @Override
-        public ProvenanceClient getProvenanceClientForToken(final String token) {
-            return wrappedClient.getProvenanceClientForToken(token);
+        public AccessClient getAccessClient() {
+            return wrappedClient.getAccessClient();
         }
 
         @Override
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/NiFiRegistryClientFactory.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/NiFiRegistryClientFactory.java
index 0416de2..16dc962 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/NiFiRegistryClientFactory.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/NiFiRegistryClientFactory.java
@@ -18,6 +18,7 @@ package org.apache.nifi.toolkit.cli.impl.client;
 
 import org.apache.commons.cli.MissingOptionException;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.client.AccessClient;
 import org.apache.nifi.registry.client.BucketClient;
 import org.apache.nifi.registry.client.BundleClient;
 import org.apache.nifi.registry.client.BundleVersionClient;
@@ -28,12 +29,16 @@ import org.apache.nifi.registry.client.FlowSnapshotClient;
 import org.apache.nifi.registry.client.ItemsClient;
 import org.apache.nifi.registry.client.NiFiRegistryClient;
 import org.apache.nifi.registry.client.NiFiRegistryClientConfig;
+import org.apache.nifi.registry.client.PoliciesClient;
+import org.apache.nifi.registry.client.RequestConfig;
+import org.apache.nifi.registry.client.TenantsClient;
 import org.apache.nifi.registry.client.UserClient;
 import org.apache.nifi.registry.client.impl.JerseyNiFiRegistryClient;
+import org.apache.nifi.registry.client.impl.request.BasicAuthRequestConfig;
+import org.apache.nifi.registry.client.impl.request.BearerTokenRequestConfig;
+import org.apache.nifi.registry.client.impl.request.ProxiedEntityRequestConfig;
 import org.apache.nifi.registry.security.util.KeystoreType;
 import org.apache.nifi.toolkit.cli.api.ClientFactory;
-import org.apache.nifi.toolkit.cli.impl.client.registry.PoliciesClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
 
 import java.io.IOException;
@@ -64,6 +69,12 @@ public class NiFiRegistryClientFactory implements ClientFactory<NiFiRegistryClie
         final String truststorePasswd = properties.getProperty(CommandOption.TRUSTSTORE_PASSWORD.getLongName());
 
         final String proxiedEntity = properties.getProperty(CommandOption.PROXIED_ENTITY.getLongName());
+        final String protocol = properties.getProperty(CommandOption.PROTOCOL.getLongName());
+
+        final String basicAuthUsername = properties.getProperty(CommandOption.BASIC_AUTH_USER.getLongName());
+        final String basicAuthPassword = properties.getProperty(CommandOption.BASIC_AUTH_PASSWORD.getLongName());
+
+        final String bearerToken = properties.getProperty(CommandOption.BEARER_TOKEN.getLongName());
 
         final boolean secureUrl = url.startsWith("https");
 
@@ -75,6 +86,29 @@ public class NiFiRegistryClientFactory implements ClientFactory<NiFiRegistryClie
                     + ", and " + CommandOption.TRUSTSTORE_PASSWORD.getLongName() + " are required when using an https url");
         }
 
+        if (!StringUtils.isBlank(proxiedEntity) && (!StringUtils.isBlank(basicAuthUsername) || !StringUtils.isBlank(basicAuthPassword))) {
+            throw new IllegalStateException(CommandOption.PROXIED_ENTITY.getLongName() + " and basic authentication can not be used together");
+        }
+
+        if (!StringUtils.isBlank(proxiedEntity) && !StringUtils.isBlank(bearerToken)) {
+            throw new IllegalStateException(CommandOption.PROXIED_ENTITY.getLongName() + " and "
+                    + CommandOption.BEARER_TOKEN.getLongName() + " can not be used together");
+        }
+
+        if (!StringUtils.isBlank(bearerToken) && (!StringUtils.isBlank(basicAuthUsername) || !StringUtils.isBlank(basicAuthPassword))) {
+            throw new IllegalStateException(CommandOption.BEARER_TOKEN.getLongName() + " and basic authentication can not be used together");
+        }
+
+        if (!StringUtils.isBlank(basicAuthUsername) && StringUtils.isBlank(basicAuthPassword)) {
+            throw new MissingOptionException(CommandOption.BASIC_AUTH_PASSWORD.getLongName()
+                    + " is required when specifying " + CommandOption.BASIC_AUTH_USER.getLongName());
+        }
+
+        if (!StringUtils.isBlank(basicAuthPassword) && StringUtils.isBlank(basicAuthUsername)) {
+            throw new MissingOptionException(CommandOption.BASIC_AUTH_USER.getLongName()
+                    + " is required when specifying " + CommandOption.BASIC_AUTH_PASSWORD.getLongName());
+        }
+
         final NiFiRegistryClientConfig.Builder clientConfigBuilder = new NiFiRegistryClientConfig.Builder()
                 .baseUrl(url);
 
@@ -100,6 +134,9 @@ public class NiFiRegistryClientFactory implements ClientFactory<NiFiRegistryClie
             if (!StringUtils.isBlank(truststorePasswd)) {
                 clientConfigBuilder.truststorePassword(truststorePasswd);
             }
+            if (!StringUtils.isBlank(protocol)) {
+                clientConfigBuilder.protocol(protocol);
+            }
         }
 
         if (!StringUtils.isBlank(connectionTimeout)) {
@@ -122,141 +159,245 @@ public class NiFiRegistryClientFactory implements ClientFactory<NiFiRegistryClie
 
         final NiFiRegistryClientConfig clientConfig = clientConfigBuilder.build();
         final NiFiRegistryClient client = new JerseyNiFiRegistryClient.Builder().config(clientConfig).build();
-        final ExtendedNiFiRegistryClient extendedClient = new JerseyExtendedNiFiRegistryClient(client, clientConfig);
 
-        // if a proxied entity was specified then return a wrapped client, otherwise return the regular client
+        // return a wrapped client based which arguments were provided, otherwise return the regular client
+
         if (!StringUtils.isBlank(proxiedEntity)) {
-            return new ProxiedNiFiRegistryClient(extendedClient, proxiedEntity);
+            final RequestConfig proxiedEntityConfig = new ProxiedEntityRequestConfig(proxiedEntity);
+            return new NiFiRegistryClientWithRequestConfig(client, proxiedEntityConfig);
+        } else if (!StringUtils.isBlank(bearerToken)) {
+            final RequestConfig bearerTokenConfig = new BearerTokenRequestConfig(bearerToken);
+            return new NiFiRegistryClientWithRequestConfig(client, bearerTokenConfig);
+        } else if (!StringUtils.isBlank(basicAuthUsername) && !StringUtils.isBlank(basicAuthPassword)) {
+            final RequestConfig basicAuthConfig = new BasicAuthRequestConfig(basicAuthUsername, basicAuthPassword);
+            return new NiFiRegistryClientWithRequestConfig(client, basicAuthConfig);
         } else {
-            return extendedClient;
+            return client;
         }
     }
 
     /**
      * Wraps a NiFiRegistryClient and ensures that all methods to obtain a more specific client will
-     * call the proxied-entity variation so that callers don't have to care if proxying is taking place.
+     * call the RequestConfig variation so that callers don't have to pass in the config one every call.
      */
-    private static class ProxiedNiFiRegistryClient implements ExtendedNiFiRegistryClient {
+    private static class NiFiRegistryClientWithRequestConfig implements NiFiRegistryClient {
 
-        private final ExtendedNiFiRegistryClient client;
-        private final String proxiedEntity;
+        private final NiFiRegistryClient client;
+        private final RequestConfig requestConfig;
 
-        public ProxiedNiFiRegistryClient(final ExtendedNiFiRegistryClient client, final String proxiedEntity) {
+        public NiFiRegistryClientWithRequestConfig(final NiFiRegistryClient client, final RequestConfig requestConfig) {
             this.client = client;
-            this.proxiedEntity = proxiedEntity;
+            this.requestConfig = requestConfig;
         }
 
+        //----------------------------------------------------------------------
+
         @Override
         public BucketClient getBucketClient() {
-            return getBucketClient(proxiedEntity);
+            return client.getBucketClient(requestConfig);
+        }
+
+        @Override
+        public BucketClient getBucketClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getBucketClient(requestConfig);
         }
 
         @Override
-        public BucketClient getBucketClient(String... proxiedEntity) {
-            return client.getBucketClient(proxiedEntity);
+        public BucketClient getBucketClient(RequestConfig requestConfig) {
+            return client.getBucketClient(requestConfig);
         }
 
+        //----------------------------------------------------------------------
+
         @Override
         public FlowClient getFlowClient() {
-            return getFlowClient(proxiedEntity);
+            return client.getFlowClient(requestConfig);
+        }
+
+        @Override
+        public FlowClient getFlowClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getFlowClient(requestConfig);
         }
 
         @Override
-        public FlowClient getFlowClient(String... proxiedEntity) {
-            return client.getFlowClient(proxiedEntity);
+        public FlowClient getFlowClient(RequestConfig requestConfig) {
+            return client.getFlowClient(requestConfig);
         }
 
+        //----------------------------------------------------------------------
+
         @Override
         public FlowSnapshotClient getFlowSnapshotClient() {
-            return getFlowSnapshotClient(proxiedEntity);
+            return client.getFlowSnapshotClient(requestConfig);
+        }
+
+        @Override
+        public FlowSnapshotClient getFlowSnapshotClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getFlowSnapshotClient(requestConfig);
         }
 
         @Override
-        public FlowSnapshotClient getFlowSnapshotClient(String... proxiedEntity) {
-            return client.getFlowSnapshotClient(proxiedEntity);
+        public FlowSnapshotClient getFlowSnapshotClient(RequestConfig requestConfig) {
+            return client.getFlowSnapshotClient(requestConfig);
         }
 
+        //----------------------------------------------------------------------
+
         @Override
         public ItemsClient getItemsClient() {
-            return getItemsClient(proxiedEntity);
+            return client.getItemsClient(requestConfig);
+        }
+
+        @Override
+        public ItemsClient getItemsClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getItemsClient(requestConfig);
         }
 
         @Override
-        public ItemsClient getItemsClient(String... proxiedEntity) {
-            return client.getItemsClient(proxiedEntity);
+        public ItemsClient getItemsClient(RequestConfig requestConfig) {
+            return client.getItemsClient(requestConfig);
         }
 
+        //----------------------------------------------------------------------
+
         @Override
         public UserClient getUserClient() {
-            return getUserClient(proxiedEntity);
+            return client.getUserClient(requestConfig);
         }
 
         @Override
-        public UserClient getUserClient(String... proxiedEntity) {
-            return client.getUserClient(proxiedEntity);
+        public UserClient getUserClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getUserClient(requestConfig);
         }
 
         @Override
+        public UserClient getUserClient(RequestConfig requestConfig) {
+            return client.getUserClient(requestConfig);
+        }
+
+        //----------------------------------------------------------------------
+
+        @Override
         public BundleClient getBundleClient() {
-            return getBundleClient(proxiedEntity);
+            return client.getBundleClient(requestConfig);
+        }
+
+        @Override
+        public BundleClient getBundleClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getBundleClient(requestConfig);
         }
 
         @Override
-        public BundleClient getBundleClient(String... proxiedEntity) {
-            return client.getBundleClient(proxiedEntity);
+        public BundleClient getBundleClient(RequestConfig requestConfig) {
+            return client.getBundleClient(requestConfig);
         }
 
+        //----------------------------------------------------------------------
+
         @Override
         public BundleVersionClient getBundleVersionClient() {
-            return getBundleVersionClient(proxiedEntity);
+            return client.getBundleVersionClient(requestConfig);
+        }
+
+        @Override
+        public BundleVersionClient getBundleVersionClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getBundleVersionClient(requestConfig);
         }
 
         @Override
-        public BundleVersionClient getBundleVersionClient(String... proxiedEntity) {
-            return client.getBundleVersionClient(proxiedEntity);
+        public BundleVersionClient getBundleVersionClient(RequestConfig requestConfig) {
+            return client.getBundleVersionClient(requestConfig);
         }
 
+        //----------------------------------------------------------------------
+
         @Override
         public ExtensionRepoClient getExtensionRepoClient() {
-            return getExtensionRepoClient(proxiedEntity);
+            return client.getExtensionRepoClient(requestConfig);
+        }
+
+        @Override
+        public ExtensionRepoClient getExtensionRepoClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getExtensionRepoClient(requestConfig);
         }
 
         @Override
-        public ExtensionRepoClient getExtensionRepoClient(String... proxiedEntity) {
-            return client.getExtensionRepoClient(proxiedEntity);
+        public ExtensionRepoClient getExtensionRepoClient(RequestConfig requestConfig) {
+            return client.getExtensionRepoClient(requestConfig);
         }
 
+        //----------------------------------------------------------------------
+
         @Override
         public ExtensionClient getExtensionClient() {
-            return getExtensionClient(proxiedEntity);
+            return client.getExtensionClient(requestConfig);
         }
 
         @Override
-        public ExtensionClient getExtensionClient(String... proxiedEntity) {
-            return client.getExtensionClient(proxiedEntity);
+        public ExtensionClient getExtensionClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getExtensionClient(requestConfig);
         }
 
         @Override
+        public ExtensionClient getExtensionClient(RequestConfig requestConfig) {
+            return client.getExtensionClient(requestConfig);
+        }
+
+        //----------------------------------------------------------------------
+
+        @Override
         public TenantsClient getTenantsClient() {
-            return getTenantsClient(proxiedEntity);
+            return client.getTenantsClient(requestConfig);
+        }
+
+        @Override
+        public TenantsClient getTenantsClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getTenantsClient(requestConfig);
         }
 
         @Override
-        public TenantsClient getTenantsClient(String... proxiedEntity) {
-            return client.getTenantsClient(proxiedEntity);
+        public TenantsClient getTenantsClient(RequestConfig requestConfig) {
+            return client.getTenantsClient(requestConfig);
         }
 
+        //----------------------------------------------------------------------
+
         @Override
         public PoliciesClient getPoliciesClient() {
-            return getPoliciesClient(proxiedEntity);
+            return client.getPoliciesClient(requestConfig);
         }
 
         @Override
-        public PoliciesClient getPoliciesClient(String... proxiedEntity) {
-            return client.getPoliciesClient(proxiedEntity);
+        public PoliciesClient getPoliciesClient(String... proxiedEntities) {
+            final RequestConfig requestConfig = new ProxiedEntityRequestConfig(proxiedEntities);
+            return client.getPoliciesClient(requestConfig);
         }
 
         @Override
+        public PoliciesClient getPoliciesClient(RequestConfig requestConfig) {
+            return client.getPoliciesClient(requestConfig);
+        }
+
+        //----------------------------------------------------------------------
+
+        @Override
+        public AccessClient getAccessClient() {
+            return client.getAccessClient();
+        }
+
+        //----------------------------------------------------------------------
+
+        @Override
         public void close() throws IOException {
             client.close();
         }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/AccessClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/AccessClient.java
new file mode 100644
index 0000000..8731c9d
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/AccessClient.java
@@ -0,0 +1,29 @@
+/*
+ * 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.toolkit.cli.impl.client.nifi;
+
+import java.io.IOException;
+
+public interface AccessClient {
+
+    String getToken(String username, String password) throws NiFiClientException, IOException;
+
+    String getTokenFromKerberosTicket() throws NiFiClientException, IOException;
+
+    void logout(String token) throws NiFiClientException, IOException;
+
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/NiFiClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/NiFiClient.java
index 1a7e7c2..3a3437e 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/NiFiClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/NiFiClient.java
@@ -25,173 +25,109 @@ public interface NiFiClient extends Closeable {
 
     // ----- ControllerClient -----
 
-    /**
-     * @return a ControllerClient
-     */
     ControllerClient getControllerClient();
 
-    /**
-     * Obtains a ControllerClient for the given proxied entities. Each operation made from this client
-     * will add the appropriate X-ProxiedEntitiesChain header to each request.
-     *
-     * @param proxiedEntity one or more identities to proxy
-     * @return a ControllerClient
-     */
-    ControllerClient getControllerClientForProxiedEntities(String ... proxiedEntity);
-
-    /**
-     * Obtains a ControllerClient that will submit the given token in the Authorization Bearer header
-     * with each request.
-     *
-     * @param token a token to authentication with
-     * @return a ControllerClient
-     */
-    ControllerClient getControllerClientForToken(String token);
+    ControllerClient getControllerClient(RequestConfig requestConfig);
 
     // ----- ControllerServicesClient -----
 
-    /**
-     * @return a ControllerServicesClient
-     */
     ControllerServicesClient getControllerServicesClient();
 
-    /**
-     * Obtains a ControllerServicesClient for the given proxied entities. Each operation made from this client
-     * will add the appropriate X-ProxiedEntitiesChain header to each request.
-     *
-     * @param proxiedEntity one or more identities to proxy
-     * @return a ControllerServicesClient
-     */
-    ControllerServicesClient getControllerServicesClientForProxiedEntities(String ... proxiedEntity);
-
-    /**
-     * Obtains a ControllerServicesClient that will submit the given token in the Authorization Bearer header
-     * with each request.
-     *
-     * @param token a token to authentication with
-     * @return a ControllerServicesClient
-     */
-    ControllerServicesClient getControllerServicesClientForToken(String token);
+    ControllerServicesClient getControllerServicesClient(RequestConfig requestConfig);
 
     // ----- FlowClient -----
 
     FlowClient getFlowClient();
 
-    FlowClient getFlowClientForProxiedEntities(String ... proxiedEntity);
-
-    FlowClient getFlowClientForToken(String token);
+    FlowClient getFlowClient(RequestConfig requestConfig);
 
     // ----- ProcessGroupClient -----
 
     ProcessGroupClient getProcessGroupClient();
 
-    ProcessGroupClient getProcessGroupClientForProxiedEntities(String ... proxiedEntity);
-
-    ProcessGroupClient getProcessGroupClientForToken(String token);
+    ProcessGroupClient getProcessGroupClient(RequestConfig requestConfig);
 
     // ----- VersionsClient -----
-    ProcessorClient getProcessorClient();
 
-    ProcessorClient getProcessorClientForProxiedEntities(String... proxiedEntity);
+    ProcessorClient getProcessorClient();
 
-    ProcessorClient getProcessorClientForToken(String token);
+    ProcessorClient getProcessorClient(RequestConfig requestConfig);
 
     // ----- VersionsClient -----
 
     VersionsClient getVersionsClient();
 
-    VersionsClient getVersionsClientForProxiedEntities(String ... proxiedEntity);
-
-    VersionsClient getVersionsClientForToken(String token);
+    VersionsClient getVersionsClient(RequestConfig requestConfig);
 
     // ----- TenantsClient -----
 
     TenantsClient getTenantsClient();
 
-    TenantsClient getTenantsClientForProxiedEntities(String ... proxiedEntity);
-
-    TenantsClient getTenantsClientForToken(String token);
+    TenantsClient getTenantsClient(RequestConfig requestConfig);
 
     // ----- PoliciesClient -----
 
     PoliciesClient getPoliciesClient();
 
-    PoliciesClient getPoliciesClientForProxiedEntities(String ... proxiedEntity);
-
-    PoliciesClient getPoliciesClientForToken(String token);
+    PoliciesClient getPoliciesClient(RequestConfig requestConfig);
 
     // ----- TemplatesClient -----
 
     TemplatesClient getTemplatesClient();
 
-    TemplatesClient getTemplatesClientForProxiedEntities(String ... proxiedEntity);
-
-    TemplatesClient getTemplatesClientForToken(String token);
+    TemplatesClient getTemplatesClient(RequestConfig requestConfig);
 
     // ----- ReportingTasksClient -----
 
     ReportingTasksClient getReportingTasksClient();
 
-    ReportingTasksClient getReportingTasksClientForProxiedEntities(String ... proxiedEntity);
-
-    ReportingTasksClient getReportingTasksClientForToken(String token);
+    ReportingTasksClient getReportingTasksClient(RequestConfig requestConfig);
 
     // ----- ParamContextClient -----
 
     ParamContextClient getParamContextClient();
 
-    ParamContextClient getParamContextClientForProxiedEntities(String ... proxiedEntity);
-
-    ParamContextClient getParamContextClientForToken(String token);
+    ParamContextClient getParamContextClient(RequestConfig requestConfig);
 
     // ----- ParamContextClient -----
 
     CountersClient getCountersClient();
 
-    CountersClient getCountersClientForProxiedEntities(String ... proxiedEntity);
-
-    CountersClient getCountersClientForToken(String token);
+    CountersClient getCountersClient(RequestConfig requestConfig);
 
     // ----- ConnectionClient -----
 
     ConnectionClient getConnectionClient();
 
-    ConnectionClient getConnectionClientForProxiedEntities(String... proxiedEntity);
-
-    ConnectionClient getConnectionClientForToken(String token);
+    ConnectionClient getConnectionClient(RequestConfig requestConfig);
 
     // ----- RemoteProcessGroupClient -----
 
     RemoteProcessGroupClient getRemoteProcessGroupClient();
 
-    RemoteProcessGroupClient getRemoteProcessGroupClientForProxiedEntities(String... proxiedEntity);
-
-    RemoteProcessGroupClient getRemoteProcessGroupClientForToken(String token);
+    RemoteProcessGroupClient getRemoteProcessGroupClient(RequestConfig requestConfig);
 
     // ----- InputPortClient -----
 
     InputPortClient getInputPortClient();
 
-    InputPortClient getInputPortClientForProxiedEntities(String... proxiedEntity);
-
-    InputPortClient getInputPortClientForToken(String token);
+    InputPortClient getInputPortClient(RequestConfig requestConfig);
 
     // ----- OutputPortClient -----
 
     OutputPortClient getOutputPortClient();
 
-    OutputPortClient getOutputPortClientForProxiedEntities(String... proxiedEntity);
-
-    OutputPortClient getOutputPortClientForToken(String token);
+    OutputPortClient getOutputPortClient(RequestConfig requestConfig);
 
     // ----- ProvenanceClient -----
 
     ProvenanceClient getProvenanceClient();
 
-    ProvenanceClient getProvenanceClientForProxiedEntities(String... proxiedEntity);
+    ProvenanceClient getProvenanceClient(RequestConfig requestConfig);
 
-    ProvenanceClient getProvenanceClientForToken(String token);
+    // ----- AccessClient -----
 
+    AccessClient getAccessClient();
 
     /**
      * The builder interface that implementations should provide for obtaining the client.
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/RequestConfig.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/RequestConfig.java
new file mode 100644
index 0000000..903df73
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/RequestConfig.java
@@ -0,0 +1,32 @@
+/*
+ * 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.toolkit.cli.impl.client.nifi;
+
+import java.util.Map;
+
+/**
+ * Configuration applied to each client request.
+ */
+public interface RequestConfig {
+
+    /**
+     * @return the headers to apply to each request
+     */
+    Map<String,String> getHeaders();
+
+
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/AbstractJerseyClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/AbstractJerseyClient.java
index 7767a64..62b9db2 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/AbstractJerseyClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/AbstractJerseyClient.java
@@ -17,6 +17,7 @@
 package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.client.Invocation;
@@ -24,7 +25,6 @@ import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.Response;
 import java.io.IOException;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -34,14 +34,16 @@ import java.util.Map;
  */
 public class AbstractJerseyClient {
 
-    private final Map<String,String> headers;
+    private static final RequestConfig EMPTY_REQUEST_CONFIG = () ->  Collections.emptyMap();
 
-    public AbstractJerseyClient(final Map<String, String> headers) {
-        this.headers = headers == null ? Collections.emptyMap() : Collections.unmodifiableMap(new HashMap<>(headers));
+    private final RequestConfig requestConfig;
+
+    public AbstractJerseyClient(final RequestConfig requestConfig) {
+        this.requestConfig = (requestConfig == null ? EMPTY_REQUEST_CONFIG : requestConfig);
     }
 
-    protected Map<String,String> getHeaders() {
-        return headers;
+    protected RequestConfig getRequestConfig() {
+        return this.requestConfig;
     }
 
     /**
@@ -52,7 +54,10 @@ public class AbstractJerseyClient {
      */
     protected Invocation.Builder getRequestBuilder(final WebTarget webTarget) {
         final Invocation.Builder requestBuilder = webTarget.request();
+
+        final Map<String,String> headers = requestConfig.getHeaders();
         headers.entrySet().stream().forEach(e -> requestBuilder.header(e.getKey(), e.getValue()));
+
         return requestBuilder;
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/CRUDJerseyClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/CRUDJerseyClient.java
index b333427..01c3cd0 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/CRUDJerseyClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/CRUDJerseyClient.java
@@ -18,6 +18,7 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.dto.RevisionDTO;
 import org.apache.nifi.web.api.entity.ComponentEntity;
 
@@ -25,7 +26,6 @@ import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
-import java.util.Map;
 
 public class CRUDJerseyClient<T extends ComponentEntity> extends AbstractJerseyClient {
     private final WebTarget creationTarget;
@@ -34,8 +34,9 @@ public class CRUDJerseyClient<T extends ComponentEntity> extends AbstractJerseyC
     private final String componentType;
 
 
-    public CRUDJerseyClient(final WebTarget creationTarget, final WebTarget accessTarget, final Map<String, String> headers, final Class<T> entityType, final String componentType) {
-        super(headers);
+    public CRUDJerseyClient(final WebTarget creationTarget, final WebTarget accessTarget, final RequestConfig requestConfig,
+                            final Class<T> entityType, final String componentType) {
+        super(requestConfig);
         this.entityType = entityType;
         this.componentType = componentType;
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyAccessClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyAccessClient.java
new file mode 100644
index 0000000..1423ce1
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyAccessClient.java
@@ -0,0 +1,87 @@
+/*
+ * 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.toolkit.cli.impl.client.nifi.impl;
+
+import org.apache.nifi.registry.client.impl.request.BearerTokenRequestConfig;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.AccessClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.util.StringUtils;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Form;
+import java.io.IOException;
+import java.util.Map;
+
+public class JerseyAccessClient extends AbstractJerseyClient implements AccessClient {
+
+    private final WebTarget accessTarget;
+
+    public JerseyAccessClient(final WebTarget baseTarget) {
+        super(null);
+        this.accessTarget = baseTarget.path("/access");
+    }
+
+    @Override
+    public String getToken(final String username, final String password) throws NiFiClientException, IOException {
+        if (StringUtils.isBlank(username)) {
+            throw new IllegalArgumentException("Username is required");
+        }
+
+        if (StringUtils.isBlank(password)) {
+            throw new IllegalArgumentException("Password is required");
+        }
+
+        return executeAction("Error performing login", () -> {
+            final WebTarget target = accessTarget.path("token");
+
+            final Form form = new Form();
+            form.param("username", username);
+            form.param("password", password);
+
+            return getRequestBuilder(target).post(Entity.form(form), String.class);
+        });
+    }
+
+    @Override
+    public String getTokenFromKerberosTicket() throws NiFiClientException, IOException {
+        return executeAction("Error performing kerberos login", () -> {
+            final WebTarget target = accessTarget.path("kerberos");
+            return getRequestBuilder(target).post(Entity.text(null), String.class);
+        });
+    }
+
+    @Override
+    public void logout(final String token) throws NiFiClientException, IOException {
+        if (StringUtils.isBlank(token)) {
+            throw new IllegalArgumentException("Token is required");
+        }
+
+        executeAction("Error performing logout", () -> {
+            final WebTarget target = accessTarget.path("logout");
+            final Invocation.Builder requestBuilder = getRequestBuilder(target);
+
+            final org.apache.nifi.registry.client.RequestConfig tokenConfig = new BearerTokenRequestConfig(token);
+            final Map<String,String> bearerHeaders = tokenConfig.getHeaders();
+            bearerHeaders.entrySet().stream().forEach(e -> requestBuilder.header(e.getKey(), e.getValue()));
+
+            requestBuilder.delete();
+            return null;
+        });
+    }
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyConnectionClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyConnectionClient.java
index 34e2953..516b031 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyConnectionClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyConnectionClient.java
@@ -19,6 +19,7 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ConnectionClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.entity.ConnectionEntity;
 import org.apache.nifi.web.api.entity.DropRequestEntity;
 import org.apache.nifi.web.api.entity.FlowFileEntity;
@@ -29,8 +30,6 @@ import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Collections;
-import java.util.Map;
 
 public class JerseyConnectionClient extends AbstractJerseyClient implements ConnectionClient {
     private final WebTarget connectionTarget;
@@ -38,11 +37,11 @@ public class JerseyConnectionClient extends AbstractJerseyClient implements Conn
     private final WebTarget flowFileQueueTarget;
 
     public JerseyConnectionClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyConnectionClient(final WebTarget baseTarget, final Map<String,String> headers) {
-        super(headers);
+    public JerseyConnectionClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
 
         this.connectionTarget = baseTarget.path("/connections/{id}");
         this.processGroupTarget = baseTarget.path("/process-groups/{pgId}");
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerClient.java
index 16c105f..e3216dc 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerClient.java
@@ -19,6 +19,7 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.entity.ClusterEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceEntity;
 import org.apache.nifi.web.api.entity.NodeEntity;
@@ -30,8 +31,6 @@ import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 /**
  * Jersey implementation of ControllerClient.
@@ -41,11 +40,11 @@ public class JerseyControllerClient extends AbstractJerseyClient implements Cont
     private final WebTarget controllerTarget;
 
     public JerseyControllerClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyControllerClient(final WebTarget baseTarget, final Map<String,String> headers) {
-        super(headers);
+    public JerseyControllerClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.controllerTarget = baseTarget.path("/controller");
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerServicesClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerServicesClient.java
index 7906f85..ec5676e 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerServicesClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerServicesClient.java
@@ -19,6 +19,7 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerServicesClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.dto.RevisionDTO;
 import org.apache.nifi.web.api.entity.ControllerServiceEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceReferencingComponentsEntity;
@@ -29,8 +30,6 @@ import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 /**
  * Jersey implementation of ControllerServicersClient.
@@ -41,11 +40,11 @@ public class JerseyControllerServicesClient extends AbstractJerseyClient impleme
     private final WebTarget processGroupTarget;
 
     public JerseyControllerServicesClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyControllerServicesClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(headers);
+    public JerseyControllerServicesClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.controllerServicesTarget = baseTarget.path("/controller-services");
         this.processGroupTarget = baseTarget.path("/process-groups/{pgId}");
     }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyCountersClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyCountersClient.java
index 81b2bd7..cf05bfc 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyCountersClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyCountersClient.java
@@ -18,22 +18,21 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 
 import org.apache.nifi.toolkit.cli.impl.client.nifi.CountersClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.entity.CountersEntity;
 
 import javax.ws.rs.client.WebTarget;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 public class JerseyCountersClient extends AbstractJerseyClient implements CountersClient {
     private final WebTarget countersTarget;
 
     public JerseyCountersClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyCountersClient(final WebTarget baseTarget, final Map<String,String> headers) {
-        super(headers);
+    public JerseyCountersClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.countersTarget = baseTarget.path("/counters");
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyFlowClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyFlowClient.java
index f18f094..96ad5f8 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyFlowClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyFlowClient.java
@@ -20,6 +20,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.FlowClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ProcessGroupBox;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.dto.PositionDTO;
 import org.apache.nifi.web.api.dto.flow.FlowDTO;
 import org.apache.nifi.web.api.dto.flow.ProcessGroupFlowDTO;
@@ -40,9 +41,7 @@ import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -57,11 +56,11 @@ public class JerseyFlowClient extends AbstractJerseyClient implements FlowClient
     private final WebTarget flowTarget;
 
     public JerseyFlowClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyFlowClient(final WebTarget baseTarget, final Map<String,String> headers) {
-        super(headers);
+    public JerseyFlowClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.flowTarget = baseTarget.path("/flow");
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyInputPortClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyInputPortClient.java
index 6c10a69..eb82275 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyInputPortClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyInputPortClient.java
@@ -18,24 +18,23 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 
 import org.apache.nifi.toolkit.cli.impl.client.nifi.InputPortClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.dto.PortDTO;
 import org.apache.nifi.web.api.entity.PortEntity;
 
 import javax.ws.rs.client.WebTarget;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 public class JerseyInputPortClient extends CRUDJerseyClient<PortEntity> implements InputPortClient {
 
     public JerseyInputPortClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyInputPortClient(final WebTarget baseTarget, final Map<String, String> headers) {
+    public JerseyInputPortClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
         super(baseTarget.path("/process-groups/{pgId}/input-ports"),
             baseTarget.path("/input-ports/{id}"),
-            headers,
+            requestConfig,
             PortEntity.class,
             "Input Port");
     }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyNiFiClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyNiFiClient.java
index e6b1014..1b7187e 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyNiFiClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyNiFiClient.java
@@ -21,7 +21,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.registry.security.util.ProxiedEntitiesUtils;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.AccessClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ConnectionClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerServicesClient;
@@ -38,6 +38,7 @@ import org.apache.nifi.toolkit.cli.impl.client.nifi.ProcessorClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ProvenanceClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.RemoteProcessGroupClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ReportingTasksClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.TemplatesClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.VersionsClient;
@@ -51,11 +52,6 @@ import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
 import javax.ws.rs.client.WebTarget;
 import java.net.URI;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
 
 /**
  * Jersey implementation of NiFiClient.
@@ -66,9 +62,6 @@ public class JerseyNiFiClient implements NiFiClient {
     static final int DEFAULT_CONNECT_TIMEOUT = 10000;
     static final int DEFAULT_READ_TIMEOUT = 10000;
 
-    static final String AUTHORIZATION_HEADER = "Authorization";
-    static final String BEARER = "Bearer";
-
     private final Client client;
     private final WebTarget baseTarget;
 
@@ -127,15 +120,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public ControllerClient getControllerClientForProxiedEntities(final String... proxiedEntity) {
-        final Map<String,String> headers = getHeaders(proxiedEntity);
-        return new JerseyControllerClient(baseTarget, headers);
-    }
-
-    @Override
-    public ControllerClient getControllerClientForToken(final String base64token) {
-        final Map<String,String> headers = getHeadersWithToken(base64token);
-        return new JerseyControllerClient(baseTarget, headers);
+    public ControllerClient getControllerClient(RequestConfig requestConfig) {
+        return new JerseyControllerClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -144,15 +130,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public ControllerServicesClient getControllerServicesClientForProxiedEntities(final String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyControllerServicesClient(baseTarget, headers);
-    }
-
-    @Override
-    public ControllerServicesClient getControllerServicesClientForToken(final String base64token) {
-        final Map<String, String> headers = getHeadersWithToken(base64token);
-        return new JerseyControllerServicesClient(baseTarget, headers);
+    public ControllerServicesClient getControllerServicesClient(RequestConfig requestConfig) {
+        return new JerseyControllerServicesClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -161,15 +140,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public FlowClient getFlowClientForProxiedEntities(String... proxiedEntity) {
-        final Map<String,String> headers = getHeaders(proxiedEntity);
-        return new JerseyFlowClient(baseTarget, headers);
-    }
-
-    @Override
-    public FlowClient getFlowClientForToken(String base64token) {
-        final Map<String,String> headers = getHeadersWithToken(base64token);
-        return new JerseyFlowClient(baseTarget, headers);
+    public FlowClient getFlowClient(RequestConfig requestConfig) {
+        return new JerseyFlowClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -178,15 +150,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public ProcessGroupClient getProcessGroupClientForProxiedEntities(String... proxiedEntity) {
-        final Map<String,String> headers = getHeaders(proxiedEntity);
-        return new JerseyProcessGroupClient(baseTarget, headers);
-    }
-
-    @Override
-    public ProcessGroupClient getProcessGroupClientForToken(String base64token) {
-        final Map<String,String> headers = getHeadersWithToken(base64token);
-        return new JerseyProcessGroupClient(baseTarget, headers);
+    public ProcessGroupClient getProcessGroupClient(RequestConfig requestConfig) {
+        return new JerseyProcessGroupClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -195,15 +160,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public ProcessorClient getProcessorClientForProxiedEntities(final String... proxiedEntity) {
-        final Map<String,String> headers = getHeaders(proxiedEntity);
-        return new JerseyProcessorClient(baseTarget, headers);
-    }
-
-    @Override
-    public ProcessorClient getProcessorClientForToken(final String token) {
-        final Map<String,String> headers = getHeadersWithToken(token);
-        return new JerseyProcessorClient(baseTarget, headers);
+    public ProcessorClient getProcessorClient(RequestConfig requestConfig) {
+        return new JerseyProcessorClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -212,15 +170,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public VersionsClient getVersionsClientForProxiedEntities(String... proxiedEntity) {
-        final Map<String,String> headers = getHeaders(proxiedEntity);
-        return new JerseyVersionsClient(baseTarget, headers);
-    }
-
-    @Override
-    public VersionsClient getVersionsClientForToken(String base64token) {
-        final Map<String,String> headers = getHeadersWithToken(base64token);
-        return new JerseyVersionsClient(baseTarget, headers);
+    public VersionsClient getVersionsClient(RequestConfig requestConfig) {
+        return new JerseyVersionsClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -229,15 +180,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public TenantsClient getTenantsClientForProxiedEntities(String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyTenantsClient(baseTarget, headers);
-    }
-
-    @Override
-    public TenantsClient getTenantsClientForToken(String base64token) {
-        final Map<String, String> headers = getHeadersWithToken(base64token);
-        return new JerseyTenantsClient(baseTarget, headers);
+    public TenantsClient getTenantsClient(RequestConfig requestConfig) {
+        return new JerseyTenantsClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -246,15 +190,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public PoliciesClient getPoliciesClientForProxiedEntities(String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyPoliciesClient(baseTarget, headers);
-    }
-
-    @Override
-    public PoliciesClient getPoliciesClientForToken(String base64token) {
-        final Map<String, String> headers = getHeadersWithToken(base64token);
-        return new JerseyPoliciesClient(baseTarget, headers);
+    public PoliciesClient getPoliciesClient(RequestConfig requestConfig) {
+        return new JerseyPoliciesClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -263,15 +200,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public TemplatesClient getTemplatesClientForProxiedEntities(String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyTemplatesClient(baseTarget, headers);
-    }
-
-    @Override
-    public TemplatesClient getTemplatesClientForToken(String base64token) {
-        final Map<String, String> headers = getHeadersWithToken(base64token);
-        return new JerseyTemplatesClient(baseTarget, headers);
+    public TemplatesClient getTemplatesClient(RequestConfig requestConfig) {
+        return new JerseyTemplatesClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -280,15 +210,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public ReportingTasksClient getReportingTasksClientForProxiedEntities(String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyReportingTasksClient(baseTarget, headers);
-    }
-
-    @Override
-    public ReportingTasksClient getReportingTasksClientForToken(String base64token) {
-        final Map<String, String> headers = getHeadersWithToken(base64token);
-        return new JerseyReportingTasksClient(baseTarget, headers);
+    public ReportingTasksClient getReportingTasksClient(RequestConfig requestConfig) {
+        return new JerseyReportingTasksClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -297,15 +220,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public ParamContextClient getParamContextClientForProxiedEntities(String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyParamContextClient(baseTarget, headers);
-    }
-
-    @Override
-    public ParamContextClient getParamContextClientForToken(String base64token) {
-        final Map<String, String> headers = getHeadersWithToken(base64token);
-        return new JerseyParamContextClient(baseTarget, headers);
+    public ParamContextClient getParamContextClient(RequestConfig requestConfig) {
+        return new JerseyParamContextClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -314,15 +230,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public CountersClient getCountersClientForProxiedEntities(final String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyCountersClient(baseTarget, headers);
-    }
-
-    @Override
-    public CountersClient getCountersClientForToken(final String token) {
-        final Map<String, String> headers = getHeadersWithToken(token);
-        return new JerseyCountersClient(baseTarget, headers);
+    public CountersClient getCountersClient(RequestConfig requestConfig) {
+        return new JerseyCountersClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -331,15 +240,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public ConnectionClient getConnectionClientForProxiedEntities(final String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyConnectionClient(baseTarget, headers);
-    }
-
-    @Override
-    public ConnectionClient getConnectionClientForToken(final String token) {
-        final Map<String, String> headers = getHeadersWithToken(token);
-        return new JerseyConnectionClient(baseTarget, headers);
+    public ConnectionClient getConnectionClient(RequestConfig requestConfig) {
+        return new JerseyConnectionClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -348,15 +250,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public RemoteProcessGroupClient getRemoteProcessGroupClientForProxiedEntities(final String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyRemoteProcessGroupClient(baseTarget, headers);
-    }
-
-    @Override
-    public RemoteProcessGroupClient getRemoteProcessGroupClientForToken(final String token) {
-        final Map<String, String> headers = getHeadersWithToken(token);
-        return new JerseyRemoteProcessGroupClient(baseTarget, headers);
+    public RemoteProcessGroupClient getRemoteProcessGroupClient(RequestConfig requestConfig) {
+        return new JerseyRemoteProcessGroupClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -365,15 +260,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public InputPortClient getInputPortClientForProxiedEntities(final String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyInputPortClient(baseTarget, headers);
-    }
-
-    @Override
-    public InputPortClient getInputPortClientForToken(final String token) {
-        final Map<String, String> headers = getHeadersWithToken(token);
-        return new JerseyInputPortClient(baseTarget, headers);
+    public InputPortClient getInputPortClient(RequestConfig requestConfig) {
+        return new JerseyInputPortClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -382,15 +270,8 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public OutputPortClient getOutputPortClientForProxiedEntities(final String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyOutputPortClient(baseTarget, headers);
-    }
-
-    @Override
-    public OutputPortClient getOutputPortClientForToken(final String token) {
-        final Map<String, String> headers = getHeadersWithToken(token);
-        return new JerseyOutputPortClient(baseTarget, headers);
+    public OutputPortClient getOutputPortClient(RequestConfig requestConfig) {
+        return new JerseyOutputPortClient(baseTarget, requestConfig);
     }
 
     @Override
@@ -399,15 +280,13 @@ public class JerseyNiFiClient implements NiFiClient {
     }
 
     @Override
-    public ProvenanceClient getProvenanceClientForProxiedEntities(final String... proxiedEntity) {
-        final Map<String, String> headers = getHeaders(proxiedEntity);
-        return new JerseyProvenanceClient(baseTarget, headers);
+    public ProvenanceClient getProvenanceClient(RequestConfig requestConfig) {
+        return new JerseyProvenanceClient(baseTarget, requestConfig);
     }
 
     @Override
-    public ProvenanceClient getProvenanceClientForToken(final String token) {
-        final Map<String, String> headers = getHeadersWithToken(token);
-        return new JerseyProvenanceClient(baseTarget, headers);
+    public AccessClient getAccessClient() {
+        return new JerseyAccessClient(baseTarget);
     }
 
     @Override
@@ -421,36 +300,6 @@ public class JerseyNiFiClient implements NiFiClient {
         }
     }
 
-    private Map<String,String> getHeadersWithToken(final String base64token) {
-        if (StringUtils.isBlank(base64token)) {
-            throw new IllegalArgumentException("Token cannot be null");
-        }
-
-        final Map<String,String> headers = new HashMap<>();
-        headers.put(AUTHORIZATION_HEADER, BEARER + " " + base64token);
-        return headers;
-    }
-
-    private Map<String,String> getHeaders(final String[] proxiedEntities) {
-        final String proxiedEntitiesValue = getProxiedEntitesValue(proxiedEntities);
-
-        final Map<String,String> headers = new HashMap<>();
-        if (proxiedEntitiesValue != null) {
-            headers.put(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxiedEntitiesValue);
-        }
-        return headers;
-    }
-
-    private String getProxiedEntitesValue(final String[] proxiedEntities) {
-        if (proxiedEntities == null) {
-            return null;
-        }
-
-        final List<String> proxiedEntityChain = Arrays.stream(proxiedEntities)
-                .map(ProxiedEntitiesUtils::formatProxyDn).collect(Collectors.toList());
-        return StringUtils.join(proxiedEntityChain, "");
-    }
-
     /**
      * Builder for creating a JerseyNiFiClient.
      */
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyOutputPortClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyOutputPortClient.java
index 645c95f..f2e55cd 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyOutputPortClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyOutputPortClient.java
@@ -18,24 +18,23 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.OutputPortClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.dto.PortDTO;
 import org.apache.nifi.web.api.entity.PortEntity;
 
 import javax.ws.rs.client.WebTarget;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 public class JerseyOutputPortClient extends CRUDJerseyClient<PortEntity> implements OutputPortClient {
 
     public JerseyOutputPortClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyOutputPortClient(final WebTarget baseTarget, final Map<String, String> headers) {
+    public JerseyOutputPortClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
         super(baseTarget.path("/process-groups/{pgId}/output-ports"),
             baseTarget.path("/output-ports/{id}"),
-            headers,
+            requestConfig,
             PortEntity.class,
             "Output Port");
     }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyParamContextClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyParamContextClient.java
index dbe8596..597aaa8 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyParamContextClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyParamContextClient.java
@@ -19,6 +19,7 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ParamContextClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.entity.ParameterContextEntity;
 import org.apache.nifi.web.api.entity.ParameterContextUpdateRequestEntity;
 import org.apache.nifi.web.api.entity.ParameterContextsEntity;
@@ -27,8 +28,6 @@ import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 public class JerseyParamContextClient extends AbstractJerseyClient implements ParamContextClient {
 
@@ -36,11 +35,11 @@ public class JerseyParamContextClient extends AbstractJerseyClient implements Pa
     private final WebTarget paramContextTarget;
 
     public JerseyParamContextClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyParamContextClient(final WebTarget baseTarget, final Map<String,String> headers) {
-        super(headers);
+    public JerseyParamContextClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.flowTarget = baseTarget.path("/flow");
         this.paramContextTarget = baseTarget.path("/parameter-contexts");
     }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyPoliciesClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyPoliciesClient.java
index e7264ca..b3f9aaf 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyPoliciesClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyPoliciesClient.java
@@ -19,14 +19,13 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.PoliciesClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.entity.AccessPolicyEntity;
 
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
+import java.io.IOException;
 
 /**
  * Jersey implementation of PoliciesClient.
@@ -36,11 +35,11 @@ public class JerseyPoliciesClient extends AbstractJerseyClient implements Polici
     private final WebTarget policiesTarget;
 
     public JerseyPoliciesClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyPoliciesClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(headers);
+    public JerseyPoliciesClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.policiesTarget = baseTarget.path("/policies");
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProcessGroupClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProcessGroupClient.java
index e46badc..6ac9d68 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProcessGroupClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProcessGroupClient.java
@@ -19,6 +19,7 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ProcessGroupClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.dto.TemplateDTO;
 import org.apache.nifi.web.api.entity.ControllerServiceEntity;
 import org.apache.nifi.web.api.entity.ProcessGroupEntity;
@@ -34,8 +35,6 @@ import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 /**
  * Jersey implementation of ProcessGroupClient.
@@ -45,11 +44,11 @@ public class JerseyProcessGroupClient extends AbstractJerseyClient implements Pr
     private final WebTarget processGroupsTarget;
 
     public JerseyProcessGroupClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyProcessGroupClient(final WebTarget baseTarget, final Map<String,String> headers) {
-        super(headers);
+    public JerseyProcessGroupClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.processGroupsTarget = baseTarget.path("/process-groups");
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProcessorClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProcessorClient.java
index d304c9a..0acd1e8 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProcessorClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProcessorClient.java
@@ -19,6 +19,7 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ProcessorClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.dto.RevisionDTO;
 import org.apache.nifi.web.api.entity.ProcessorEntity;
 import org.apache.nifi.web.api.entity.ProcessorRunStatusEntity;
@@ -27,19 +28,17 @@ import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 public class JerseyProcessorClient extends AbstractJerseyClient implements ProcessorClient {
     private final WebTarget processGroupTarget;
     private final WebTarget processorTarget;
 
     public JerseyProcessorClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyProcessorClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(headers);
+    public JerseyProcessorClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.processGroupTarget = baseTarget.path("/process-groups/{pgId}");
         this.processorTarget = baseTarget.path("/processors/{id}");
     }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProvenanceClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProvenanceClient.java
index 1cbdad3..ea83b34 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProvenanceClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyProvenanceClient.java
@@ -19,6 +19,7 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ProvenanceClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.entity.LineageEntity;
 import org.apache.nifi.web.api.entity.ProvenanceEntity;
 
@@ -26,18 +27,16 @@ import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 public class JerseyProvenanceClient extends AbstractJerseyClient implements ProvenanceClient {
     private final WebTarget provenanceTarget;
 
     public JerseyProvenanceClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyProvenanceClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(headers);
+    public JerseyProvenanceClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.provenanceTarget = baseTarget.path("/provenance");
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyRemoteProcessGroupClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyRemoteProcessGroupClient.java
index 0a8482e..a3d9209 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyRemoteProcessGroupClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyRemoteProcessGroupClient.java
@@ -19,6 +19,7 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.RemoteProcessGroupClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
 import org.apache.nifi.web.api.dto.RevisionDTO;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
@@ -27,19 +28,17 @@ import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 public class JerseyRemoteProcessGroupClient extends AbstractJerseyClient implements RemoteProcessGroupClient {
     private final WebTarget processGroupTarget;
     private final WebTarget rpgTarget;
 
     public JerseyRemoteProcessGroupClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyRemoteProcessGroupClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(headers);
+    public JerseyRemoteProcessGroupClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.processGroupTarget = baseTarget.path("/process-groups/{pgId}");
         this.rpgTarget = baseTarget.path("/remote-process-groups/{id}");
     }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyReportingTasksClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyReportingTasksClient.java
index 379ddbb..bf4f26e 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyReportingTasksClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyReportingTasksClient.java
@@ -20,15 +20,14 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.ReportingTasksClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.web.api.entity.ReportingTaskEntity;
 import org.apache.nifi.web.api.entity.ReportingTaskRunStatusEntity;
 
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
+import java.io.IOException;
 
 /**
  * Jersey implementation of ReportingTasksClient.
@@ -38,11 +37,11 @@ public class JerseyReportingTasksClient extends AbstractJerseyClient implements
     private final WebTarget reportingTasksTarget;
 
     public JerseyReportingTasksClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyReportingTasksClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(headers);
+    public JerseyReportingTasksClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.reportingTasksTarget = baseTarget.path("/reporting-tasks");
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyTemplatesClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyTemplatesClient.java
index e6672e9..17bfc40 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyTemplatesClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyTemplatesClient.java
@@ -18,13 +18,12 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.TemplatesClient;
 import org.apache.nifi.web.api.dto.TemplateDTO;
 
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 import javax.ws.rs.client.WebTarget;
+import java.io.IOException;
 
 /**
  * Jersey implementation of TemplatesClient.
@@ -34,11 +33,11 @@ public class JerseyTemplatesClient extends AbstractJerseyClient implements Templ
     private final WebTarget templatesTarget;
 
     public JerseyTemplatesClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyTemplatesClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(headers);
+    public JerseyTemplatesClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.templatesTarget = baseTarget.path("/templates");
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyTenantsClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyTenantsClient.java
index 6056b22..e093b98 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyTenantsClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyTenantsClient.java
@@ -17,6 +17,7 @@
 package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.TenantsClient;
 import org.apache.nifi.util.StringUtils;
 import org.apache.nifi.web.api.entity.UserEntity;
@@ -24,12 +25,10 @@ import org.apache.nifi.web.api.entity.UserGroupEntity;
 import org.apache.nifi.web.api.entity.UserGroupsEntity;
 import org.apache.nifi.web.api.entity.UsersEntity;
 
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
+import java.io.IOException;
 
 /**
  * Jersey implementation of TenantsClient.
@@ -39,11 +38,11 @@ public class JerseyTenantsClient extends AbstractJerseyClient implements Tenants
     private final WebTarget tenantsTarget;
 
     public JerseyTenantsClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyTenantsClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(headers);
+    public JerseyTenantsClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.tenantsTarget = baseTarget.path("/tenants");
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyVersionsClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyVersionsClient.java
index 157a649..b145b38 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyVersionsClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyVersionsClient.java
@@ -18,6 +18,7 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
 import org.apache.nifi.toolkit.cli.impl.client.nifi.VersionsClient;
 import org.apache.nifi.web.api.entity.VersionControlInformationEntity;
 import org.apache.nifi.web.api.entity.VersionedFlowUpdateRequestEntity;
@@ -26,8 +27,6 @@ import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
 
 /**
  * Jersey implementation of VersionsClient.
@@ -37,11 +36,11 @@ public class JerseyVersionsClient extends AbstractJerseyClient implements Versio
     private final WebTarget versionsTarget;
 
     public JerseyVersionsClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
+        this(baseTarget, null);
     }
 
-    public JerseyVersionsClient(final WebTarget baseTarget, final Map<String,String> headers) {
-        super(headers);
+    public JerseyVersionsClient(final WebTarget baseTarget, final RequestConfig requestConfig) {
+        super(requestConfig);
         this.versionsTarget = baseTarget.path("/versions");
     }
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/request/BasicAuthRequestConfig.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/request/BasicAuthRequestConfig.java
new file mode 100644
index 0000000..1cfc958
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/request/BasicAuthRequestConfig.java
@@ -0,0 +1,55 @@
+/*
+ * 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.toolkit.cli.impl.client.nifi.impl.request;
+
+import org.apache.commons.lang3.Validate;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Implementation of RequestConfig for a request with basic auth.
+ */
+public class BasicAuthRequestConfig implements RequestConfig {
+
+    public static final String AUTHORIZATION_HEADER = "Authorization";
+    public static final String BASIC = "Basic";
+
+    private final String username;
+    private final String password;
+
+    public BasicAuthRequestConfig(final String username, final String password) {
+        this.username = Validate.notBlank(username);
+        this.password = Validate.notBlank(password);
+    }
+
+    @Override
+    public Map<String, String> getHeaders() {
+        final String basicCreds = username + ":" + password;
+        final byte[] basicCredsBytes = basicCreds.getBytes(StandardCharsets.UTF_8);
+
+        final Base64.Encoder encoder = Base64.getEncoder();
+        final String encodedBasicCreds = encoder.encodeToString(basicCredsBytes);
+
+        final Map<String,String> headers = new HashMap<>();
+        headers.put(AUTHORIZATION_HEADER, BASIC + " " + encodedBasicCreds);
+        return headers;
+    }
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/request/BearerTokenRequestConfig.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/request/BearerTokenRequestConfig.java
new file mode 100644
index 0000000..1568075
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/request/BearerTokenRequestConfig.java
@@ -0,0 +1,45 @@
+/*
+ * 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.toolkit.cli.impl.client.nifi.impl.request;
+
+import org.apache.commons.lang3.Validate;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Implementation of RequestConfig for a request with a bearer token.
+ */
+public class BearerTokenRequestConfig implements RequestConfig {
+
+    public static final String AUTHORIZATION_HEADER = "Authorization";
+    public static final String BEARER = "Bearer";
+
+    private final String token;
+
+    public BearerTokenRequestConfig(final String token) {
+        this.token = Validate.notBlank(token);
+    }
+
+    @Override
+    public Map<String, String> getHeaders() {
+        final Map<String,String> headers = new HashMap<>();
+        headers.put(AUTHORIZATION_HEADER, BEARER + " " + token);
+        return headers;
+    }
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/request/ProxiedEntityRequestConfig.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/request/ProxiedEntityRequestConfig.java
new file mode 100644
index 0000000..3ece9ca
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/request/ProxiedEntityRequestConfig.java
@@ -0,0 +1,62 @@
+/*
+ * 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.toolkit.cli.impl.client.nifi.impl.request;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.nifi.registry.security.util.ProxiedEntitiesUtils;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Implementation of RequestConfig that produces headers for a request with proxied-entities.
+ */
+public class ProxiedEntityRequestConfig implements RequestConfig {
+
+    private final String[] proxiedEntities;
+
+    public ProxiedEntityRequestConfig(final String... proxiedEntities) {
+        this.proxiedEntities = Validate.notNull(proxiedEntities);
+    }
+
+    @Override
+    public Map<String, String> getHeaders() {
+        final String proxiedEntitiesValue = getProxiedEntitesValue(proxiedEntities);
+
+        final Map<String,String> headers = new HashMap<>();
+        if (proxiedEntitiesValue != null) {
+            headers.put(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxiedEntitiesValue);
+        }
+        return headers;
+    }
+
+    private String getProxiedEntitesValue(final String[] proxiedEntities) {
+        if (proxiedEntities == null) {
+            return null;
+        }
+
+        final List<String> proxiedEntityChain = Arrays.stream(proxiedEntities)
+                .map(ProxiedEntitiesUtils::formatProxyDn).collect(Collectors.toList());
+        return StringUtils.join(proxiedEntityChain, "");
+    }
+
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/PoliciesClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/PoliciesClient.java
deleted file mode 100644
index fe614f5..0000000
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/PoliciesClient.java
+++ /dev/null
@@ -1,65 +0,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.
- */
-package org.apache.nifi.toolkit.cli.impl.client.registry;
-
-import org.apache.nifi.registry.authorization.AccessPolicy;
-import org.apache.nifi.registry.client.NiFiRegistryException;
-
-import java.io.IOException;
-
-/**
- * Provides API for access policies related services available in NiFi Registry.
- */
-public interface PoliciesClient {
-
-    /**
-     * Returns a given access policy.
-     *
-     * @param resource The action allowed by the access policy.
-     * @param action The resource managed by the access policy.
-     *
-     * @return The access policy.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    AccessPolicy getAccessPolicy(String action, String resource) throws NiFiRegistryException, IOException;
-
-    /**
-     * Creates a new access policy.
-     *
-     * @param policy The access policy to be created. Note: identifier will be ignored and assigned by NiFi Registry.
-     *
-     * @return The created access with an assigned identifier.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    AccessPolicy createAccessPolicy(AccessPolicy policy) throws NiFiRegistryException, IOException;
-
-    /**
-     * Updates an existing access policy.
-     *
-     * @param policy The access policy with new attributes.
-     *
-     * @return The updated access policy.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    AccessPolicy updateAccessPolicy(AccessPolicy policy) throws NiFiRegistryException, IOException;
-}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/TenantsClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/TenantsClient.java
deleted file mode 100644
index ab4c17b..0000000
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/TenantsClient.java
+++ /dev/null
@@ -1,122 +0,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.
- */
-package org.apache.nifi.toolkit.cli.impl.client.registry;
-
-import org.apache.nifi.registry.authorization.User;
-import org.apache.nifi.registry.authorization.UserGroup;
-import org.apache.nifi.registry.client.NiFiRegistryException;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Provides API for tenant (user/group) related services available in NiFi Registry.
- */
-public interface TenantsClient {
-
-    /**
-     * Returns all users.
-     *
-     * @return The list of users.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    List<User> getUsers() throws NiFiRegistryException, IOException;
-
-    /**
-     * Returns a user with a given identifier.
-     *
-     * @param id Identifier of the user.
-     *
-     * @return The user.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    User getUser(String id) throws NiFiRegistryException, IOException;
-
-    /**
-     * Creates a new user in NiFi Registry.
-     *
-     * @param user The new user. Note: identifier will be ignored and assigned be NiFi Registry.
-     *
-     * @return The created user with an assigned identifier.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    User createUser(User user) throws NiFiRegistryException, IOException;
-
-    /**
-     * Updates an existing user.
-     *
-     * @param user The user with the new attributes.
-     *
-     * @return The updated user.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    User updateUser(User user) throws NiFiRegistryException, IOException;
-
-    /**
-     * Returns all user groups.
-     *
-     * @return The list of user groups.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    List<UserGroup> getUserGroups() throws NiFiRegistryException, IOException;
-
-    /**
-     * Returns a user group with a given identifier.
-     *
-     * @param id Identifier of the user group.
-     *
-     * @return The user group.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    UserGroup getUserGroup(String id) throws NiFiRegistryException, IOException;
-
-    /**
-     * Creates a new user group.
-     *
-     * @param group The user group to be created. Note: identifier will be ignored and assigned by NiFi Registry.
-     *
-     * @return The created user group with an assigned identifier.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    UserGroup createUserGroup(UserGroup group) throws NiFiRegistryException, IOException;
-
-    /**
-     * Updates an existing user group.
-     *
-     * @param group The user group with new attributes.
-     *
-     * @return The user group after store.
-     *
-     * @throws NiFiRegistryException Thrown in case of unsuccessful execution.
-     * @throws IOException Thrown when there is an issue while communicating with NiFi Registry.
-     */
-    UserGroup updateUserGroup(UserGroup group) throws NiFiRegistryException, IOException;
-}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/impl/AbstractCRUDJerseyClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/impl/AbstractCRUDJerseyClient.java
deleted file mode 100644
index 4aef09b..0000000
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/impl/AbstractCRUDJerseyClient.java
+++ /dev/null
@@ -1,91 +0,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.
- */
-package org.apache.nifi.toolkit.cli.impl.client.registry.impl;
-
-import org.apache.nifi.registry.client.NiFiRegistryException;
-import org.apache.nifi.registry.client.impl.AbstractJerseyClient;
-import org.apache.nifi.util.StringUtils;
-
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.MediaType;
-import java.io.IOException;
-import java.util.Map;
-
-public class AbstractCRUDJerseyClient extends AbstractJerseyClient {
-    protected final WebTarget baseTarget;
-
-    public AbstractCRUDJerseyClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(headers);
-        this.baseTarget = baseTarget;
-    }
-
-    protected <T> T get(
-        String id,
-        Class<T> entityType,
-        String entityTypeName,
-        String entityPath
-    ) throws NiFiRegistryException, IOException {
-        if (StringUtils.isBlank(id)) {
-            throw new IllegalArgumentException(entityTypeName + " id cannot be blank");
-        }
-
-        return executeAction("Error retrieving " + entityTypeName.toLowerCase(), () -> {
-            final WebTarget target = baseTarget.path(entityPath).path(id);
-            return getRequestBuilder(target).get(entityType);
-        });
-    }
-
-    protected <T> T create(
-        T entity,
-        Class<T> entityType,
-        String entityTypeName,
-        String entityPath
-    ) throws NiFiRegistryException, IOException {
-        if (entity == null) {
-            throw new IllegalArgumentException(entityTypeName + " cannot be null");
-        }
-
-        return executeAction("Error creating " + entityTypeName.toLowerCase(), () -> {
-            final WebTarget target = baseTarget.path(entityPath);
-
-            return getRequestBuilder(target).post(
-                Entity.entity(entity, MediaType.APPLICATION_JSON_TYPE), entityType
-            );
-        });
-    }
-
-    protected <T> T update(
-        T entity,
-        String id,
-        Class<T> entityType,
-        String entityTypeName,
-        String entityPath
-    ) throws NiFiRegistryException, IOException {
-        if (entity == null) {
-            throw new IllegalArgumentException(entityTypeName + " cannot be null");
-        }
-
-        return executeAction("Error updating " + entityTypeName.toLowerCase(), () -> {
-            final WebTarget target = baseTarget.path(entityPath).path(id);
-
-            return getRequestBuilder(target).put(
-                Entity.entity(entity, MediaType.APPLICATION_JSON_TYPE), entityType
-            );
-        });
-    }
-}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/impl/JerseyPoliciesClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/impl/JerseyPoliciesClient.java
deleted file mode 100644
index 282234a..0000000
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/impl/JerseyPoliciesClient.java
+++ /dev/null
@@ -1,62 +0,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.
- */
-package org.apache.nifi.toolkit.cli.impl.client.registry.impl;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.registry.authorization.AccessPolicy;
-import org.apache.nifi.registry.client.NiFiRegistryException;
-import org.apache.nifi.toolkit.cli.impl.client.registry.PoliciesClient;
-
-import javax.ws.rs.client.WebTarget;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
-
-public class JerseyPoliciesClient extends AbstractCRUDJerseyClient implements PoliciesClient {
-    public static final String ACCESS_POLICY = "Access policy";
-    public static final String POLICIES_PATH = "policies";
-
-    public JerseyPoliciesClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
-    }
-
-    public JerseyPoliciesClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(baseTarget, headers);
-    }
-
-    @Override
-    public AccessPolicy getAccessPolicy(String action, String resource) throws NiFiRegistryException, IOException {
-        if (StringUtils.isBlank(resource) || StringUtils.isBlank(action)) {
-            throw new IllegalArgumentException("Resource and action cannot be null");
-        }
-
-        return executeAction("Error retrieving access policy", () -> {
-            final WebTarget target = baseTarget.path(POLICIES_PATH).path(action).path(resource);
-            return getRequestBuilder(target).get(AccessPolicy.class);
-        });
-    }
-
-    @Override
-    public AccessPolicy createAccessPolicy(final AccessPolicy policy) throws NiFiRegistryException, IOException {
-        return create(policy, AccessPolicy.class, ACCESS_POLICY, POLICIES_PATH);
-    }
-
-    @Override
-    public AccessPolicy updateAccessPolicy(final AccessPolicy policy) throws NiFiRegistryException, IOException {
-        return update(policy, policy.getIdentifier(), AccessPolicy.class, ACCESS_POLICY, POLICIES_PATH);
-    }
-}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/impl/JerseyTenantsClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/impl/JerseyTenantsClient.java
deleted file mode 100644
index d59d8f8..0000000
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/registry/impl/JerseyTenantsClient.java
+++ /dev/null
@@ -1,91 +0,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.
- */
-package org.apache.nifi.toolkit.cli.impl.client.registry.impl;
-
-import org.apache.nifi.registry.authorization.User;
-import org.apache.nifi.registry.authorization.UserGroup;
-import org.apache.nifi.registry.client.NiFiRegistryException;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
-
-import javax.ws.rs.client.WebTarget;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-public class JerseyTenantsClient extends AbstractCRUDJerseyClient implements TenantsClient {
-    public static final String USER = "User";
-    public static final String USERS_PATH = "users";
-
-    public static final String USER_GROUP = "User group";
-    public static final String USER_GROUPS_PATH = "user-groups";
-
-    public JerseyTenantsClient(final WebTarget baseTarget) {
-        this(baseTarget, Collections.emptyMap());
-    }
-
-    public JerseyTenantsClient(final WebTarget baseTarget, final Map<String, String> headers) {
-        super(baseTarget.path("/tenants"), headers);
-    }
-
-    @Override
-    public List<User> getUsers() throws NiFiRegistryException, IOException {
-        return executeAction("Error retrieving users", () -> {
-            final WebTarget target = baseTarget.path(USERS_PATH);
-            return Arrays.asList(getRequestBuilder(target).get(User[].class));
-        });
-    }
-
-    @Override
-    public User getUser(final String id) throws NiFiRegistryException, IOException {
-        return get(id, User.class, USER, USERS_PATH);
-    }
-
-    @Override
-    public User createUser(final User user) throws NiFiRegistryException, IOException {
-        return create(user, User.class, USER, USERS_PATH);
-    }
-
-    @Override
-    public User updateUser(final User user) throws NiFiRegistryException, IOException {
-        return update(user, user.getIdentifier(), User.class, USER, USERS_PATH);
-    }
-
-    @Override
-    public List<UserGroup> getUserGroups() throws NiFiRegistryException, IOException {
-        return executeAction("Error retrieving users", () -> {
-            final WebTarget target = baseTarget.path(USER_GROUPS_PATH);
-            return Arrays.asList(getRequestBuilder(target).get(UserGroup[].class));
-        });
-    }
-
-    @Override
-    public UserGroup getUserGroup(final String id) throws NiFiRegistryException, IOException {
-        return get(id, UserGroup.class, USER_GROUP, USER_GROUPS_PATH);
-    }
-
-    @Override
-    public UserGroup createUserGroup(final UserGroup group) throws NiFiRegistryException, IOException {
-        return create(group, UserGroup.class, USER_GROUP, USER_GROUPS_PATH);
-    }
-
-    @Override
-    public UserGroup updateUserGroup(final UserGroup group) throws NiFiRegistryException, IOException {
-        return update(group, group.getIdentifier(), UserGroup.class, USER_GROUP, USER_GROUPS_PATH);
-    }
-}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/AbstractCommand.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/AbstractCommand.java
index 948f394..2d6735f 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/AbstractCommand.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/AbstractCommand.java
@@ -77,6 +77,11 @@ public abstract class AbstractCommand<R extends Result> implements Command<R> {
 
         options.addOption(CommandOption.PROXIED_ENTITY.createOption());
 
+        options.addOption(CommandOption.BASIC_AUTH_USER.createOption());
+        options.addOption(CommandOption.BASIC_AUTH_PASSWORD.createOption());
+
+        options.addOption(CommandOption.BEARER_TOKEN.createOption());
+
         options.addOption(CommandOption.OUTPUT_TYPE.createOption());
         options.addOption(CommandOption.VERBOSE.createOption());
         options.addOption(CommandOption.HELP.createOption());
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java
index 324272e..02263e9 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java
@@ -132,6 +132,18 @@ public enum CommandOption {
     PROXIED_ENTITY("pe", "proxiedEntity", "The identity of an entity to proxy", true),
     PROTOCOL("pro", "protocol", "The security protocol to use, such as TLSv.1.2", true),
 
+    BASIC_AUTH_USER("bau", "basicAuthUsername", "The username for basic auth", true),
+    BASIC_AUTH_PASSWORD("bap", "basicAuthPassword", "The password for basic auth ", true),
+
+    BEARER_TOKEN("btk", "bearerToken", "The bearer token to be passed in the Authorization header of a request", true),
+
+    USERNAME("usr", "username", "The username for authentication when obtaining an access token", true),
+    PASSWORD("pwd", "password", "The password for authentication when obtaining an access token", true),
+
+    KERBEROS_PRINCIPAL("krbPr", "kerberosPrincipal", "The kerberos principal", true),
+    KERBEROS_KEYTAB("krbKt", "kerberosKeytab", "The keytab for a kerberos principal", true, true),
+    KERBEROS_PASSWORD("krbPw", "kerberosPassword", "The password for a kerberos principal", true),
+
     // Miscellaneous
     FORCE("force", "force", "Indicates to force a delete operation", false),
     OUTPUT_TYPE("ot", "outputType", "The type of output to produce (json or simple)", true),
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java
index 1c80c06..c112e0a 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java
@@ -18,6 +18,9 @@ package org.apache.nifi.toolkit.cli.impl.command.nifi;
 
 import org.apache.nifi.toolkit.cli.api.Command;
 import org.apache.nifi.toolkit.cli.impl.command.AbstractCommandGroup;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.access.GetAccessToken;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.access.GetAccessTokenSpnego;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.access.LogoutAccessToken;
 import org.apache.nifi.toolkit.cli.impl.command.nifi.cs.DisableControllerServices;
 import org.apache.nifi.toolkit.cli.impl.command.nifi.cs.EnableControllerServices;
 import org.apache.nifi.toolkit.cli.impl.command.nifi.flow.ClusterSummary;
@@ -156,6 +159,9 @@ public class NiFiCommandGroup extends AbstractCommandGroup {
         commands.add(new ExportParamContext());
         commands.add(new ImportParamContext());
         commands.add(new MergeParamContext());
+        commands.add(new GetAccessToken());
+        commands.add(new GetAccessTokenSpnego());
+        commands.add(new LogoutAccessToken());
         return new ArrayList<>(commands);
     }
 }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/access/GetAccessToken.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/access/GetAccessToken.java
new file mode 100644
index 0000000..437ffdd
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/access/GetAccessToken.java
@@ -0,0 +1,59 @@
+/*
+ * 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.toolkit.cli.impl.command.nifi.access;
+
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.nifi.toolkit.cli.api.CommandException;
+import org.apache.nifi.toolkit.cli.api.Context;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.AbstractNiFiCommand;
+import org.apache.nifi.toolkit.cli.impl.result.StringResult;
+
+import java.io.IOException;
+import java.util.Properties;
+
+public class GetAccessToken extends AbstractNiFiCommand<StringResult> {
+
+    public GetAccessToken() {
+        super("get-access-token", StringResult.class);
+    }
+
+    @Override
+    public String getDescription() {
+        return "Authenticates to NiFi with the given username and password and returns an access token for use " +
+                "on future requests as the value of the " + CommandOption.BEARER_TOKEN.getLongName() + " argument";
+    }
+
+    @Override
+    public void doInitialize(final Context context) {
+        addOption(CommandOption.USERNAME.createOption());
+        addOption(CommandOption.PASSWORD.createOption());
+    }
+
+    @Override
+    public StringResult doExecute(final NiFiClient client, final Properties properties)
+            throws NiFiClientException, IOException, MissingOptionException, CommandException {
+
+        final String username = getRequiredArg(properties, CommandOption.USERNAME);
+        final String password = getRequiredArg(properties, CommandOption.PASSWORD);
+
+        final String token = client.getAccessClient().getToken(username, password);
+        return new StringResult(token, getContext().isInteractive());
+    }
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/access/GetAccessTokenSpnego.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/access/GetAccessTokenSpnego.java
new file mode 100644
index 0000000..e5433cf
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/access/GetAccessTokenSpnego.java
@@ -0,0 +1,94 @@
+/*
+ * 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.toolkit.cli.impl.command.nifi.access;
+
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.nifi.documentation.init.NopComponentLog;
+import org.apache.nifi.security.krb.KerberosAction;
+import org.apache.nifi.security.krb.KerberosKeytabUser;
+import org.apache.nifi.security.krb.KerberosPasswordUser;
+import org.apache.nifi.security.krb.KerberosTicketCacheUser;
+import org.apache.nifi.security.krb.KerberosUser;
+import org.apache.nifi.toolkit.cli.api.CommandException;
+import org.apache.nifi.toolkit.cli.api.Context;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.AbstractNiFiCommand;
+import org.apache.nifi.toolkit.cli.impl.result.StringResult;
+import org.apache.nifi.util.StringUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Properties;
+
+public class GetAccessTokenSpnego extends AbstractNiFiCommand<StringResult> {
+
+    public GetAccessTokenSpnego() {
+        super("get-access-token-spnego", StringResult.class);
+    }
+
+    @Override
+    public String getDescription() {
+        return "Authenticates to NiFi via SPNEGO and returns an access token for use " +
+                "on future requests as the value of the " + CommandOption.BEARER_TOKEN.getLongName() + " argument. " +
+                "If a keytab or password is not specified, then the ticket cache will be used and it is " +
+                "assumed that a kinit was done for the given principal outside of the CLI.";
+    }
+
+    @Override
+    public void doInitialize(final Context context) {
+        addOption(CommandOption.KERBEROS_PRINCIPAL.createOption());
+        addOption(CommandOption.KERBEROS_KEYTAB.createOption());
+        addOption(CommandOption.KERBEROS_PASSWORD.createOption());
+    }
+
+    @Override
+    public StringResult doExecute(final NiFiClient client, final Properties properties)
+            throws NiFiClientException, IOException, MissingOptionException, CommandException {
+
+        final String principal = getRequiredArg(properties, CommandOption.KERBEROS_PRINCIPAL);
+
+        final String keytab = getArg(properties, CommandOption.KERBEROS_KEYTAB);
+        final String password = getArg(properties, CommandOption.KERBEROS_PASSWORD);
+
+        if (!StringUtils.isBlank(keytab) && !StringUtils.isBlank(password)) {
+            throw new MissingOptionException("Only one of keytab or password can be specified");
+        }
+
+        final KerberosUser kerberosUser;
+        if (!StringUtils.isBlank(keytab)) {
+            final File keytabFile = new File(keytab);
+            if (!keytabFile.exists()) {
+                throw new CommandException("Unable to find keytab file at: " + keytabFile.getAbsolutePath());
+            }
+            kerberosUser = new KerberosKeytabUser(principal, keytab);
+        } else if (!StringUtils.isBlank(password)) {
+            kerberosUser = new KerberosPasswordUser(principal, password);
+        } else {
+            kerberosUser = new KerberosTicketCacheUser(principal);
+        }
+
+        final KerberosAction<String> kerberosAction = new KerberosAction<>(
+                kerberosUser,
+                () -> client.getAccessClient().getTokenFromKerberosTicket(),
+                new NopComponentLog());
+
+        final String token = kerberosAction.execute();
+        return new StringResult(token, getContext().isInteractive());
+    }
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/access/LogoutAccessToken.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/access/LogoutAccessToken.java
new file mode 100644
index 0000000..a0b8d74
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/access/LogoutAccessToken.java
@@ -0,0 +1,54 @@
+/*
+ * 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.toolkit.cli.impl.command.nifi.access;
+
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.nifi.toolkit.cli.api.CommandException;
+import org.apache.nifi.toolkit.cli.api.Context;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.AbstractNiFiCommand;
+import org.apache.nifi.toolkit.cli.impl.result.VoidResult;
+
+import java.io.IOException;
+import java.util.Properties;
+
+public class LogoutAccessToken extends AbstractNiFiCommand<VoidResult> {
+
+    public LogoutAccessToken() {
+        super("logout-access-token", VoidResult.class);
+    }
+
+    @Override
+    public String getDescription() {
+        return "Performs a logout for the given access token";
+    }
+
+    @Override
+    public void doInitialize(final Context context) {
+        addOption(CommandOption.BEARER_TOKEN.createOption());
+    }
+
+    @Override
+    public VoidResult doExecute(final NiFiClient client, final Properties properties)
+            throws NiFiClientException, IOException, MissingOptionException, CommandException {
+        final String bearerToken = getRequiredArg(properties, CommandOption.BEARER_TOKEN);
+        client.getAccessClient().logout(bearerToken);
+        return VoidResult.getInstance();
+    }
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/AbstractNiFiRegistryCommand.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/AbstractNiFiRegistryCommand.java
index 2556bc4..5975ee5 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/AbstractNiFiRegistryCommand.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/AbstractNiFiRegistryCommand.java
@@ -67,7 +67,7 @@ public abstract class AbstractNiFiRegistryCommand<R extends Result> extends Abst
      * @return the Result of executing the command
      */
     public abstract R doExecute(final NiFiRegistryClient client, final Properties properties)
-            throws IOException, NiFiRegistryException, ParseException;
+            throws IOException, NiFiRegistryException, ParseException, CommandException;
 
     protected List<Integer> getVersions(final NiFiRegistryClient client, final String flowId)
             throws NiFiRegistryException, IOException {
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/NiFiRegistryCommandGroup.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/NiFiRegistryCommandGroup.java
index b8f2516..5a9a42b 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/NiFiRegistryCommandGroup.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/NiFiRegistryCommandGroup.java
@@ -18,6 +18,9 @@ package org.apache.nifi.toolkit.cli.impl.command.registry;
 
 import org.apache.nifi.toolkit.cli.api.Command;
 import org.apache.nifi.toolkit.cli.impl.command.AbstractCommandGroup;
+import org.apache.nifi.toolkit.cli.impl.command.registry.access.GetAccessToken;
+import org.apache.nifi.toolkit.cli.impl.command.registry.access.GetAccessTokenSpnego;
+import org.apache.nifi.toolkit.cli.impl.command.registry.access.LogoutAccessToken;
 import org.apache.nifi.toolkit.cli.impl.command.registry.bucket.CreateBucket;
 import org.apache.nifi.toolkit.cli.impl.command.registry.bucket.DeleteBucket;
 import org.apache.nifi.toolkit.cli.impl.command.registry.bucket.ListBuckets;
@@ -98,6 +101,9 @@ public class NiFiRegistryCommandGroup extends AbstractCommandGroup {
         commandList.add(new GetAccessPolicy());
         commandList.add(new CreateOrUpdateAccessPolicy());
         commandList.add(new UpdateBucketPolicy());
+        commandList.add(new GetAccessToken());
+        commandList.add(new GetAccessTokenSpnego());
+        commandList.add(new LogoutAccessToken());
         return new ArrayList<>(commandList);
     }
 }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUser.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/access/GetAccessToken.java
similarity index 52%
copy from nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUser.java
copy to nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/access/GetAccessToken.java
index 21ac38a..4916363 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUser.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/access/GetAccessToken.java
@@ -14,15 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.nifi.toolkit.cli.impl.command.registry.tenant;
+package org.apache.nifi.toolkit.cli.impl.command.registry.access;
 
 import org.apache.commons.cli.ParseException;
-import org.apache.nifi.registry.authorization.User;
 import org.apache.nifi.registry.client.NiFiRegistryClient;
 import org.apache.nifi.registry.client.NiFiRegistryException;
 import org.apache.nifi.toolkit.cli.api.Context;
-import org.apache.nifi.toolkit.cli.impl.client.ExtendedNiFiRegistryClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
 import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
 import org.apache.nifi.toolkit.cli.impl.result.StringResult;
@@ -30,40 +27,32 @@ import org.apache.nifi.toolkit.cli.impl.result.StringResult;
 import java.io.IOException;
 import java.util.Properties;
 
-/**
- * Command for creating a user.
- */
-public class CreateUser extends AbstractNiFiRegistryCommand<StringResult> {
+public class GetAccessToken extends AbstractNiFiRegistryCommand<StringResult> {
 
-    public CreateUser() {
-        super("create-user", StringResult.class);
+    public GetAccessToken() {
+        super("get-access-token", StringResult.class);
     }
 
     @Override
     public String getDescription() {
-        return "Creates a new user.";
+        return "Authenticates to NiFi Registry with the given username and password and returns an access token for use " +
+                "on future requests as the value of the " + CommandOption.BEARER_TOKEN.getLongName() + " argument";
     }
 
     @Override
-    protected void doInitialize(final Context context) {
-        addOption(CommandOption.USER_NAME.createOption());
+    public void doInitialize(final Context context) {
+        addOption(CommandOption.USERNAME.createOption());
+        addOption(CommandOption.PASSWORD.createOption());
     }
 
     @Override
-    public StringResult doExecute(final NiFiRegistryClient client, final Properties properties)
+    public StringResult doExecute(NiFiRegistryClient client, Properties properties)
             throws IOException, NiFiRegistryException, ParseException {
 
-        if (!(client instanceof ExtendedNiFiRegistryClient)) {
-            throw new IllegalArgumentException("This command needs extended registry client!");
-        }
-
-        final ExtendedNiFiRegistryClient extendedClient = (ExtendedNiFiRegistryClient) client;
-        final TenantsClient tenantsClient = extendedClient.getTenantsClient();
-
-        final String userName = getRequiredArg(properties, CommandOption.USER_NAME);
-        final User user = new User(null, userName);
-        final User createdUser = tenantsClient.createUser(user);
+        final String username = getRequiredArg(properties, CommandOption.USERNAME);
+        final String password = getRequiredArg(properties, CommandOption.PASSWORD);
 
-        return new StringResult(createdUser.getIdentifier(), getContext().isInteractive());
+        final String token = client.getAccessClient().getToken(username, password);
+        return new StringResult(token, getContext().isInteractive());
     }
 }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/access/GetAccessTokenSpnego.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/access/GetAccessTokenSpnego.java
new file mode 100644
index 0000000..7fa6ce5
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/access/GetAccessTokenSpnego.java
@@ -0,0 +1,96 @@
+/*
+ * 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.toolkit.cli.impl.command.registry.access;
+
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.commons.cli.ParseException;
+import org.apache.nifi.documentation.init.NopComponentLog;
+import org.apache.nifi.registry.client.NiFiRegistryClient;
+import org.apache.nifi.registry.client.NiFiRegistryException;
+import org.apache.nifi.security.krb.KerberosAction;
+import org.apache.nifi.security.krb.KerberosKeytabUser;
+import org.apache.nifi.security.krb.KerberosPasswordUser;
+import org.apache.nifi.security.krb.KerberosTicketCacheUser;
+import org.apache.nifi.security.krb.KerberosUser;
+import org.apache.nifi.toolkit.cli.api.CommandException;
+import org.apache.nifi.toolkit.cli.api.Context;
+import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
+import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
+import org.apache.nifi.toolkit.cli.impl.result.StringResult;
+import org.apache.nifi.util.StringUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Properties;
+
+public class GetAccessTokenSpnego extends AbstractNiFiRegistryCommand<StringResult> {
+
+    public GetAccessTokenSpnego() {
+        super("get-access-token-spnego", StringResult.class);
+    }
+
+    @Override
+    public String getDescription() {
+        return "Authenticates to NiFi Registry via SPNEGO and returns an access token for use " +
+                "on future requests as the value of the " + CommandOption.BEARER_TOKEN.getLongName() + " argument. " +
+                "If a keytab or password is not specified, then the ticket cache will be used and it is " +
+                "assumed that a kinit was done for the given principal outside of the CLI.";
+    }
+
+    @Override
+    public void doInitialize(final Context context) {
+        addOption(CommandOption.KERBEROS_PRINCIPAL.createOption());
+        addOption(CommandOption.KERBEROS_KEYTAB.createOption());
+        addOption(CommandOption.KERBEROS_PASSWORD.createOption());
+    }
+
+    @Override
+    public StringResult doExecute(final NiFiRegistryClient client, final Properties properties)
+            throws IOException, NiFiRegistryException, ParseException, CommandException {
+
+        final String principal = getRequiredArg(properties, CommandOption.KERBEROS_PRINCIPAL);
+
+        final String keytab = getArg(properties, CommandOption.KERBEROS_KEYTAB);
+        final String password = getArg(properties, CommandOption.KERBEROS_PASSWORD);
+
+        if (!StringUtils.isBlank(keytab) && !StringUtils.isBlank(password)) {
+            throw new MissingOptionException("Only one of keytab or password can be specified");
+        }
+
+        final KerberosUser kerberosUser;
+        if (!StringUtils.isBlank(keytab)) {
+            final File keytabFile = new File(keytab);
+            if (!keytabFile.exists()) {
+                throw new CommandException("Unable to find keytab file at: " + keytabFile.getAbsolutePath());
+            }
+            kerberosUser = new KerberosKeytabUser(principal, keytab);
+        } else if (!StringUtils.isBlank(password)) {
+            kerberosUser = new KerberosPasswordUser(principal, password);
+        } else {
+            kerberosUser = new KerberosTicketCacheUser(principal);
+        }
+
+        final KerberosAction<String> kerberosAction = new KerberosAction<>(
+                kerberosUser,
+                () -> client.getAccessClient().getTokenFromKerberosTicket(),
+                new NopComponentLog());
+
+        final String token = kerberosAction.execute();
+        return new StringResult(token, getContext().isInteractive());
+    }
+
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/access/LogoutAccessToken.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/access/LogoutAccessToken.java
new file mode 100644
index 0000000..3d344a8
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/access/LogoutAccessToken.java
@@ -0,0 +1,55 @@
+/*
+ * 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.toolkit.cli.impl.command.registry.access;
+
+import org.apache.commons.cli.ParseException;
+import org.apache.nifi.registry.client.NiFiRegistryClient;
+import org.apache.nifi.registry.client.NiFiRegistryException;
+import org.apache.nifi.toolkit.cli.api.CommandException;
+import org.apache.nifi.toolkit.cli.api.Context;
+import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
+import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
+import org.apache.nifi.toolkit.cli.impl.result.VoidResult;
+
+import java.io.IOException;
+import java.util.Properties;
+
+public class LogoutAccessToken extends AbstractNiFiRegistryCommand<VoidResult> {
+
+    public LogoutAccessToken() {
+        super("logout-access-token", VoidResult.class);
+    }
+
+    @Override
+    public String getDescription() {
+        return "Performs a logout for the given access token";
+    }
+
+    @Override
+    public void doInitialize(final Context context) {
+        addOption(CommandOption.BEARER_TOKEN.createOption());
+    }
+
+    @Override
+    public VoidResult doExecute(NiFiRegistryClient client, Properties properties)
+            throws IOException, NiFiRegistryException, ParseException, CommandException {
+        final String bearerToken = getRequiredArg(properties, CommandOption.BEARER_TOKEN);
+        client.getAccessClient().logout(bearerToken);
+        return VoidResult.getInstance();
+    }
+
+}
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/bucket/UpdateBucketPolicy.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/bucket/UpdateBucketPolicy.java
index a89ab87..16a1e5e 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/bucket/UpdateBucketPolicy.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/bucket/UpdateBucketPolicy.java
@@ -22,9 +22,8 @@ import org.apache.nifi.registry.authorization.Tenant;
 import org.apache.nifi.registry.bucket.Bucket;
 import org.apache.nifi.registry.client.NiFiRegistryClient;
 import org.apache.nifi.registry.client.NiFiRegistryException;
+import org.apache.nifi.registry.client.PoliciesClient;
 import org.apache.nifi.toolkit.cli.api.Context;
-import org.apache.nifi.toolkit.cli.impl.client.ExtendedNiFiRegistryClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.PoliciesClient;
 import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
 import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
 import org.apache.nifi.toolkit.cli.impl.command.registry.tenant.TenantHelper;
@@ -64,11 +63,7 @@ public class UpdateBucketPolicy extends AbstractNiFiRegistryCommand<StringResult
 
     @Override
     public StringResult doExecute(NiFiRegistryClient client, Properties properties) throws IOException, NiFiRegistryException, ParseException {
-        if (!(client instanceof ExtendedNiFiRegistryClient)) {
-            throw new IllegalArgumentException("This command needs extended registry client!");
-        }
-        final ExtendedNiFiRegistryClient extendedClient = (ExtendedNiFiRegistryClient) client;
-        final PoliciesClient policiesClient = extendedClient.getPoliciesClient();
+        final PoliciesClient policiesClient = client.getPoliciesClient();
 
         final String bucketName = getArg(properties, CommandOption.BUCKET_NAME);
         String bucketId = getArg(properties, CommandOption.BUCKET_ID);
@@ -95,7 +90,7 @@ public class UpdateBucketPolicy extends AbstractNiFiRegistryCommand<StringResult
             bucketId = optionalBucket.get().getIdentifier();
         } else {
             try {
-                extendedClient.getBucketClient().get(bucketId);
+                client.getBucketClient().get(bucketId);
             } catch (NiFiRegistryException e) {
                 throw new IllegalArgumentException("Specified bucket does not exist");
             }
@@ -111,13 +106,13 @@ public class UpdateBucketPolicy extends AbstractNiFiRegistryCommand<StringResult
         }
         if (!StringUtils.isBlank(userNames) || !StringUtils.isBlank(userIds)) {
             Set<Tenant> users = TenantHelper.selectExistingTenants(userNames,
-                    userIds, extendedClient.getTenantsClient().getUsers());
+                    userIds, client.getTenantsClient().getUsers());
             //Overwrite users, similar to CreateOrUpdateAccessPolicy of Registry
             accessPolicy.setUsers(users);
         }
         if (!StringUtils.isBlank(groupNames) || !StringUtils.isBlank(groupIds)) {
             Set<Tenant> groups = TenantHelper.selectExistingTenants(groupNames,
-                    groupIds, extendedClient.getTenantsClient().getUserGroups());
+                    groupIds, client.getTenantsClient().getUserGroups());
             //Overwrite user-groups, similar to CreateOrUpdateAccessPolicy of Registry
             accessPolicy.setUserGroups(groups);
         }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/policy/CreateOrUpdateAccessPolicy.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/policy/CreateOrUpdateAccessPolicy.java
index 9a4f977..7990edc 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/policy/CreateOrUpdateAccessPolicy.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/policy/CreateOrUpdateAccessPolicy.java
@@ -22,10 +22,9 @@ import org.apache.nifi.registry.authorization.AccessPolicy;
 import org.apache.nifi.registry.authorization.Tenant;
 import org.apache.nifi.registry.client.NiFiRegistryClient;
 import org.apache.nifi.registry.client.NiFiRegistryException;
+import org.apache.nifi.registry.client.PoliciesClient;
+import org.apache.nifi.registry.client.TenantsClient;
 import org.apache.nifi.toolkit.cli.api.Context;
-import org.apache.nifi.toolkit.cli.impl.client.ExtendedNiFiRegistryClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.PoliciesClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
 import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
 import org.apache.nifi.toolkit.cli.impl.command.registry.tenant.TenantHelper;
@@ -67,13 +66,8 @@ public class CreateOrUpdateAccessPolicy extends AbstractNiFiRegistryCommand<Void
 
     @Override
     public VoidResult doExecute(final NiFiRegistryClient client, final Properties properties) throws IOException, NiFiRegistryException, ParseException {
-        if (!(client instanceof ExtendedNiFiRegistryClient)) {
-            throw new IllegalArgumentException("This command needs extended registry client!");
-        }
-        final ExtendedNiFiRegistryClient extendedClient = (ExtendedNiFiRegistryClient) client;
-
-        final PoliciesClient policiesClient = extendedClient.getPoliciesClient();
-        final TenantsClient tenantsClient = extendedClient.getTenantsClient();
+        final PoliciesClient policiesClient = client.getPoliciesClient();
+        final TenantsClient tenantsClient = client.getTenantsClient();
 
         final String action = getRequiredArg(properties, CommandOption.POLICY_ACTION);
         final String resource = getRequiredArg(properties, CommandOption.POLICY_RESOURCE);
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/policy/GetAccessPolicy.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/policy/GetAccessPolicy.java
index 278e540..72994db 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/policy/GetAccessPolicy.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/policy/GetAccessPolicy.java
@@ -20,9 +20,8 @@ import org.apache.commons.cli.ParseException;
 import org.apache.nifi.registry.authorization.AccessPolicy;
 import org.apache.nifi.registry.client.NiFiRegistryClient;
 import org.apache.nifi.registry.client.NiFiRegistryException;
+import org.apache.nifi.registry.client.PoliciesClient;
 import org.apache.nifi.toolkit.cli.api.Context;
-import org.apache.nifi.toolkit.cli.impl.client.ExtendedNiFiRegistryClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.PoliciesClient;
 import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
 import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
 import org.apache.nifi.toolkit.cli.impl.result.registry.AccessPolicyResult;
@@ -51,12 +50,7 @@ public class GetAccessPolicy extends AbstractNiFiRegistryCommand<AccessPolicyRes
 
     @Override
     public AccessPolicyResult doExecute(final NiFiRegistryClient client, final Properties properties) throws IOException, NiFiRegistryException, ParseException {
-        if (!(client instanceof ExtendedNiFiRegistryClient)) {
-            throw new IllegalArgumentException("This command needs extended registry client!");
-        }
-        final ExtendedNiFiRegistryClient extendedClient = (ExtendedNiFiRegistryClient) client;
-
-        final PoliciesClient policiesClient = extendedClient.getPoliciesClient();
+        final PoliciesClient policiesClient = client.getPoliciesClient();
 
         final String action = getRequiredArg(properties, CommandOption.POLICY_ACTION);
         final String resource = getRequiredArg(properties, CommandOption.POLICY_RESOURCE);
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/AbstractListTenants.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/AbstractListTenants.java
index 58b631f..6c923e6 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/AbstractListTenants.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/AbstractListTenants.java
@@ -20,9 +20,8 @@ import org.apache.commons.cli.ParseException;
 import org.apache.nifi.registry.authorization.Tenant;
 import org.apache.nifi.registry.client.NiFiRegistryClient;
 import org.apache.nifi.registry.client.NiFiRegistryException;
+import org.apache.nifi.registry.client.TenantsClient;
 import org.apache.nifi.toolkit.cli.api.Result;
-import org.apache.nifi.toolkit.cli.impl.client.ExtendedNiFiRegistryClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
 
 import java.io.IOException;
@@ -43,12 +42,7 @@ public abstract class AbstractListTenants<T extends Tenant, R extends Result> ex
     public R doExecute(final NiFiRegistryClient client, final Properties properties)
         throws IOException, NiFiRegistryException, ParseException {
 
-        if (!(client instanceof ExtendedNiFiRegistryClient)) {
-            throw new IllegalArgumentException("This command needs extended registry client!");
-        }
-
-        final ExtendedNiFiRegistryClient extendedClient = (ExtendedNiFiRegistryClient) client;
-        final TenantsClient tenantsClient = extendedClient.getTenantsClient();
+        final TenantsClient tenantsClient = client.getTenantsClient();
 
         return getTenants(properties, tenantsClient);
     }
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUser.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUser.java
index 21ac38a..5b4a5d5 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUser.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUser.java
@@ -20,9 +20,8 @@ import org.apache.commons.cli.ParseException;
 import org.apache.nifi.registry.authorization.User;
 import org.apache.nifi.registry.client.NiFiRegistryClient;
 import org.apache.nifi.registry.client.NiFiRegistryException;
+import org.apache.nifi.registry.client.TenantsClient;
 import org.apache.nifi.toolkit.cli.api.Context;
-import org.apache.nifi.toolkit.cli.impl.client.ExtendedNiFiRegistryClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
 import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
 import org.apache.nifi.toolkit.cli.impl.result.StringResult;
@@ -53,12 +52,7 @@ public class CreateUser extends AbstractNiFiRegistryCommand<StringResult> {
     public StringResult doExecute(final NiFiRegistryClient client, final Properties properties)
             throws IOException, NiFiRegistryException, ParseException {
 
-        if (!(client instanceof ExtendedNiFiRegistryClient)) {
-            throw new IllegalArgumentException("This command needs extended registry client!");
-        }
-
-        final ExtendedNiFiRegistryClient extendedClient = (ExtendedNiFiRegistryClient) client;
-        final TenantsClient tenantsClient = extendedClient.getTenantsClient();
+        final TenantsClient tenantsClient = client.getTenantsClient();
 
         final String userName = getRequiredArg(properties, CommandOption.USER_NAME);
         final User user = new User(null, userName);
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUserGroup.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUserGroup.java
index 212ba72..9df8c32 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUserGroup.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/CreateUserGroup.java
@@ -21,9 +21,8 @@ import org.apache.nifi.registry.authorization.Tenant;
 import org.apache.nifi.registry.authorization.UserGroup;
 import org.apache.nifi.registry.client.NiFiRegistryClient;
 import org.apache.nifi.registry.client.NiFiRegistryException;
+import org.apache.nifi.registry.client.TenantsClient;
 import org.apache.nifi.toolkit.cli.api.Context;
-import org.apache.nifi.toolkit.cli.impl.client.ExtendedNiFiRegistryClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
 import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
 import org.apache.nifi.toolkit.cli.impl.result.StringResult;
@@ -60,12 +59,7 @@ public class CreateUserGroup extends AbstractNiFiRegistryCommand<StringResult> {
     public StringResult doExecute(final NiFiRegistryClient client, final Properties properties)
             throws IOException, NiFiRegistryException, ParseException {
 
-        if (!(client instanceof ExtendedNiFiRegistryClient)) {
-            throw new IllegalArgumentException("This command needs extended registry client!");
-        }
-
-        final ExtendedNiFiRegistryClient extendedClient = (ExtendedNiFiRegistryClient) client;
-        final TenantsClient tenantsClient = extendedClient.getTenantsClient();
+        final TenantsClient tenantsClient = client.getTenantsClient();
 
         final String groupName = getRequiredArg(properties, CommandOption.UG_NAME);
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/ListUserGroups.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/ListUserGroups.java
index c8dd38e..2d07f83 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/ListUserGroups.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/ListUserGroups.java
@@ -18,7 +18,7 @@ package org.apache.nifi.toolkit.cli.impl.command.registry.tenant;
 
 import org.apache.nifi.registry.authorization.UserGroup;
 import org.apache.nifi.registry.client.NiFiRegistryException;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
+import org.apache.nifi.registry.client.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.result.registry.UserGroupsResult;
 
 import java.io.IOException;
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/ListUsers.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/ListUsers.java
index 52877ab..e97bb94 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/ListUsers.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/ListUsers.java
@@ -18,7 +18,7 @@ package org.apache.nifi.toolkit.cli.impl.command.registry.tenant;
 
 import org.apache.nifi.registry.authorization.User;
 import org.apache.nifi.registry.client.NiFiRegistryException;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
+import org.apache.nifi.registry.client.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.result.registry.UsersResult;
 
 import java.io.IOException;
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/UpdateUser.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/UpdateUser.java
index d2c8a05..1e6c606 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/UpdateUser.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/UpdateUser.java
@@ -21,9 +21,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.registry.authorization.User;
 import org.apache.nifi.registry.client.NiFiRegistryClient;
 import org.apache.nifi.registry.client.NiFiRegistryException;
+import org.apache.nifi.registry.client.TenantsClient;
 import org.apache.nifi.toolkit.cli.api.Context;
-import org.apache.nifi.toolkit.cli.impl.client.ExtendedNiFiRegistryClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
 import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
 import org.apache.nifi.toolkit.cli.impl.result.VoidResult;
@@ -57,12 +56,7 @@ public class UpdateUser extends AbstractNiFiRegistryCommand<VoidResult> {
     public VoidResult doExecute(final NiFiRegistryClient client, final Properties properties)
         throws IOException, NiFiRegistryException, ParseException {
 
-        if (!(client instanceof ExtendedNiFiRegistryClient)) {
-            throw new IllegalArgumentException("This command needs extended registry client!");
-        }
-
-        final ExtendedNiFiRegistryClient extendedClient = (ExtendedNiFiRegistryClient) client;
-        final TenantsClient tenantsClient = extendedClient.getTenantsClient();
+        final TenantsClient tenantsClient = client.getTenantsClient();
         final String userId = getRequiredArg(properties, CommandOption.USER_ID);
         final User existingUser = tenantsClient.getUser(userId);
 
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/UpdateUserGroup.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/UpdateUserGroup.java
index 45b0ff2..9d8d98f 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/UpdateUserGroup.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/tenant/UpdateUserGroup.java
@@ -22,9 +22,8 @@ import org.apache.nifi.registry.authorization.Tenant;
 import org.apache.nifi.registry.authorization.UserGroup;
 import org.apache.nifi.registry.client.NiFiRegistryClient;
 import org.apache.nifi.registry.client.NiFiRegistryException;
+import org.apache.nifi.registry.client.TenantsClient;
 import org.apache.nifi.toolkit.cli.api.Context;
-import org.apache.nifi.toolkit.cli.impl.client.ExtendedNiFiRegistryClient;
-import org.apache.nifi.toolkit.cli.impl.client.registry.TenantsClient;
 import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
 import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand;
 import org.apache.nifi.toolkit.cli.impl.result.VoidResult;
@@ -61,12 +60,8 @@ public class UpdateUserGroup extends AbstractNiFiRegistryCommand<VoidResult> {
     @Override
     public VoidResult doExecute(final NiFiRegistryClient client, final Properties properties)
             throws IOException, NiFiRegistryException, ParseException {
-        if (!(client instanceof ExtendedNiFiRegistryClient)) {
-            throw new IllegalArgumentException("This command needs extended registry client!");
-        }
 
-        final ExtendedNiFiRegistryClient extendedClient = (ExtendedNiFiRegistryClient) client;
-        final TenantsClient tenantsClient = extendedClient.getTenantsClient();
+        final TenantsClient tenantsClient = client.getTenantsClient();
         final String groupId = getRequiredArg(properties, CommandOption.UG_ID);
         final UserGroup existingGroup = tenantsClient.getUserGroup(groupId);
 
diff --git a/pom.xml b/pom.xml
index 519d0cc..e9983bc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -93,7 +93,7 @@
         <jetty.version>9.4.26.v20200117</jetty.version>
         <jackson.version>2.9.10</jackson.version>
         <jackson-databind.version>2.9.10.5</jackson-databind.version>
-        <nifi.registry.version>0.7.0</nifi.registry.version>
+        <nifi.registry.version>0.8.0</nifi.registry.version>
         <nifi.groovy.version>2.5.4</nifi.groovy.version>
         <surefire.version>2.22.2</surefire.version>
         <!-- The Hadoop version used by nifi-hadoop-libraries-nar and any NARs that depend on it, other NARs that need
@@ -623,6 +623,7 @@
                                     <failWhenParentIsSnapshot>false</failWhenParentIsSnapshot>
                                     <excludes>
                                         <exclude>org.apache.nifi:*</exclude>
+                                        <exclude>org.apache.nifi.registry:*</exclude>
                                     </excludes>
                                 </requireReleaseDeps>
                             </rules>