mirror of https://github.com/apache/nifi.git
NIFI-11267 Removed deprecated OAuth2TokenProviderImpl
Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com> This closes #7029.
This commit is contained in:
parent
665b1696ef
commit
b23b2621ac
|
@ -40,31 +40,20 @@
|
|||
<artifactId>nifi-utils</artifactId>
|
||||
<version>2.0.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>2.0.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
|
@ -76,10 +65,5 @@
|
|||
<version>2.0.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -1,186 +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.oauth2;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
||||
import org.apache.nifi.annotation.documentation.DeprecationNotice;
|
||||
import org.apache.nifi.annotation.documentation.Tags;
|
||||
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;
|
||||
|
||||
@Deprecated
|
||||
@DeprecationNotice(alternatives = {StandardOauth2AccessTokenProvider.class})
|
||||
@Tags({"oauth2", "provider", "authorization" })
|
||||
@CapabilityDescription("This controller service provides a way of working with access and refresh tokens via the " +
|
||||
"password and client_credential grant flows in the OAuth2 specification. It is meant to provide a way for components " +
|
||||
"to get a token from an oauth2 provider and pass that token as a part of a header to another service.")
|
||||
public class OAuth2TokenProviderImpl extends AbstractControllerService implements OAuth2TokenProvider {
|
||||
@Override
|
||||
public List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
||||
return PROPERTIES;
|
||||
}
|
||||
|
||||
private String resourceServerUrl;
|
||||
private SSLContext sslContext;
|
||||
private SSLContextService sslService;
|
||||
|
||||
@OnEnabled
|
||||
public void onEnabled(ConfigurationContext context) {
|
||||
resourceServerUrl = context.getProperty(ACCESS_TOKEN_URL).evaluateAttributeExpressions().getValue();
|
||||
|
||||
sslService = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextService.class);
|
||||
|
||||
sslContext = sslService == null ? null : sslService.createContext();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AccessToken getAccessTokenByPassword(String clientId, String clientSecret,
|
||||
String username, String password) throws AccessTokenAcquisitionException {
|
||||
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 (sslService != null) {
|
||||
final X509TrustManager trustManager = sslService.createTrustManager();
|
||||
clientBuilder.sslSocketFactory(sslContext.getSocketFactory(), trustManager);
|
||||
}
|
||||
|
||||
return clientBuilder;
|
||||
}
|
||||
|
||||
private AccessToken executePost(OkHttpClient httpClient, Request newRequest) throws AccessTokenAcquisitionException {
|
||||
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 AccessTokenAcquisitionException(String.format("Got HTTP %d during oauth2 request.", response.code()));
|
||||
}
|
||||
|
||||
return parseTokenResponse(body);
|
||||
} catch (IOException e) {
|
||||
throw new AccessTokenAcquisitionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessToken getAccessTokenByClientCredentials(String clientId, String clientSecret) throws AccessTokenAcquisitionException {
|
||||
OkHttpClient.Builder builder = getClientBuilder();
|
||||
OkHttpClient client = builder.build();
|
||||
|
||||
RequestBody body = new FormBody.Builder()
|
||||
.add("grant_type", "client_credentials")
|
||||
.add("client_id", clientId)
|
||||
.add("client_secret", clientSecret)
|
||||
.build();
|
||||
|
||||
Request newRequest = new Request.Builder()
|
||||
.url(resourceServerUrl)
|
||||
.post(body)
|
||||
.build();
|
||||
|
||||
return executePost(client, newRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessToken refreshToken(AccessToken refreshThis) throws AccessTokenAcquisitionException {
|
||||
if (StringUtils.isEmpty(refreshThis.getRefreshToken())) {
|
||||
throw new ProcessException("Missing refresh token. Refresh cannot happen.");
|
||||
}
|
||||
OkHttpClient.Builder builder = getClientBuilder();
|
||||
OkHttpClient client = builder.build();
|
||||
RequestBody body = new FormBody.Builder()
|
||||
.add("grant_type", "refresh_token")
|
||||
.add("refresh_token", refreshThis.getRefreshToken())
|
||||
.build();
|
||||
|
||||
Request newRequest = new Request.Builder()
|
||||
.url(resourceServerUrl)
|
||||
.post(body)
|
||||
.build();
|
||||
|
||||
return executePost(client, newRequest);
|
||||
}
|
||||
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
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 AccessToken parseTokenResponse(String rawResponse) {
|
||||
try {
|
||||
Map<String, Object> parsed = MAPPER.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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,6 +12,4 @@
|
|||
# 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
|
||||
org.apache.nifi.oauth2.StandardOauth2AccessTokenProvider
|
||||
|
||||
|
|
|
@ -1,125 +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.oauth2;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import org.apache.nifi.processor.AbstractProcessor;
|
||||
import org.apache.nifi.processor.ProcessContext;
|
||||
import org.apache.nifi.processor.ProcessSession;
|
||||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
import org.apache.nifi.util.TestRunners;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class OAuth2TokenProviderImplTest {
|
||||
private TestRunner runner;
|
||||
|
||||
private MockWebServer mockWebServer;
|
||||
|
||||
private OAuth2TokenProvider oAuth2TokenProvider;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws Exception {
|
||||
mockWebServer = new MockWebServer();
|
||||
final String url = mockWebServer.url("/").toString();
|
||||
|
||||
runner = TestRunners.newTestRunner(new AbstractProcessor() {
|
||||
@Override
|
||||
public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException {
|
||||
|
||||
}
|
||||
});
|
||||
oAuth2TokenProvider = new OAuth2TokenProviderImpl();
|
||||
runner.addControllerService("provider", oAuth2TokenProvider);
|
||||
runner.setProperty(oAuth2TokenProvider, OAuth2TokenProvider.ACCESS_TOKEN_URL, url);
|
||||
runner.enableControllerService(oAuth2TokenProvider);
|
||||
runner.assertValid();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientCredentialGrant() throws AccessTokenAcquisitionException, JsonProcessingException {
|
||||
enqueueTokenResponse();
|
||||
final AccessToken token = oAuth2TokenProvider.getAccessTokenByClientCredentials(
|
||||
"test-client",
|
||||
UUID.randomUUID().toString()
|
||||
);
|
||||
assertAccessTokenFound(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorHandler() {
|
||||
mockWebServer.enqueue(new MockResponse().setResponseCode(500));
|
||||
assertThrows(AccessTokenAcquisitionException.class, () -> oAuth2TokenProvider.getAccessTokenByClientCredentials(
|
||||
"test-client",
|
||||
UUID.randomUUID().toString()
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPasswordGrant() throws AccessTokenAcquisitionException, JsonProcessingException {
|
||||
enqueueTokenResponse();
|
||||
final AccessToken token = oAuth2TokenProvider.getAccessTokenByPassword(
|
||||
"test-client",
|
||||
UUID.randomUUID().toString(),
|
||||
"user",
|
||||
"password"
|
||||
);
|
||||
assertAccessTokenFound(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshToken() throws AccessTokenAcquisitionException, JsonProcessingException {
|
||||
enqueueTokenResponse();
|
||||
final AccessToken token = oAuth2TokenProvider.refreshToken(
|
||||
new AccessToken("token", "refresh", "BEARER", 300, "test")
|
||||
);
|
||||
assertAccessTokenFound(token);
|
||||
}
|
||||
|
||||
private void assertAccessTokenFound(final AccessToken accessToken) {
|
||||
assertNotNull(accessToken);
|
||||
assertEquals("access token", accessToken.getAccessToken());
|
||||
assertEquals(5300, accessToken.getExpiresIn());
|
||||
assertEquals("BEARER", accessToken.getTokenType());
|
||||
assertFalse(accessToken.isExpired());
|
||||
}
|
||||
|
||||
private void enqueueTokenResponse() throws JsonProcessingException {
|
||||
final Map<String, Object> token = new HashMap<>();
|
||||
token.put("access_token", "access token");
|
||||
token.put("refresh_token", "refresh token");
|
||||
token.put("token_type", "BEARER");
|
||||
token.put("expires_in", 5300);
|
||||
token.put("scope", "test scope");
|
||||
final String accessToken = new ObjectMapper().writeValueAsString(token);
|
||||
mockWebServer.enqueue(new MockResponse().setResponseCode(200).addHeader("Content-Type", "application/json").setBody(accessToken));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue