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 19bac11438 NIFI-14061 Added support for file scheme in OIDC Discovery 
URL
19bac11438 is described below

commit 19bac1143807ba7ce440feb3eff7bad89c4c9a23
Author: exceptionfactory <[email protected]>
AuthorDate: Sat Dec 14 11:20:34 2024 -0600

    NIFI-14061 Added support for file scheme in OIDC Discovery URL
    
    Signed-off-by: Pierre Villard <[email protected]>
    
    This closes #9580.
---
 .../src/main/asciidoc/administration-guide.adoc    |  3 +-
 .../StandardClientRegistrationProvider.java        | 29 ++++++--
 .../StandardClientRegistrationProviderTest.java    | 78 ++++++++++++++++------
 3 files changed, 85 insertions(+), 25 deletions(-)

diff --git a/nifi-docs/src/main/asciidoc/administration-guide.adoc 
b/nifi-docs/src/main/asciidoc/administration-guide.adoc
index c315e9f5ed..75a4030fcf 100644
--- a/nifi-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc
@@ -569,7 +569,8 @@ OpenID Connect integration supports the following settings 
in _nifi.properties_.
 [options="header"]
 
|==================================================================================================================================================
 | Property Name                                             | Description
-|`nifi.security.user.oidc.discovery.url`                    | The 
link:http://openid.net/specs/openid-connect-discovery-1_0.html[Discovery 
Configuration URL^] for the OpenID Connect Provider
+|`nifi.security.user.oidc.discovery.url`                    | The 
link:http://openid.net/specs/openid-connect-discovery-1_0.html[Discovery 
Configuration URL^]
+                                                              for the OpenID 
Connect Provider. Supports URLs with `https` or `file` schemes.
 |`nifi.security.user.oidc.connect.timeout`                  | Socket Connect 
timeout when communicating with the OpenID Connect Provider. The default value 
is `5 secs`
 |`nifi.security.user.oidc.read.timeout`                     | Socket Read 
timeout when communicating with the OpenID Connect Provider. The default value 
is `5 secs`
 |`nifi.security.user.oidc.client.id`                        | The Client ID 
for NiFi registered with the OpenID Connect Provider
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/registration/StandardClientRegistrationProvider.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/registration/StandardClientRegistrationProvider.java
index 40491d1085..c4731ab8e3 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/registration/StandardClientRegistrationProvider.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/registration/StandardClientRegistrationProvider.java
@@ -33,6 +33,10 @@ import 
org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
 import org.springframework.security.oauth2.core.oidc.OidcScopes;
 import org.springframework.web.client.RestClient;
 
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedHashMap;
@@ -51,6 +55,8 @@ public class StandardClientRegistrationProvider implements 
ClientRegistrationPro
 
     private static final Set<String> STANDARD_SCOPES = 
Collections.unmodifiableSet(new 
LinkedHashSet<>(Arrays.asList(OidcScopes.OPENID, OidcScopes.EMAIL)));
 
+    private static final String FILE_URI_SCHEME = "file";
+
     private final NiFiProperties properties;
 
     private final RestClient restClient;
@@ -107,13 +113,26 @@ public class StandardClientRegistrationProvider 
implements ClientRegistrationPro
 
     private OIDCProviderMetadata getProviderMetadata() {
         final String discoveryUrl = properties.getOidcDiscoveryUrl();
+        final URI discoveryUri = URI.create(discoveryUrl);
+        final String discoveryUriScheme = discoveryUri.getScheme();
 
         final String metadataObject;
-        try {
-            metadataObject = 
restClient.get().uri(discoveryUrl).retrieve().body(String.class);
-        } catch (final RuntimeException e) {
-            final String message = String.format("OpenID Connect Metadata URL 
[%s] retrieval failed", discoveryUrl);
-            throw new OidcConfigurationException(message, e);
+
+        if (FILE_URI_SCHEME.equals(discoveryUriScheme)) {
+            try {
+                final Path discoveryPath = Paths.get(discoveryUri);
+                metadataObject = Files.readString(discoveryPath);
+            } catch (final Exception e) {
+                final String message = String.format("OpenID Connect Metadata 
File URI [%s] read failed", discoveryUrl);
+                throw new OidcConfigurationException(message, e);
+            }
+        } else {
+            try {
+                metadataObject = 
restClient.get().uri(discoveryUrl).retrieve().body(String.class);
+            } catch (final RuntimeException e) {
+                final String message = String.format("OpenID Connect Metadata 
URL [%s] retrieval failed", discoveryUrl);
+                throw new OidcConfigurationException(message, e);
+            }
         }
 
         try {
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/registration/StandardClientRegistrationProviderTest.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/registration/StandardClientRegistrationProviderTest.java
index 896d3f8194..3e22dc432f 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/registration/StandardClientRegistrationProviderTest.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/registration/StandardClientRegistrationProviderTest.java
@@ -24,6 +24,7 @@ import org.apache.nifi.util.NiFiProperties;
 import org.apache.nifi.web.security.oidc.OidcConfigurationException;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import 
org.springframework.security.oauth2.client.registration.ClientRegistration;
@@ -31,7 +32,10 @@ import 
org.springframework.security.oauth2.core.AuthenticationMethod;
 import org.springframework.security.oauth2.core.oidc.OidcScopes;
 import org.springframework.web.client.RestClient;
 
+import java.io.IOException;
 import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedHashSet;
@@ -71,6 +75,10 @@ class StandardClientRegistrationProviderTest {
 
     private static final String INVALID_CONFIGURATION = "{}";
 
+    private static final String OPENID_CONFIGURATION_PREFIX = 
"openid-configuration";
+
+    private static final String OPENID_CONFIGURATION_EXTENSION = ".json";
+
     @Mock
     RestClient restClient;
 
@@ -82,7 +90,7 @@ class StandardClientRegistrationProviderTest {
 
     @Test
     void testGetClientRegistration() {
-        final NiFiProperties properties = getProperties();
+        final NiFiProperties properties = getProperties(DISCOVERY_URL);
         final StandardClientRegistrationProvider provider = new 
StandardClientRegistrationProvider(properties, restClient);
 
         final OIDCProviderMetadata providerMetadata = getProviderMetadata();
@@ -95,28 +103,40 @@ class StandardClientRegistrationProviderTest {
 
         final ClientRegistration clientRegistration = 
provider.getClientRegistration();
 
-        assertNotNull(clientRegistration);
-        assertEquals(CLIENT_ID, clientRegistration.getClientId());
-        assertEquals(CLIENT_SECRET, clientRegistration.getClientSecret());
+        assertClientRegistrationFound(clientRegistration);
+    }
 
-        final ClientRegistration.ProviderDetails providerDetails = 
clientRegistration.getProviderDetails();
-        assertEquals(ISSUER, providerDetails.getIssuerUri());
-        assertEquals(JWK_SET_URI.toString(), providerDetails.getJwkSetUri());
-        assertEquals(AUTHORIZATION_ENDPOINT_URI.toString(), 
providerDetails.getAuthorizationUri());
-        assertEquals(TOKEN_ENDPOINT_URI.toString(), 
providerDetails.getTokenUri());
+    @Test
+    void testGetClientRegistrationFileUri(@TempDir final Path tempDir) throws 
IOException {
+        final OIDCProviderMetadata providerMetadata = getProviderMetadata();
+        final String serializedMetadata = providerMetadata.toString();
 
-        final ClientRegistration.ProviderDetails.UserInfoEndpoint 
userInfoEndpoint = providerDetails.getUserInfoEndpoint();
-        assertEquals(USER_INFO_URI.toString(), userInfoEndpoint.getUri());
-        assertEquals(USER_NAME_ATTRIBUTE_NAME, 
userInfoEndpoint.getUserNameAttributeName());
-        assertEquals(AuthenticationMethod.HEADER, 
userInfoEndpoint.getAuthenticationMethod());
+        final Path configurationPath = Files.createTempFile(tempDir, 
OPENID_CONFIGURATION_PREFIX, OPENID_CONFIGURATION_EXTENSION);
+        Files.writeString(configurationPath, serializedMetadata);
+        final String discoveryUrl = configurationPath.toUri().toString();
 
-        final Set<String> scopes = clientRegistration.getScopes();
-        assertEquals(EXPECTED_SCOPES, scopes);
+        final NiFiProperties properties = getProperties(discoveryUrl);
+        final StandardClientRegistrationProvider provider = new 
StandardClientRegistrationProvider(properties, restClient);
+
+        final ClientRegistration clientRegistration = 
provider.getClientRegistration();
+
+        assertClientRegistrationFound(clientRegistration);
+    }
+
+    @Test
+    void testGetClientRegistrationFileUriFailed(@TempDir final Path tempDir) {
+        final Path configurationPath = 
tempDir.resolve(OPENID_CONFIGURATION_PREFIX);
+        final String discoveryUrl = configurationPath.toUri().toString();
+
+        final NiFiProperties properties = getProperties(discoveryUrl);
+        final StandardClientRegistrationProvider provider = new 
StandardClientRegistrationProvider(properties, restClient);
+
+        assertThrows(OidcConfigurationException.class, 
provider::getClientRegistration);
     }
 
     @Test
     void testGetClientRegistrationRetrievalFailed() {
-        final NiFiProperties properties = getProperties();
+        final NiFiProperties properties = getProperties(DISCOVERY_URL);
         final StandardClientRegistrationProvider provider = new 
StandardClientRegistrationProvider(properties, restClient);
 
         doReturn(requestHeadersUriSpec).when(restClient).get();
@@ -128,7 +148,7 @@ class StandardClientRegistrationProviderTest {
 
     @Test
     void testGetClientRegistrationParsingFailed() {
-        final NiFiProperties properties = getProperties();
+        final NiFiProperties properties = getProperties(DISCOVERY_URL);
         final StandardClientRegistrationProvider provider = new 
StandardClientRegistrationProvider(properties, restClient);
 
         doReturn(requestHeadersUriSpec).when(restClient).get();
@@ -139,9 +159,29 @@ class StandardClientRegistrationProviderTest {
         assertThrows(OidcConfigurationException.class, 
provider::getClientRegistration);
     }
 
-    private NiFiProperties getProperties() {
+    private void assertClientRegistrationFound(final ClientRegistration 
clientRegistration) {
+        assertNotNull(clientRegistration);
+        assertEquals(CLIENT_ID, clientRegistration.getClientId());
+        assertEquals(CLIENT_SECRET, clientRegistration.getClientSecret());
+
+        final ClientRegistration.ProviderDetails providerDetails = 
clientRegistration.getProviderDetails();
+        assertEquals(ISSUER, providerDetails.getIssuerUri());
+        assertEquals(JWK_SET_URI.toString(), providerDetails.getJwkSetUri());
+        assertEquals(AUTHORIZATION_ENDPOINT_URI.toString(), 
providerDetails.getAuthorizationUri());
+        assertEquals(TOKEN_ENDPOINT_URI.toString(), 
providerDetails.getTokenUri());
+
+        final ClientRegistration.ProviderDetails.UserInfoEndpoint 
userInfoEndpoint = providerDetails.getUserInfoEndpoint();
+        assertEquals(USER_INFO_URI.toString(), userInfoEndpoint.getUri());
+        assertEquals(USER_NAME_ATTRIBUTE_NAME, 
userInfoEndpoint.getUserNameAttributeName());
+        assertEquals(AuthenticationMethod.HEADER, 
userInfoEndpoint.getAuthenticationMethod());
+
+        final Set<String> scopes = clientRegistration.getScopes();
+        assertEquals(EXPECTED_SCOPES, scopes);
+    }
+
+    private NiFiProperties getProperties(final String discoveryUrl) {
         final Properties properties = new Properties();
-        properties.put(NiFiProperties.SECURITY_USER_OIDC_DISCOVERY_URL, 
DISCOVERY_URL);
+        properties.put(NiFiProperties.SECURITY_USER_OIDC_DISCOVERY_URL, 
discoveryUrl);
         properties.put(NiFiProperties.SECURITY_USER_OIDC_CLIENT_ID, CLIENT_ID);
         properties.put(NiFiProperties.SECURITY_USER_OIDC_CLIENT_SECRET, 
CLIENT_SECRET);
         
properties.put(NiFiProperties.SECURITY_USER_OIDC_CLAIM_IDENTIFYING_USER, 
USER_NAME_ATTRIBUTE_NAME);

Reply via email to