You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@nifi.apache.org by GitBox <gi...@apache.org> on 2020/05/27 13:51:52 UTC

[GitHub] [nifi] jdye64 commented on a change in pull request #4173: NIFI-7299 Add basic OAuth2 token provider controller service

jdye64 commented on a change in pull request #4173:
URL: https://github.com/apache/nifi/pull/4173#discussion_r431135321



##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-api/src/main/java/org/apache/nifi/oauth2/AccessToken.java
##########
@@ -0,0 +1,54 @@
+package org.apache.nifi.oauth2;

Review comment:
       Missing Apache license header here

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/pom.xml
##########
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements. See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+  http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-oauth2-provider-bundle</artifactId>
+        <version>1.12.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>nifi-oauth2-provider-service</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-oauth2-provider-api</artifactId>
+            <version>1.12.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-utils</artifactId>
+            <version>1.12.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-record</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-ssl-context-service-api</artifactId>
+            <version>1.12.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+
+<!--        <dependency>-->
+<!--            <groupId>com.github.stephenc.findbugs</groupId>-->
+<!--            <artifactId>findbugs-annotations</artifactId>-->
+<!--            <version>1.3.9-1</version>-->
+<!--        </dependency>-->

Review comment:
       could we remove this?

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProviderImpl.java
##########
@@ -0,0 +1,138 @@
+package org.apache.nifi.oauth2;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.FormBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import org.apache.nifi.annotation.lifecycle.OnEnabled;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.util.StringUtils;
+
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
+import java.util.List;
+
+import static org.apache.nifi.oauth2.Util.parseTokenResponse;
+
+public class OAuth2TokenProviderImpl extends AbstractControllerService implements OAuth2TokenProvider {
+    @Override
+    public List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return PROPERTIES;
+    }
+
+    private String resourceServerUrl;
+    private ObjectMapper mapper = new ObjectMapper();
+    private SSLContext sslContext;
+    private SSLContextService sslContextService;
+
+    @OnEnabled
+    public void onEnabled(ConfigurationContext context) {
+        resourceServerUrl = context.getProperty(ACCESS_TOKEN_URL).evaluateAttributeExpressions().getValue();
+
+        sslContextService = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextService.class);
+
+        sslContext = sslContextService == null ? null : sslContextService.createSSLContext(SSLContextService.ClientAuth.NONE);
+    }
+
+
+    @Override
+    public AccessToken getAccessTokenByPassword(String clientId, String clientSecret,
+                                                String username, String password) {
+        OkHttpClient.Builder builder = getClientBuilder();
+        OkHttpClient client = builder.build();
+
+        RequestBody body = new FormBody.Builder()
+                .add("username", username)
+                .add("password", password)
+                .add("client_id", clientId)
+                .add("client_secret", clientSecret)
+                .add("grant_type", "password")
+                .build();
+
+        Request newRequest = new Request.Builder()
+                .url(resourceServerUrl)
+                .post(body)
+                .build();
+
+        return executePost(client, newRequest);
+    }
+
+    private OkHttpClient.Builder getClientBuilder() {

Review comment:
       Could the client builder be created a single time when `onEnabled` is invoked? Otherwise it seems like this will be called several times and several OkHttpClient.Builder objects created/recreated when really only a single one is needed.
   
   Maybe they go stale? I don't know just want to throw it out there.

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/Util.java
##########
@@ -0,0 +1,122 @@
+package org.apache.nifi.oauth2;

Review comment:
       Missing Apache license header

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
##########
@@ -0,0 +1,15 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+org.apache.nifi.oauth2.OAuth2TokenProviderImpl

Review comment:
       Just syntactical but can we add a newline at end of file

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-api/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProvider.java
##########
@@ -0,0 +1,41 @@
+package org.apache.nifi.oauth2;

Review comment:
       Missing Apache license header here

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/Util.java
##########
@@ -0,0 +1,122 @@
+package org.apache.nifi.oauth2;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.OkHttpClient;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.util.StringUtils;
+
+import javax.net.ssl.*;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.util.Map;
+
+public class Util {
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    /**
+     * This code as taken from the InvokeHttp processor from Apache NiFi 1.10-SNAPSHOT found here:
+     *
+     * https://github.com/apache/nifi/blob/1cadc722229ad50cf569ee107eaeeb95dc216ea2/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java
+     * @param okHttpClientBuilder
+     * @param sslService
+     * @param sslContext
+     * @param setAsSocketFactory
+     * @throws IOException
+     * @throws KeyStoreException
+     * @throws CertificateException
+     * @throws NoSuchAlgorithmException
+     * @throws UnrecoverableKeyException
+     * @throws KeyManagementException
+     */
+    public static void setSslSocketFactory(OkHttpClient.Builder okHttpClientBuilder, SSLContextService sslService, SSLContext sslContext, boolean setAsSocketFactory)
+            throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
+
+        final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+        final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
+        // initialize the KeyManager array to null and we will overwrite later if a keystore is loaded
+        KeyManager[] keyManagers = null;
+
+        // we will only initialize the keystore if properties have been supplied by the SSLContextService
+        if (sslService.isKeyStoreConfigured()) {
+            final String keystoreLocation = sslService.getKeyStoreFile();
+            final String keystorePass = sslService.getKeyStorePassword();
+            final String keystoreType = sslService.getKeyStoreType();
+
+            // prepare the keystore
+            final KeyStore keyStore = KeyStore.getInstance(keystoreType);
+
+            try (FileInputStream keyStoreStream = new FileInputStream(keystoreLocation)) {
+                keyStore.load(keyStoreStream, keystorePass.toCharArray());
+            }
+
+            keyManagerFactory.init(keyStore, keystorePass.toCharArray());
+            keyManagers = keyManagerFactory.getKeyManagers();
+        }
+
+        // we will only initialize the truststure if properties have been supplied by the SSLContextService
+        if (sslService.isTrustStoreConfigured()) {
+            // load truststore
+            final String truststoreLocation = sslService.getTrustStoreFile();
+            final String truststorePass = sslService.getTrustStorePassword();
+            final String truststoreType = sslService.getTrustStoreType();
+
+            KeyStore truststore = KeyStore.getInstance(truststoreType);
+            truststore.load(new FileInputStream(truststoreLocation), truststorePass.toCharArray());
+            trustManagerFactory.init(truststore);
+        }
+
+         /*
+            TrustManagerFactory.getTrustManagers returns a trust manager for each type of trust material. Since we are getting a trust manager factory that uses "X509"
+            as it's trust management algorithm, we are able to grab the first (and thus the most preferred) and use it as our x509 Trust Manager
+            https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/TrustManagerFactory.html#getTrustManagers--
+         */
+        final X509TrustManager x509TrustManager;
+        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
+        if (trustManagers[0] != null) {
+            x509TrustManager = (X509TrustManager) trustManagers[0];
+        } else {
+            throw new IllegalStateException("List of trust managers is null");
+        }
+
+        // if keystore properties were not supplied, the keyManagers array will be null
+        sslContext.init(keyManagers, trustManagerFactory.getTrustManagers(), null);
+
+        final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+        okHttpClientBuilder.sslSocketFactory(sslSocketFactory, x509TrustManager);
+        if (setAsSocketFactory) {
+            okHttpClientBuilder.socketFactory(sslSocketFactory);
+        }
+    }

Review comment:
       @alopresto I would feel more comfortable if you would double check this

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/pom.xml
##########
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements. See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+  http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-standard-services</artifactId>
+        <version>1.12.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.apache.nifi</groupId>
+    <artifactId>nifi-oauth2-provider-bundle</artifactId>
+    <version>1.12.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <properties>
+        <hbase.version>2.2.2</hbase.version>
+    </properties>

Review comment:
       Why is a hbase version defined here?

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProviderImpl.java
##########
@@ -0,0 +1,138 @@
+package org.apache.nifi.oauth2;

Review comment:
       Missing Apache license header

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-api/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProvider.java
##########
@@ -0,0 +1,41 @@
+package org.apache.nifi.oauth2;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.Validator;
+import org.apache.nifi.controller.ControllerService;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.ssl.SSLContextService;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Interface for defining a credential-providing controller service for oauth2 processes.
+ */
+public interface OAuth2TokenProvider extends ControllerService {
+    PropertyDescriptor SSL_CONTEXT = new PropertyDescriptor.Builder()
+            .name("oauth2-ssl-context")
+            .displayName("SSL Context")
+            .addValidator(Validator.VALID)
+            .identifiesControllerService(SSLContextService.class)
+            .required(false)
+            .build();
+    PropertyDescriptor ACCESS_TOKEN_URL = new PropertyDescriptor.Builder()
+            .name("oauth2-access-token-url")
+            .displayName("Access Token Url")
+            .description("The full endpoint of the URL where access tokens are handled.")
+            .required(false)

Review comment:
       Shouldn't this always be required? Otherwise no token will ever be retrieved.

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-api/src/main/java/org/apache/nifi/oauth2/AccessToken.java
##########
@@ -0,0 +1,54 @@
+package org.apache.nifi.oauth2;
+
+public class AccessToken {
+    private String accessToken;
+    private String refreshToken;
+    private String tokenType;
+    private Integer expires;
+    private String scope;
+
+    private Long fetchTime;
+
+    public AccessToken() {}

Review comment:
       Typically a default constructor is not explicitly defined

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProviderImpl.java
##########
@@ -0,0 +1,138 @@
+package org.apache.nifi.oauth2;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.FormBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import org.apache.nifi.annotation.lifecycle.OnEnabled;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.util.StringUtils;
+
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
+import java.util.List;
+
+import static org.apache.nifi.oauth2.Util.parseTokenResponse;
+
+public class OAuth2TokenProviderImpl extends AbstractControllerService implements OAuth2TokenProvider {
+    @Override
+    public List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return PROPERTIES;
+    }
+
+    private String resourceServerUrl;
+    private ObjectMapper mapper = new ObjectMapper();

Review comment:
       I don't see where this is actually being used anywhere in this class? Can we remove

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/Util.java
##########
@@ -0,0 +1,122 @@
+package org.apache.nifi.oauth2;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.OkHttpClient;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.util.StringUtils;
+
+import javax.net.ssl.*;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.util.Map;
+
+public class Util {
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    /**
+     * This code as taken from the InvokeHttp processor from Apache NiFi 1.10-SNAPSHOT found here:
+     *
+     * https://github.com/apache/nifi/blob/1cadc722229ad50cf569ee107eaeeb95dc216ea2/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java
+     * @param okHttpClientBuilder
+     * @param sslService
+     * @param sslContext
+     * @param setAsSocketFactory
+     * @throws IOException
+     * @throws KeyStoreException
+     * @throws CertificateException
+     * @throws NoSuchAlgorithmException
+     * @throws UnrecoverableKeyException
+     * @throws KeyManagementException
+     */
+    public static void setSslSocketFactory(OkHttpClient.Builder okHttpClientBuilder, SSLContextService sslService, SSLContext sslContext, boolean setAsSocketFactory)
+            throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
+
+        final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+        final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
+        // initialize the KeyManager array to null and we will overwrite later if a keystore is loaded
+        KeyManager[] keyManagers = null;
+
+        // we will only initialize the keystore if properties have been supplied by the SSLContextService
+        if (sslService.isKeyStoreConfigured()) {
+            final String keystoreLocation = sslService.getKeyStoreFile();
+            final String keystorePass = sslService.getKeyStorePassword();
+            final String keystoreType = sslService.getKeyStoreType();
+
+            // prepare the keystore
+            final KeyStore keyStore = KeyStore.getInstance(keystoreType);
+
+            try (FileInputStream keyStoreStream = new FileInputStream(keystoreLocation)) {
+                keyStore.load(keyStoreStream, keystorePass.toCharArray());
+            }
+
+            keyManagerFactory.init(keyStore, keystorePass.toCharArray());
+            keyManagers = keyManagerFactory.getKeyManagers();
+        }
+
+        // we will only initialize the truststure if properties have been supplied by the SSLContextService
+        if (sslService.isTrustStoreConfigured()) {
+            // load truststore
+            final String truststoreLocation = sslService.getTrustStoreFile();
+            final String truststorePass = sslService.getTrustStorePassword();
+            final String truststoreType = sslService.getTrustStoreType();
+
+            KeyStore truststore = KeyStore.getInstance(truststoreType);
+            truststore.load(new FileInputStream(truststoreLocation), truststorePass.toCharArray());
+            trustManagerFactory.init(truststore);
+        }
+
+         /*
+            TrustManagerFactory.getTrustManagers returns a trust manager for each type of trust material. Since we are getting a trust manager factory that uses "X509"
+            as it's trust management algorithm, we are able to grab the first (and thus the most preferred) and use it as our x509 Trust Manager
+            https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/TrustManagerFactory.html#getTrustManagers--
+         */
+        final X509TrustManager x509TrustManager;
+        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
+        if (trustManagers[0] != null) {
+            x509TrustManager = (X509TrustManager) trustManagers[0];
+        } else {
+            throw new IllegalStateException("List of trust managers is null");
+        }
+
+        // if keystore properties were not supplied, the keyManagers array will be null
+        sslContext.init(keyManagers, trustManagerFactory.getTrustManagers(), null);
+
+        final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+        okHttpClientBuilder.sslSocketFactory(sslSocketFactory, x509TrustManager);
+        if (setAsSocketFactory) {
+            okHttpClientBuilder.socketFactory(sslSocketFactory);
+        }
+    }
+
+    public static final String KEY_ACCESS_TOKEN = "access_token";
+    public static final String KEY_REFRESH_TOKEN = "refresh_token";
+    public static final String KEY_EXPIRES = "expires_in";
+    public static final String KEY_TOKEN_TYPE = "token_type";
+    public static final String KEY_SCOPE = "scope";
+
+    public static AccessToken parseTokenResponse(String rawResponse) {
+        try {
+            Map<String, Object> parsed = new ObjectMapper().readValue(rawResponse, Map.class);
+            String accessToken = (String)parsed.get(KEY_ACCESS_TOKEN);
+            String refreshToken = (String)parsed.get(KEY_REFRESH_TOKEN);
+            Integer expires = (Integer)parsed.get(KEY_EXPIRES);
+            String tokenType = (String)parsed.get(KEY_TOKEN_TYPE);
+            String scope = (String)parsed.get(KEY_SCOPE);
+
+            if (StringUtils.isEmpty(accessToken)) {
+                throw new Exception(String.format("Missing value for %s", KEY_ACCESS_TOKEN));
+            }
+
+            if (StringUtils.isEmpty(tokenType)) {
+                throw new Exception(String.format("Missing value for %s", KEY_TOKEN_TYPE));
+            }
+
+            return new AccessToken(accessToken, refreshToken, tokenType, expires, scope);
+        } catch (Exception ex) {
+            throw new ProcessException(ex);

Review comment:
       Just a question, how do you envision a consuming processor to behave when something like this occurs?

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProviderImpl.java
##########
@@ -0,0 +1,138 @@
+package org.apache.nifi.oauth2;
+
+import com.fasterxml.jackson.databind.ObjectMapper;

Review comment:
       likewise if the ObjectMapper isn't being used we should remove the import

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProviderImpl.java
##########
@@ -0,0 +1,138 @@
+package org.apache.nifi.oauth2;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.FormBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import org.apache.nifi.annotation.lifecycle.OnEnabled;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.util.StringUtils;
+
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
+import java.util.List;
+
+import static org.apache.nifi.oauth2.Util.parseTokenResponse;
+
+public class OAuth2TokenProviderImpl extends AbstractControllerService implements OAuth2TokenProvider {
+    @Override
+    public List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return PROPERTIES;
+    }
+
+    private String resourceServerUrl;
+    private ObjectMapper mapper = new ObjectMapper();
+    private SSLContext sslContext;
+    private SSLContextService sslContextService;
+
+    @OnEnabled
+    public void onEnabled(ConfigurationContext context) {
+        resourceServerUrl = context.getProperty(ACCESS_TOKEN_URL).evaluateAttributeExpressions().getValue();
+
+        sslContextService = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextService.class);
+
+        sslContext = sslContextService == null ? null : sslContextService.createSSLContext(SSLContextService.ClientAuth.NONE);
+    }
+
+
+    @Override
+    public AccessToken getAccessTokenByPassword(String clientId, String clientSecret,
+                                                String username, String password) {
+        OkHttpClient.Builder builder = getClientBuilder();
+        OkHttpClient client = builder.build();
+
+        RequestBody body = new FormBody.Builder()
+                .add("username", username)
+                .add("password", password)
+                .add("client_id", clientId)
+                .add("client_secret", clientSecret)
+                .add("grant_type", "password")
+                .build();
+
+        Request newRequest = new Request.Builder()
+                .url(resourceServerUrl)
+                .post(body)
+                .build();
+
+        return executePost(client, newRequest);
+    }
+
+    private OkHttpClient.Builder getClientBuilder() {
+        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
+
+        if (sslContext != null) {
+            try {
+                Util.setSslSocketFactory(clientBuilder, sslContextService, sslContext, false);
+            } catch (Exception e) {
+                throw new ProcessException(e);
+            }
+        }
+
+        return clientBuilder;
+    }
+
+    private AccessToken executePost(OkHttpClient httpClient, Request newRequest) {
+        try {
+            Response response = httpClient.newCall(newRequest).execute();
+            String body = response.body().string();
+            if (response.code() >= 300) {
+                getLogger().error(String.format("Bad response from the server during oauth2 request:\n%s", body));
+                throw new ProcessException(String.format("Got HTTP %d during oauth2 request.", response.code()));
+            }
+
+            return parseTokenResponse(body);
+        } catch (IOException e) {
+            throw new ProcessException(e);
+        }
+    }
+
+    @Override
+    public AccessToken getAccessTokenByClientCredentials(String clientId, String clientSecret) {
+        OkHttpClient.Builder builder = getClientBuilder();
+//        builder.authenticator((route, response) -> {
+//            String credential = Credentials.basic(username, password); // Base64.getEncoder().encodeToString(String.format("%s:%s", username, password).getBytes());
+//
+//            return response.request().newBuilder().header("Authorization", credential).build();
+//        });

Review comment:
       Can this be removed?

##########
File path: nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/Util.java
##########
@@ -0,0 +1,122 @@
+package org.apache.nifi.oauth2;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.OkHttpClient;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.util.StringUtils;
+
+import javax.net.ssl.*;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.util.Map;
+
+public class Util {
+    private static final ObjectMapper MAPPER = new ObjectMapper();

Review comment:
       I don't see where this is being used?




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org