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 547f338147 NIFI-12695 Enabled PKCE Support for OIDC Integration
547f338147 is described below

commit 547f338147f4c48d9612ce4e7a6d52e0d8714f7f
Author: exceptionfactory <[email protected]>
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 <[email protected]>
    
    This closes #8324.
---
 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 66ac8ef0f2..97ef2e8728 100644
--- a/nifi-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc
@@ -518,6 +518,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 17bfee9878..39c397e20d 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 jakarta.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 a06ba3accc..6b36272318 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 jakarta.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() {

Reply via email to