[cxf] branch 3.4.x-fixes updated: CXF-8369 - [oauth2] code_challenge_method not forwarded

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[cxf] branch 3.4.x-fixes updated: CXF-8369 - [oauth2] code_challenge_method not forwarded

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

coheigea pushed a commit to branch 3.4.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/3.4.x-fixes by this push:
     new 7fe3f8d  CXF-8369 - [oauth2] code_challenge_method not forwarded
7fe3f8d is described below

commit 7fe3f8dc32b47974bb79ec6cba3afcddefca0084
Author: Colm O hEigeartaigh <[hidden email]>
AuthorDate: Mon Nov 16 16:26:17 2020 +0000

    CXF-8369 - [oauth2] code_challenge_method not forwarded
   
    (cherry picked from commit 72882445f3c00faf3987c2025aec09679c0efb0b)
---
 .../oauth2/common/OAuthRedirectionState.java       |  8 +++++
 .../grants/code/AbstractCodeDataProvider.java      |  1 +
 .../grants/code/AuthorizationCodeGrantHandler.java | 36 ++++++++++++++++++----
 .../grants/code/AuthorizationCodeRegistration.java |  9 ++++++
 .../grants/code/ServerAuthorizationCodeGrant.java  |  9 ++++++
 .../oauth2/provider/JoseSessionTokenProvider.java  |  8 ++++-
 .../services/AuthorizationCodeGrantService.java    |  2 ++
 .../services/RedirectionBasedGrantService.java     |  1 +
 .../security/oauth2/common/OAuth2TestUtils.java    |  3 ++
 .../security/oauth2/grants/PublicClientTest.java   | 25 +++++++--------
 .../oauth2/grants/grants-server-public-session.xml | 36 ++++++++--------------
 .../oauth2/grants/grants-server-public.xml         | 25 +++++----------
 12 files changed, 102 insertions(+), 61 deletions(-)

diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthRedirectionState.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthRedirectionState.java
index e583949..f29b68b 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthRedirectionState.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthRedirectionState.java
@@ -33,6 +33,7 @@ public class OAuthRedirectionState implements Serializable {
     private String audience;
     private String nonce;
     private String clientCodeChallenge;
+    private String clientCodeChallengeMethod;
     private String responseType;
     private Map<String, String> extraProperties = new LinkedHashMap<>();
 
@@ -146,5 +147,12 @@ public class OAuthRedirectionState implements Serializable {
         this.extraProperties = extraProperties;
     }
 
+    public String getClientCodeChallengeMethod() {
+        return clientCodeChallengeMethod;
+    }
+
+    public void setClientCodeChallengeMethod(String clientCodeChallengeMethod) {
+        this.clientCodeChallengeMethod = clientCodeChallengeMethod;
+    }
 
 }
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AbstractCodeDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AbstractCodeDataProvider.java
index 8787a8b..0dd987b 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AbstractCodeDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AbstractCodeDataProvider.java
@@ -62,6 +62,7 @@ public abstract class AbstractCodeDataProvider extends AbstractOAuthDataProvider
         grant.setAudience(reg.getAudience());
         grant.setResponseType(reg.getResponseType());
         grant.setClientCodeChallenge(reg.getClientCodeChallenge());
+        grant.setClientCodeChallengeMethod(reg.getClientCodeChallengeMethod());
         grant.setNonce(reg.getNonce());
         grant.getExtraProperties().putAll(reg.getExtraProperties());
         return grant;
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java
index f32b0df..b7d787b 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.rs.security.oauth2.grants.code;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -39,7 +40,7 @@ import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
  */
 public class AuthorizationCodeGrantHandler extends AbstractGrantHandler {
 
-    private CodeVerifierTransformer codeVerifierTransformer;
+    private List<CodeVerifierTransformer> codeVerifierTransformers = Collections.emptyList();
     private boolean expectCodeVerifierForPublicClients;
 
     public AuthorizationCodeGrantHandler() {
@@ -79,7 +80,9 @@ public class AuthorizationCodeGrantHandler extends AbstractGrantHandler {
 
         String clientCodeVerifier = params.getFirst(OAuthConstants.AUTHORIZATION_CODE_VERIFIER);
         String clientCodeChallenge = grant.getClientCodeChallenge();
-        if (!compareCodeVerifierWithChallenge(client, clientCodeVerifier, clientCodeChallenge)) {
+        String clientCodeChallengeMethod = grant.getClientCodeChallengeMethod();
+        if (!compareCodeVerifierWithChallenge(client, clientCodeVerifier,
+                clientCodeChallenge, clientCodeChallengeMethod)) {
             throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
         }
         List<String> audiences = getAudiences(client, params, grant.getAudience());
@@ -149,7 +152,7 @@ public class AuthorizationCodeGrantHandler extends AbstractGrantHandler {
     }
 
     private boolean compareCodeVerifierWithChallenge(Client c, String clientCodeVerifier,
-                                                     String clientCodeChallenge) {
+                                                     String clientCodeChallenge, String clientCodeChallengeMethod) {
         if (clientCodeChallenge == null && clientCodeVerifier == null
             && (c.isConfidential() || !expectCodeVerifierForPublicClients)) {
             return true;
@@ -157,14 +160,35 @@ public class AuthorizationCodeGrantHandler extends AbstractGrantHandler {
             || clientCodeChallenge == null && clientCodeVerifier != null) {
             return false;
         } else {
-            String transformedCodeVerifier = codeVerifierTransformer == null
-                ? clientCodeVerifier : codeVerifierTransformer.transformCodeVerifier(clientCodeVerifier);
+            CodeVerifierTransformer codeVerifierTransformer = null;
+            if (!codeVerifierTransformers.isEmpty() && clientCodeChallengeMethod != null) {
+                codeVerifierTransformer = codeVerifierTransformers.stream()
+                        .filter(t -> clientCodeChallengeMethod.equals(t.getChallengeMethod()))
+                        .findAny()
+                        .orElse(null);
+                // If we have configured codeVerifierTransformers then we must have a match
+                if (codeVerifierTransformer == null) {
+                    return false;
+                }
+            }
+            // Fall back to plain
+            if (codeVerifierTransformer == null) {
+                codeVerifierTransformer = new PlainCodeVerifier();
+            }
+            String transformedCodeVerifier = codeVerifierTransformer.transformCodeVerifier(clientCodeVerifier);
             return clientCodeChallenge.equals(transformedCodeVerifier);
         }
     }
 
     public void setCodeVerifierTransformer(CodeVerifierTransformer codeVerifier) {
-        this.codeVerifierTransformer = codeVerifier;
+        setCodeVerifierTransformers(codeVerifier == null ? null : Collections.singletonList(codeVerifier));
+    }
+
+    public void setCodeVerifierTransformers(List<CodeVerifierTransformer> codeVerifierTransformers) {
+        if (codeVerifierTransformers == null) {
+            this.codeVerifierTransformers = Collections.emptyList();
+        }
+        this.codeVerifierTransformers = new ArrayList<>(codeVerifierTransformers);
     }
 
     public void setExpectCodeVerifierForPublicClients(boolean expectCodeVerifierForPublicClients) {
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java
index 4886c76..af673c7 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java
@@ -40,6 +40,7 @@ public class AuthorizationCodeRegistration {
     private String nonce;
     private String responseType;
     private String clientCodeChallenge;
+    private String clientCodeChallengeMethod;
     private boolean preauthorizedTokenAvailable;
     private Map<String, String> extraProperties = new LinkedHashMap<>();
     /**
@@ -155,4 +156,12 @@ public class AuthorizationCodeRegistration {
     public void setResponseType(String responseType) {
         this.responseType = responseType;
     }
+
+    public String getClientCodeChallengeMethod() {
+        return clientCodeChallengeMethod;
+    }
+
+    public void setClientCodeChallengeMethod(String clientCodeChallengeMethod) {
+        this.clientCodeChallengeMethod = clientCodeChallengeMethod;
+    }
 }
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java
index e936b69..021c26e 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java
@@ -51,6 +51,7 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant {
     private String audience;
     private String responseType;
     private String clientCodeChallenge;
+    private String clientCodeChallengeMethod;
     private String nonce;
     private boolean preauthorizedTokenAvailable;
     private Map<String, String> extraProperties = new LinkedHashMap<>();
@@ -208,4 +209,12 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant {
     public void setResponseType(String responseType) {
         this.responseType = responseType;
     }
+
+    public String getClientCodeChallengeMethod() {
+        return clientCodeChallengeMethod;
+    }
+
+    public void setClientCodeChallengeMethod(String clientCodeChallengeMethod) {
+        this.clientCodeChallengeMethod = clientCodeChallengeMethod;
+    }
 }
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JoseSessionTokenProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JoseSessionTokenProvider.java
index f30f5d5..5dd538f 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JoseSessionTokenProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JoseSessionTokenProvider.java
@@ -174,6 +174,9 @@ public class JoseSessionTokenProvider implements SessionAuthenticityTokenProvide
         if (!StringUtils.isEmpty(parts[8])) {
             state.setExtraProperties(ModelEncryptionSupport.parseSimpleMap(parts[8]));
         }
+        if (!StringUtils.isEmpty(parts[9])) {
+            state.setClientCodeChallengeMethod(parts[9]);
+        }
         return state;
     }
     protected String convertStateToString(OAuthRedirectionState secData) {
@@ -185,7 +188,7 @@ public class JoseSessionTokenProvider implements SessionAuthenticityTokenProvide
         // 1: client audience
         state.append(ModelEncryptionSupport.tokenizeString(secData.getAudience()));
         state.append(ModelEncryptionSupport.SEP);
-        // 2: client code verifier
+        // 2: client code challenge
         state.append(ModelEncryptionSupport.tokenizeString(secData.getClientCodeChallenge()));
         state.append(ModelEncryptionSupport.SEP);
         // 3: state
@@ -205,6 +208,9 @@ public class JoseSessionTokenProvider implements SessionAuthenticityTokenProvide
         state.append(ModelEncryptionSupport.SEP);
         // 8: extra props
         state.append(secData.getExtraProperties().toString());
+        state.append(ModelEncryptionSupport.SEP);
+        // 9: client code challenge method
+        state.append(ModelEncryptionSupport.tokenizeString(secData.getClientCodeChallengeMethod()));
 
         return state.toString();
     }
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
index d63e85ed..16d26b5 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
@@ -63,6 +63,7 @@ public class AuthorizationCodeGrantService extends RedirectionBasedGrantService
     protected OAuthRedirectionState recreateRedirectionStateFromParams(MultivaluedMap<String, String> params) {
         OAuthRedirectionState state = super.recreateRedirectionStateFromParams(params);
         state.setClientCodeChallenge(params.getFirst(OAuthConstants.AUTHORIZATION_CODE_CHALLENGE));
+        state.setClientCodeChallengeMethod(params.getFirst(OAuthConstants.AUTHORIZATION_CODE_CHALLENGE_METHOD));
         return state;
     }
 
@@ -147,6 +148,7 @@ public class AuthorizationCodeGrantService extends RedirectionBasedGrantService
         codeReg.setAudience(state.getAudience());
         codeReg.setNonce(state.getNonce());
         codeReg.setClientCodeChallenge(state.getClientCodeChallenge());
+        codeReg.setClientCodeChallengeMethod(state.getClientCodeChallengeMethod());
         codeReg.getExtraProperties().putAll(state.getExtraProperties());
         return codeReg;
     }
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
index 63f65a7..372d2f2 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
@@ -293,6 +293,7 @@ public abstract class RedirectionBasedGrantService extends AbstractOAuthService
             secData.setProposedScope(builder.toString().trim());
         }
         secData.setClientCodeChallenge(params.getFirst(OAuthConstants.AUTHORIZATION_CODE_CHALLENGE));
+        secData.setClientCodeChallengeMethod(params.getFirst(OAuthConstants.AUTHORIZATION_CODE_CHALLENGE_METHOD));
         if (!authorizationCanBeSkipped) {
             secData.setPermissions(requestedPerms);
             secData.setAlreadyAuthorizedPermissions(alreadyAuthorizedPerms);
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuth2TestUtils.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuth2TestUtils.java
index ce488b2..d040d85 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuth2TestUtils.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuth2TestUtils.java
@@ -152,6 +152,9 @@ public final class OAuth2TestUtils {
         if (authzData.getClientCodeChallenge() != null) {
             form.param("code_challenge", authzData.getClientCodeChallenge());
         }
+        if (authzData.getClientCodeChallengeMethod() != null) {
+            form.param("code_challenge_method", authzData.getClientCodeChallengeMethod());
+        }
         form.param("response_type", authzData.getResponseType());
         form.param("oauthDecision", "allow");
 
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/PublicClientTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/PublicClientTest.java
index dab76fc..e687ccc 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/PublicClientTest.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/PublicClientTest.java
@@ -61,15 +61,12 @@ public class PublicClientTest extends AbstractClientServerTestBase {
 
     final String port;
 
-    private final String tokenServiceAddressPlain;
-    private final String tokenServiceAddressDigest;
+    private final String tokenServiceAddress;
 
     public PublicClientTest(String port) {
         this.port = port;
         // services2 doesn't require basic auth
-        tokenServiceAddressPlain = "https://localhost:" + port + "/services2/";
-        // services3 doesn't require basic auth
-        tokenServiceAddressDigest = "https://localhost:" + port + "/services3/";
+        tokenServiceAddress = "https://localhost:" + port + "/services2/";
     }
 
     @BeforeClass
@@ -133,35 +130,35 @@ public class PublicClientTest extends AbstractClientServerTestBase {
 
     @org.junit.Test
     public void testPKCEPlain() throws Exception {
-        testPKCE(new PlainCodeVerifier(), tokenServiceAddressPlain);
+        testPKCE(new PlainCodeVerifier());
     }
 
     @org.junit.Test
     public void testPKCEPlainMissingVerifier() throws Exception {
-        testPKCEMissingVerifier(new PlainCodeVerifier(), tokenServiceAddressPlain);
+        testPKCEMissingVerifier(new PlainCodeVerifier());
     }
 
     @org.junit.Test
     public void testPKCEPlainDifferentVerifier() throws Exception {
-        testPKCEDifferentVerifier(new PlainCodeVerifier(), tokenServiceAddressPlain);
+        testPKCEDifferentVerifier(new PlainCodeVerifier());
     }
 
     @org.junit.Test
     public void testPKCEDigest() {
-        testPKCE(new DigestCodeVerifier(), tokenServiceAddressDigest);
+        testPKCE(new DigestCodeVerifier());
     }
 
     @org.junit.Test
     public void testPKCEDigestMissingVerifier() {
-        testPKCEMissingVerifier(new DigestCodeVerifier(), tokenServiceAddressDigest);
+        testPKCEMissingVerifier(new DigestCodeVerifier());
     }
 
     @org.junit.Test
     public void testPKCEDigestDifferentVerifier() {
-        testPKCEDifferentVerifier(new DigestCodeVerifier(), tokenServiceAddressDigest);
+        testPKCEDifferentVerifier(new DigestCodeVerifier());
     }
 
-    private void testPKCE(CodeVerifierTransformer transformer, String tokenServiceAddress) {
+    private void testPKCE(CodeVerifierTransformer transformer) {
         URL busFile = PublicClientTest.class.getResource("publicclient.xml");
 
         String address = "https://localhost:" + port + "/services/";
@@ -191,7 +188,7 @@ public class PublicClientTest extends AbstractClientServerTestBase {
         assertNotNull(accessToken.getTokenKey());
     }
 
-    private void testPKCEMissingVerifier(CodeVerifierTransformer transformer, String tokenServiceAddress) {
+    private void testPKCEMissingVerifier(CodeVerifierTransformer transformer) {
         URL busFile = PublicClientTest.class.getResource("publicclient.xml");
 
         String address = "https://localhost:" + port + "/services/";
@@ -224,7 +221,7 @@ public class PublicClientTest extends AbstractClientServerTestBase {
         }
     }
 
-    private void testPKCEDifferentVerifier(CodeVerifierTransformer transformer, String tokenServiceAddress) {
+    private void testPKCEDifferentVerifier(CodeVerifierTransformer transformer) {
         URL busFile = PublicClientTest.class.getResource("publicclient.xml");
 
         String address = "https://localhost:" + port + "/services/";
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/grants-server-public-session.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/grants-server-public-session.xml
index 0b9cd88..0b6471a 100644
--- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/grants-server-public-session.xml
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/grants-server-public-session.xml
@@ -132,28 +132,18 @@ under the License.
            <entry key="rs.security.decryption.key.password.provider" value-ref="keyPasswordProvider"/>
        </jaxrs:properties>
    </jaxrs:server>
-  
-   <jaxrs:server
-       depends-on="tls-config"
-       address="<a href="https://localhost:$">https://localhost:${testutil.ports.jaxrs-oauth2-grants-jcache-public-session}/services2">
-       <jaxrs:serviceBeans>
-           <ref bean="tokenService"/>
-       </jaxrs:serviceBeans>
-       <jaxrs:properties>
-           <entry key="rs.security.signature.out.properties" value="org/apache/cxf/systest/jaxrs/security/alice.rs.properties"/>
-           <entry key="rs.security.encryption.in.properties" value="org/apache/cxf/systest/jaxrs/security/bob.rs.properties"/>
-           <entry key="rs.security.encryption.out.properties" value="org/apache/cxf/systest/jaxrs/security/bob.rs.properties"/>
-           <entry key="rs.security.signature.in.properties" value="org/apache/cxf/systest/jaxrs/security/alice.rs.properties"/>
-           <entry key="rs.security.signature.key.password.provider" value-ref="keyPasswordProvider"/>
-           <entry key="rs.security.decryption.key.password.provider" value-ref="keyPasswordProvider"/>
-       </jaxrs:properties>
-   </jaxrs:server>
-  
-   <bean id="digestVerifier" class="org.apache.cxf.rs.security.oauth2.grants.code.DigestCodeVerifier" />
-   <bean id="codeGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeGrantHandler">
-      <property name="dataProvider" ref="oauthProvider"/>
-      <property name="codeVerifierTransformer" ref="digestVerifier"/>
-   </bean>
+
+    <bean id="digestVerifier" class="org.apache.cxf.rs.security.oauth2.grants.code.DigestCodeVerifier" />
+    <bean id="plainVerifier" class="org.apache.cxf.rs.security.oauth2.grants.code.PlainCodeVerifier" />
+    <bean id="codeGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeGrantHandler">
+        <property name="dataProvider" ref="oauthProvider"/>
+        <property name="codeVerifierTransformers">
+            <list>
+                <ref bean="digestVerifier"/>
+                <ref bean="plainVerifier"/>
+            </list>
+        </property>
+    </bean>
   
    <bean id="digestTokenService" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenService">
       <property name="dataProvider" ref="oauthProvider"/>
@@ -167,7 +157,7 @@ under the License.
   
    <jaxrs:server
        depends-on="tls-config"
-       address="<a href="https://localhost:$">https://localhost:${testutil.ports.jaxrs-oauth2-grants-jcache-public-session}/services3">
+       address="<a href="https://localhost:$">https://localhost:${testutil.ports.jaxrs-oauth2-grants-jcache-public-session}/services2">
        <jaxrs:serviceBeans>
            <ref bean="digestTokenService"/>
        </jaxrs:serviceBeans>
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/grants-server-public.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/grants-server-public.xml
index 91c8f8f..188bca5 100644
--- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/grants-server-public.xml
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/grants-server-public.xml
@@ -126,25 +126,16 @@ under the License.
        </jaxrs:properties>
    </jaxrs:server>
   
-   <jaxrs:server
-       depends-on="tls-config"
-       address="<a href="https://localhost:$">https://localhost:${testutil.ports.jaxrs-oauth2-grants-jcache-public}/services2">
-       <jaxrs:serviceBeans>
-           <ref bean="tokenService"/>
-       </jaxrs:serviceBeans>
-       <jaxrs:properties>
-           <entry key="rs.security.keystore.type" value="jks" />
-           <entry key="rs.security.keystore.alias" value="alice"/>
-           <entry key="rs.security.keystore.password" value="password"/>
-           <entry key="rs.security.keystore.file" value="keys/alice.jks" />
-           <entry key="rs.security.signature.algorithm" value="RS256" />
-       </jaxrs:properties>
-   </jaxrs:server>
-  
    <bean id="digestVerifier" class="org.apache.cxf.rs.security.oauth2.grants.code.DigestCodeVerifier" />
+   <bean id="plainVerifier" class="org.apache.cxf.rs.security.oauth2.grants.code.PlainCodeVerifier" />
    <bean id="codeGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeGrantHandler">
       <property name="dataProvider" ref="oauthProvider"/>
-      <property name="codeVerifierTransformer" ref="digestVerifier"/>
+      <property name="codeVerifierTransformers">
+          <list>
+              <ref bean="digestVerifier"/>
+              <ref bean="plainVerifier"/>
+          </list>
+      </property>
    </bean>
   
    <bean id="digestTokenService" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenService">
@@ -159,7 +150,7 @@ under the License.
   
    <jaxrs:server
        depends-on="tls-config"
-       address="<a href="https://localhost:$">https://localhost:${testutil.ports.jaxrs-oauth2-grants-jcache-public}/services3">
+       address="<a href="https://localhost:$">https://localhost:${testutil.ports.jaxrs-oauth2-grants-jcache-public}/services2">
        <jaxrs:serviceBeans>
            <ref bean="digestTokenService"/>
        </jaxrs:serviceBeans>