Github user jdye64 commented on a diff in the pull request:
https://github.com/apache/nifi/pull/2085#discussion_r160197726
--- Diff:
nifi-nar-bundles/nifi-oauth-bundle/nifi-oauth/src/main/java/org/apache/nifi/oauth/AbstractOAuthControllerService.java
---
@@ -0,0 +1,172 @@
+/*
+ * 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.oauth;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.reporting.InitializationException;
+
+
+public abstract class AbstractOAuthControllerService
+ extends AbstractControllerService implements OAuth2ClientService {
+
+ protected String accessToken = null;
+ protected String refreshToken = null;
+ protected String tokenType = null;
+ protected long expiresIn = -1;
+ protected long expiresTime = -1;
+ protected long lastResponseTimestamp = -1;
+ protected Map<String, String> extraHeaders = new HashMap<String,
String>();
+ protected String authUrl = null;
+ protected long expireTimeSafetyNetSeconds = -1;
+ protected String accessTokenRespName = null;
+ protected String expireTimeRespName = null;
+ protected String expireInRespName = null;
+ protected String tokenTypeRespName = null;
+ protected String scopeRespName = null;
+
+ public static final PropertyDescriptor AUTH_SERVER_URL = new
PropertyDescriptor
+ .Builder().name("OAuth2 Authorization Server URL")
+ .displayName("OAuth2 Authorization Server")
+ .description("OAuth2 Authorization Server that grants access
to the protected resources on the behalf of the resource owner.")
+ .required(true)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .build();
+
+ public static final PropertyDescriptor
RESPONSE_ACCESS_TOKEN_FIELD_NAME = new PropertyDescriptor
+ .Builder().name("JSON response 'access_token' name")
+ .displayName("JSON response 'access_token' name")
+ .description("Name of the field in the JSON response that
contains the access token. IETF OAuth2 spec default is 'access_token' if your
API provider's" +
+ " response field is different this is where you can
change that.")
+ .defaultValue("access_token")
+ .required(true)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .build();
+
+ public static final PropertyDescriptor RESPONSE_EXPIRE_TIME_FIELD_NAME
= new PropertyDescriptor
+ .Builder().name("JSON response 'expire_time' name")
+ .displayName("JSON response 'expire_time' name")
+ .description("Name of the field in the JSON response that
contains the expire time. IETF OAuth2 spec default is 'expire_time' if your API
provider's" +
+ " response field is different this is where you can
change that.")
+ .defaultValue("expire_time")
+ .required(true)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .build();
+
+ public static final PropertyDescriptor RESPONSE_EXPIRE_IN_FIELD_NAME =
new PropertyDescriptor
+ .Builder().name("JSON response 'expire_in' name")
+ .displayName("JSON response 'expire_in' name")
+ .description("Name of the field in the JSON response that
contains the expire in. IETF OAuth2 spec default is 'expire_in' if your API
provider's" +
+ " response field is different this is where you can
change that.")
+ .defaultValue("expire_in")
+ .required(true)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .build();
+
+ public static final PropertyDescriptor RESPONSE_TOKEN_TYPE_FIELD_NAME
= new PropertyDescriptor
+ .Builder().name("JSON response 'token_type' name")
+ .displayName("JSON response 'token_type' name")
+ .description("Name of the field in the JSON response that
contains the token type. IETF OAuth2 spec default is 'token_type' if your API
provider's" +
+ " response field is different this is where you can
change that.")
+ .defaultValue("token_type")
+ .required(true)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .build();
+
+ public static final PropertyDescriptor RESPONSE_SCOPE_FIELD_NAME = new
PropertyDescriptor
+ .Builder().name("JSON response 'scope' name")
+ .displayName("JSON response 'scope' name")
+ .description("Name of the field in the JSON response that
contains the scope. IETF OAuth2 spec default is 'scope' if your API provider's"
+
+ " response field is different this is where you can
change that.")
+ .defaultValue("scope")
+ .required(true)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .build();
+
+ public static final PropertyDescriptor EXPIRE_TIME_SAFETY_NET = new
PropertyDescriptor
+ .Builder().name("Expire time safety net in seconds")
+ .displayName("Expire time safety net in seconds")
+ .description("There can be a chance that the authentication
server and the NiFi agent clocks could be out of sync. Expires In is an OAuth
standard " +
+ "that tells when the access token received will be
invalidated. Comparing the current system clock to that value and understanding
if the " +
+ "access token is still valid can be achieved this way.
However since the clocks can be out of sync with the authentication server " +
+ "this property ensures that the access token can be
refreshed at a configurable interval before it actual expires to ensure no
downtime " +
+ "waiting on new tokens from the authentication
server.")
+ .defaultValue("10")
+ .required(true)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .build();
+
+ protected void onEnabled(final ConfigurationContext context)
+ throws InitializationException {
+ Map<PropertyDescriptor, String> allProperties =
context.getProperties();
+ Iterator<PropertyDescriptor> itr =
allProperties.keySet().iterator();
+ while (itr.hasNext()) {
+ PropertyDescriptor pd = itr.next();
+ if (pd.isDynamic()) {
+ extraHeaders.put(pd.getName(), allProperties.get(pd));
+ }
+ }
+
+ this.authUrl = context.getProperty(AUTH_SERVER_URL).getValue();
+ this.expireTimeSafetyNetSeconds = new
Long(context.getProperty(EXPIRE_TIME_SAFETY_NET).getValue());
+
+ // Name of the OAuth2 spec fields that should be extracted from
the JSON authentication response. While in theory every provider should be
+ // using the same names in the response JSON that rarely happens.
These values are used to ensure that if the provider does NOT follow the
+ // spec the user can still use this integration approach instead
of having to write something custom.
+ this.accessTokenRespName =
context.getProperty(RESPONSE_ACCESS_TOKEN_FIELD_NAME).getValue();
+ this.expireTimeRespName =
context.getProperty(RESPONSE_EXPIRE_TIME_FIELD_NAME).getValue();
+ this.expireInRespName =
context.getProperty(RESPONSE_EXPIRE_IN_FIELD_NAME).getValue();
+ this.tokenTypeRespName =
context.getProperty(RESPONSE_TOKEN_TYPE_FIELD_NAME).getValue();
+ this.scopeRespName =
context.getProperty(RESPONSE_SCOPE_FIELD_NAME).getValue();
+ }
+
+ public boolean isOAuthTokenExpired() {
+ if (expiresTime == -1 && expiresIn == -1)
+ return true;
+
+ if (expiresTime > 0) {
+ // Use the actual time that the token will authenticate
+ if ((expiresTime - (expireTimeSafetyNetSeconds * 1000)) <=
System.currentTimeMillis()) {
--- End diff --
Andy. I think I could have chosen a better name for the
"expireTimeSafetyNetSeconds" variable. My intended behavior was for that
variable to be more of a method for causing the auth token to be refresh before
the token was actually expired. My thought process around this was if users
could control having their token refreshed before they were actually invalid it
would allow them a rough way to help prevent bottlenecking of processing when
the token was invalid and the processors using the controller service were
having to wait on the token to be refreshed. Does that make sense?
---