You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ex...@apache.org on 2024/02/01 14:42:06 UTC

(nifi) branch support/nifi-1.x updated: NIFI-12695 Enabled PKCE Support for OIDC Integration

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

exceptionfactory pushed a commit to branch support/nifi-1.x
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/support/nifi-1.x by this push:
     new cbfc47d460 NIFI-12695 Enabled PKCE Support for OIDC Integration
cbfc47d460 is described below

commit cbfc47d46021eb46c6d4c387096af8777bd0ea4a
Author: exceptionfactory <ex...@apache.org>
AuthorDate: Tue Jan 30 21:59:42 2024 -0600

    NIFI-12695 Enabled PKCE Support for OIDC Integration
    
    - Added Spring Security PKCE OAuth2 Request Customizer to standard Resolver
    
    Signed-off-by: Pierre Villard <pi...@gmail.com>
    
    This closes #8324.
    
    (cherry picked from commit 547f338147f4c48d9612ce4e7a6d52e0d8714f7f)
---
 nifi-docs/src/main/asciidoc/administration-guide.adoc      |  3 +++
 .../web/StandardOAuth2AuthorizationRequestResolver.java    |  9 +++++++--
 .../StandardOAuth2AuthorizationRequestResolverTest.java    | 14 ++++++++++++++
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/nifi-docs/src/main/asciidoc/administration-guide.adoc b/nifi-docs/src/main/asciidoc/administration-guide.adoc
index c50eea6c03..dc9819aab1 100644
--- a/nifi-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc
@@ -497,6 +497,9 @@ The implementation supports the Authorization Code Grant Type as described in
 link:https://www.rfc-editor.org/rfc/rfc6749#section-4.1[RFC 6749 Section 4.1^] and
 link:https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps[OpenID Connect Core Section 3.1.1^].
 
+The Authorization Code Grant Type implementation supports link:https://www.rfc-editor.org/rfc/rfc7636[RFC 7636] Proof
+Key for Code Exchange as part of the authentication process. PKCE support uses the `S256` code challenge method.
+
 After successful authentication with the Authorization Server, NiFi generates an application Bearer Token with an
 expiration based on the OAuth2 Access Token expiration. NiFi stores authorized tokens using the local State
 Provider and encrypts serialized information using the application Sensitive Properties Key.
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/client/web/StandardOAuth2AuthorizationRequestResolver.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/client/web/StandardOAuth2AuthorizationRequestResolver.java
index dd8ca86ee3..3cdd3cc74e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/client/web/StandardOAuth2AuthorizationRequestResolver.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/client/web/StandardOAuth2AuthorizationRequestResolver.java
@@ -19,7 +19,7 @@ package org.apache.nifi.web.security.oidc.client.web;
 import org.apache.nifi.web.util.RequestUriBuilder;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
 import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver;
-import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
+import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestCustomizers;
 import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
 import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
 import org.springframework.web.util.UriComponentsBuilder;
@@ -28,6 +28,8 @@ import javax.servlet.http.HttpServletRequest;
 import java.net.URI;
 import java.util.Objects;
 
+import static org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI;
+
 /**
  * Authorization Request Resolver supports handling of headers from reverse proxy servers
  */
@@ -41,7 +43,10 @@ public class StandardOAuth2AuthorizationRequestResolver implements OAuth2Authori
      */
     public StandardOAuth2AuthorizationRequestResolver(final ClientRegistrationRepository clientRegistrationRepository) {
         Objects.requireNonNull(clientRegistrationRepository, "Repository required");
-        resolver = new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
+        final DefaultOAuth2AuthorizationRequestResolver requestResolver = new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
+        // Enable RFC 7636 Proof Key for Code Exchange on Requests
+        requestResolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce());
+        resolver = requestResolver;
     }
 
     /**
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/client/web/StandardOAuth2AuthorizationRequestResolverTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/client/web/StandardOAuth2AuthorizationRequestResolverTest.java
index 5644c68f66..a862d099c9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/client/web/StandardOAuth2AuthorizationRequestResolverTest.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/client/web/StandardOAuth2AuthorizationRequestResolverTest.java
@@ -30,11 +30,15 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
 import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
 
 import javax.servlet.ServletContext;
+import org.springframework.security.oauth2.core.endpoint.PkceParameterNames;
+
 import java.net.URI;
+import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
 
@@ -99,6 +103,7 @@ class StandardOAuth2AuthorizationRequestResolverTest {
 
         assertNotNull(authorizationRequest);
         assertEquals(REDIRECT_URI, authorizationRequest.getRedirectUri());
+        assertPkceParametersFound(authorizationRequest);
     }
 
     @Test
@@ -119,6 +124,15 @@ class StandardOAuth2AuthorizationRequestResolverTest {
 
         assertNotNull(authorizationRequest);
         assertEquals(FORWARDED_REDIRECT_URI, authorizationRequest.getRedirectUri());
+        assertPkceParametersFound(authorizationRequest);
+    }
+
+    private void assertPkceParametersFound(final OAuth2AuthorizationRequest authorizationRequest) {
+        assertNotNull(authorizationRequest.getAttribute(PkceParameterNames.CODE_VERIFIER));
+
+        final Map<String, Object> additionalParameters = authorizationRequest.getAdditionalParameters();
+        assertTrue(additionalParameters.containsKey(PkceParameterNames.CODE_CHALLENGE));
+        assertTrue(additionalParameters.containsKey(PkceParameterNames.CODE_CHALLENGE_METHOD));
     }
 
     ClientRegistration getClientRegistration() {