You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2017/04/27 12:33:50 UTC

cxf git commit: Adding DynReg and access token cert binding test

Repository: cxf
Updated Branches:
  refs/heads/master 993439e90 -> 6070ddeef


Adding DynReg and access token cert binding test


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/6070ddee
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/6070ddee
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/6070ddee

Branch: refs/heads/master
Commit: 6070ddeef82e3b7366f1dc7d1252bc03af8766dd
Parents: 993439e
Author: Sergey Beryozkin <sb...@gmail.com>
Authored: Thu Apr 27 13:33:36 2017 +0100
Committer: Sergey Beryozkin <sb...@gmail.com>
Committed: Thu Apr 27 13:33:36 2017 +0100

----------------------------------------------------------------------
 .../cxf/jaxrs/json/basic/JsonMapObject.java     |  9 +++
 .../security/jose/jws/JwsCompactConsumer.java   |  1 +
 .../cxf/rs/security/oauth2/common/Client.java   | 11 ++-
 .../DefaultEHCacheOAuthDataProvider.java        | 42 +---------
 .../services/DynamicRegistrationService.java    | 39 ++++++++--
 .../rs/security/oauth2/utils/EHCacheUtil.java   | 42 ++++++++++
 .../security/oauth2/utils/OAuthConstants.java   | 11 ++-
 .../security/oauth2/tls/JAXRSOAuth2TlsTest.java | 81 +++++++++++++++++++-
 .../oidc/OIDCDynamicRegistrationTest.java       | 47 ++++++++++++
 .../jaxrs/security/oauth2/tls/serverTls.xml     |  9 +++
 10 files changed, 242 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/6070ddee/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObject.java
----------------------------------------------------------------------
diff --git a/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObject.java b/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObject.java
index 3161160..184b525 100644
--- a/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObject.java
+++ b/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObject.java
@@ -58,6 +58,15 @@ public class JsonMapObject implements Serializable {
     public Object getProperty(String name) {
         return values.get(name);
     }
+    
+    public Map<String, Object> getMapProperty(String name) {
+        Object value = getProperty(name);
+        if (value != null) {
+            return CastUtils.cast((Map<?, ?>)value);
+        } else {
+            return null;
+        }
+    }
 
     public Map<String, Object> asMap() {
         return values;

http://git-wip-us.apache.org/repos/asf/cxf/blob/6070ddee/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
index 6948d3e..5152363 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
@@ -76,6 +76,7 @@ public class JwsCompactConsumer {
     }
     public String getDecodedJwsPayload() {
         if (decodedJwsPayload == null) {
+            getJwsHeaders();
             if (JwsUtils.isPayloadUnencoded(jwsHeaders)) {
                 decodedJwsPayload = jwsPayload;
             } else {

http://git-wip-us.apache.org/repos/asf/cxf/blob/6070ddee/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
index 1d981ac..b337bc9 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
@@ -65,7 +65,8 @@ public class Client implements Serializable {
     private long registeredAt;
     private String homeRealm;
     private boolean registeredDynamically;
-
+    private String tokenEndpointAuthMethod;
+    
     public Client() {
 
     }
@@ -402,4 +403,12 @@ public class Client implements Serializable {
     public void setApplicationLogoutUri(String applicationLogoutUri) {
         this.applicationLogoutUri = applicationLogoutUri;
     }
+
+    public String getTokenEndpointAuthMethod() {
+        return tokenEndpointAuthMethod;
+    }
+
+    public void setTokenEndpointAuthMethod(String tokenEndpointAuthMethod) {
+        this.tokenEndpointAuthMethod = tokenEndpointAuthMethod;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/6070ddee/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEHCacheOAuthDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEHCacheOAuthDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEHCacheOAuthDataProvider.java
index e186935..f428a4c 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEHCacheOAuthDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEHCacheOAuthDataProvider.java
@@ -18,8 +18,6 @@
  */
 package org.apache.cxf.rs.security.oauth2.provider;
 
-import java.io.File;
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -28,14 +26,10 @@ import net.sf.ehcache.CacheManager;
 import net.sf.ehcache.Ehcache;
 import net.sf.ehcache.Element;
 import net.sf.ehcache.config.CacheConfiguration;
-import net.sf.ehcache.config.Configuration;
-import net.sf.ehcache.config.ConfigurationFactory;
-import net.sf.ehcache.config.DiskStoreConfiguration;
 
 import org.apache.cxf.Bus;
 import org.apache.cxf.BusFactory;
 import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.jaxrs.utils.ResourceUtils;
 import org.apache.cxf.rs.security.jose.jwt.JoseJwtConsumer;
 import org.apache.cxf.rs.security.oauth2.common.Client;
 import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
@@ -187,39 +181,7 @@ public class DefaultEHCacheOAuthDataProvider extends AbstractOAuthDataProvider {
         element.setTimeToIdle(parsedTTL);
         cache.put(element);
     }
-
-    private static CacheManager createCacheManager(String configFile, Bus bus) {
-        if (bus == null) {
-            bus = BusFactory.getThreadDefaultBus(true);
-        }
-
-        URL configFileURL = null;
-        try {
-            configFileURL =
-                ResourceUtils.getClasspathResourceURL(configFile, DefaultEHCacheOAuthDataProvider.class, bus);
-        } catch (Exception ex) {
-            // ignore
-        }
-        CacheManager cacheManager = null;
-        if (configFileURL == null) {
-            cacheManager = EHCacheUtil.createCacheManager();
-        } else {
-            Configuration conf = ConfigurationFactory.parseConfiguration(configFileURL);
-
-            if (bus != null) {
-                conf.setName(bus.getId());
-                DiskStoreConfiguration dsc = conf.getDiskStoreConfiguration();
-                if (dsc != null && "java.io.tmpdir".equals(dsc.getOriginalPath())) {
-                    String path = conf.getDiskStoreConfiguration().getPath() + File.separator
-                        + bus.getId();
-                    conf.getDiskStoreConfiguration().setPath(path);
-                }
-            }
-
-            cacheManager = EHCacheUtil.createCacheManager(conf);
-        }
-        return cacheManager;
-    }
+    
 
     protected static Ehcache createCache(CacheManager cacheManager, String cacheKey) {
         CacheConfiguration clientCC = EHCacheUtil.getCacheConfiguration(cacheKey, cacheManager);
@@ -228,7 +190,7 @@ public class DefaultEHCacheOAuthDataProvider extends AbstractOAuthDataProvider {
 
     private void createCaches(String configFile, Bus bus,
                               String clientCacheKey, String accessTokenKey, String refreshTokenKey) {
-        cacheManager = createCacheManager(configFile, bus);
+        cacheManager = EHCacheUtil.createCacheManager(configFile, bus);
 
         clientCache = createCache(cacheManager, clientCacheKey);
         accessTokenCache = createCache(cacheManager, accessTokenKey);

http://git-wip-us.apache.org/repos/asf/cxf/blob/6070ddee/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
index 7f914ec..bd1675c 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
@@ -181,7 +181,20 @@ public class DynamicRegistrationService {
         if (!c.getRegisteredAudiences().isEmpty()) {
             reg.setResourceUris(c.getRegisteredAudiences());
         }
-        //etc
+        if (c.getTokenEndpointAuthMethod() != null) {
+            reg.setTokenEndpointAuthMethod(c.getTokenEndpointAuthMethod());
+            if (OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS.equals(c.getTokenEndpointAuthMethod())) {
+                String subjectDn = c.getProperties().get(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN);
+                if (subjectDn != null) {
+                    reg.setProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN, subjectDn);
+                }
+                String issuerDn = c.getProperties().get(OAuthConstants.TLS_CLIENT_AUTH_ISSUER_DN);
+                if (issuerDn != null) {
+                    reg.setProperty(OAuthConstants.TLS_CLIENT_AUTH_ISSUER_DN, issuerDn);
+                }
+            }
+        }
+        
         return reg;
     }
 
@@ -220,9 +233,13 @@ public class DynamicRegistrationService {
             grantTypes = Collections.singletonList("authorization_code");
         }
         
-        boolean passwordRequired = grantTypes.contains(OAuthConstants.AUTHORIZATION_CODE_GRANT)
-               || grantTypes.contains(OAuthConstants.RESOURCE_OWNER_GRANT)
-               || grantTypes.contains(OAuthConstants.CLIENT_CREDENTIALS_GRANT);
+        String tokenEndpointAuthMethod = request.getTokenEndpointAuthMethod();
+        //TODO: default is expected to be set to OAuthConstants.TOKEN_ENDPOINT_AUTH_BASIC
+        
+        boolean passwordRequired = !grantTypes.contains(OAuthConstants.IMPLICIT_GRANT)
+            && (tokenEndpointAuthMethod == null
+                || OAuthConstants.TOKEN_ENDPOINT_AUTH_BASIC.equals(tokenEndpointAuthMethod)
+                || OAuthConstants.TOKEN_ENDPOINT_AUTH_POST.equals(tokenEndpointAuthMethod));
 
         // Application Type
         // https://tools.ietf.org/html/rfc7591 has no this property but
@@ -232,7 +249,8 @@ public class DynamicRegistrationService {
             appType = DEFAULT_APPLICATION_TYPE;
         }
         boolean isConfidential = DEFAULT_APPLICATION_TYPE.equals(appType)
-            && !grantTypes.contains(OAuthConstants.IMPLICIT_GRANT);
+            && (passwordRequired
+                || OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS.equals(tokenEndpointAuthMethod));
 
         // Client Secret
         String clientSecret = passwordRequired ? generateClientSecret(request) : null;
@@ -242,6 +260,17 @@ public class DynamicRegistrationService {
 
         newClient.setAllowedGrantTypes(grantTypes);
 
+        newClient.setTokenEndpointAuthMethod(tokenEndpointAuthMethod);
+        if (OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS.equals(tokenEndpointAuthMethod)) {
+            String subjectDn = (String)request.getProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN);
+            if (subjectDn != null) {
+                newClient.getProperties().put(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN, subjectDn);
+            }
+            String issuerDn = (String)request.getProperty(OAuthConstants.TLS_CLIENT_AUTH_ISSUER_DN);
+            if (issuerDn != null) {
+                newClient.getProperties().put(OAuthConstants.TLS_CLIENT_AUTH_ISSUER_DN, issuerDn);
+            }
+        }
         // Client Registration Time
         newClient.setRegisteredAt(System.currentTimeMillis() / 1000);
 

http://git-wip-us.apache.org/repos/asf/cxf/blob/6070ddee/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/EHCacheUtil.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/EHCacheUtil.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/EHCacheUtil.java
index e0be844..73de08c 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/EHCacheUtil.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/EHCacheUtil.java
@@ -19,12 +19,21 @@
 
 package org.apache.cxf.rs.security.oauth2.utils;
 
+import java.io.File;
 import java.lang.reflect.Method;
+import java.net.URL;
 
 import net.sf.ehcache.CacheException;
 import net.sf.ehcache.CacheManager;
 import net.sf.ehcache.config.CacheConfiguration;
 import net.sf.ehcache.config.Configuration;
+import net.sf.ehcache.config.ConfigurationFactory;
+import net.sf.ehcache.config.DiskStoreConfiguration;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
+import org.apache.cxf.rs.security.oauth2.provider.DefaultEHCacheOAuthDataProvider;
 
 /**
  */
@@ -85,4 +94,37 @@ public final class EHCacheUtil {
             throw new CacheException(e);
         }
     }
+    
+    public static CacheManager createCacheManager(String configFile, Bus bus) {
+        if (bus == null) {
+            bus = BusFactory.getThreadDefaultBus(true);
+        }
+
+        URL configFileURL = null;
+        try {
+            configFileURL =
+                ResourceUtils.getClasspathResourceURL(configFile, DefaultEHCacheOAuthDataProvider.class, bus);
+        } catch (Exception ex) {
+            // ignore
+        }
+        CacheManager cacheManager = null;
+        if (configFileURL == null) {
+            cacheManager = createCacheManager();
+        } else {
+            Configuration conf = ConfigurationFactory.parseConfiguration(configFileURL);
+
+            if (bus != null) {
+                conf.setName(bus.getId());
+                DiskStoreConfiguration dsc = conf.getDiskStoreConfiguration();
+                if (dsc != null && "java.io.tmpdir".equals(dsc.getOriginalPath())) {
+                    String path = conf.getDiskStoreConfiguration().getPath() + File.separator
+                        + bus.getId();
+                    conf.getDiskStoreConfiguration().setPath(path);
+                }
+            }
+
+            cacheManager = EHCacheUtil.createCacheManager(conf);
+        }
+        return cacheManager;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/6070ddee/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java
index 6b3fd35..7a8fe25 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java
@@ -130,6 +130,15 @@ public final class OAuthConstants {
     public static final String TOKEN_TYPE_HINT = "token_type_hint";
     public static final String UNSUPPORTED_TOKEN_TYPE = "unsupported_token_type";
 
+    // Token Service Authentication Methods
+    public static final String TOKEN_ENDPOINT_AUTH_NONE = "none";
+    public static final String TOKEN_ENDPOINT_AUTH_BASIC = "client_secret_basic";
+    public static final String TOKEN_ENDPOINT_AUTH_POST = "client_secret_post";
+    public static final String TOKEN_ENDPOINT_AUTH_TLS = "tls_client_auth";
+    // TLS Authentication Binding Properties
+    public static final String TLS_CLIENT_AUTH_SUBJECT_DN = "tls_client_auth_subject_dn";
+    public static final String TLS_CLIENT_AUTH_ISSUER_DN = "tls_client_auth_issuer_dn";
+    
     // Authorization scheme constants, used internally by AccessTokenValidation client and service
     public static final String AUTHORIZATION_SCHEME_TYPE = "authScheme";
     public static final String AUTHORIZATION_SCHEME_DATA = "authSchemeData";
@@ -143,8 +152,6 @@ public final class OAuthConstants {
     public static final String CLIENT_SECRET_CONTENT_ENCRYPTION_ALGORITHM =
         "client.secret.content.encryption.algorithm";
 
-    public static final String TLS_CLIENT_AUTH_SUBJECT_DN = "tls_client_auth_subject_dn";
-    public static final String TLS_CLIENT_AUTH_ISSUER_DN = "tls_client_auth_issuer_dn";
     private OAuthConstants() {
     }
 

http://git-wip-us.apache.org/repos/asf/cxf/blob/6070ddee/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/JAXRSOAuth2TlsTest.java
----------------------------------------------------------------------
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/JAXRSOAuth2TlsTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/JAXRSOAuth2TlsTest.java
index 2614dea..ca85869 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/JAXRSOAuth2TlsTest.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/JAXRSOAuth2TlsTest.java
@@ -20,20 +20,33 @@
 package org.apache.cxf.systest.jaxrs.security.oauth2.tls;
 
 import java.net.URL;
+import java.util.Collections;
+import java.util.Map;
 
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 
+import net.sf.ehcache.CacheManager;
+
 import org.apache.cxf.Bus;
 import org.apache.cxf.bus.spring.SpringBusFactory;
 import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.provider.json.JsonMapObjectProvider;
+import org.apache.cxf.rs.security.jose.common.JoseConstants;
+import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer;
+import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
+import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
+import org.apache.cxf.rs.security.jose.jwt.JwtUtils;
 import org.apache.cxf.rs.security.oauth2.client.Consumer;
 import org.apache.cxf.rs.security.oauth2.client.OAuthClientUtils;
 import org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant;
 import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
 import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+import org.apache.cxf.rs.security.oauth2.services.ClientRegistration;
+import org.apache.cxf.rs.security.oauth2.services.ClientRegistrationResponse;
+import org.apache.cxf.rs.security.oauth2.utils.EHCacheUtil;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
 import org.apache.cxf.systest.jaxrs.security.Book;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
@@ -46,6 +59,10 @@ public class JAXRSOAuth2TlsTest extends AbstractBusClientServerTestBase {
     
     @BeforeClass
     public static void startServers() throws Exception {
+        CacheManager manager = EHCacheUtil.createCacheManager("cxf-oauth2-ehcache.xml", null);
+        if (manager != null) {
+            manager.clearAll();
+        }
         assertTrue("server did not launch correctly",
                    launchServer(BookServerOAuth2Tls.class, true));
     }
@@ -91,17 +108,50 @@ public class JAXRSOAuth2TlsTest extends AbstractBusClientServerTestBase {
         ClientAccessToken at = OAuthClientUtils.getAccessToken(wc, new Consumer("bound"), 
                                                                new CustomGrant());
         assertNotNull(at.getTokenKey());
-        
     }
     
     @Test
     public void testTwoWayTLSClientIdBoundJwt() throws Exception {
+        doTestTwoWayTLSClientIdBoundJwt("boundJwt");
+    }
+    
+    @Test
+    public void testRegisterClientTwoWayTLSClientIdBoundDynReg() throws Exception {
+        String dynRegAddress = "https://localhost:" + PORT + "/oauth2Jwt/register";
+        WebClient wcDynReg = createDynRegWebClient(dynRegAddress);
+        
+        wcDynReg.accept("application/json").type("application/json");
+        ClientRegistration reg = newClientRegistration(); 
+        wcDynReg.authorization(new ClientAccessToken("Bearer", "123456789"));
+        ClientRegistrationResponse resp = wcDynReg.post(reg, ClientRegistrationResponse.class);
+                
+        doTestTwoWayTLSClientIdBoundJwt(resp.getClientId());
+
+        // delete the client
+        String regAccessToken = resp.getRegistrationAccessToken();
+        assertNotNull(regAccessToken);
+        wcDynReg.path(resp.getClientId());
+        
+
+        wcDynReg.authorization(new ClientAccessToken("Bearer", regAccessToken));
+
+        assertEquals(200, wcDynReg.delete().getStatus());
+        assertNotNull(regAccessToken);
+    }
+
+    private void doTestTwoWayTLSClientIdBoundJwt(String clientId) throws Exception {
         String atServiceAddress = "https://localhost:" + PORT + "/oauth2Jwt/token";
         WebClient wc = createOAuth2WebClient(atServiceAddress);
 
-        ClientAccessToken at = OAuthClientUtils.getAccessToken(wc, new Consumer("boundJwt"), 
+        ClientAccessToken at = OAuthClientUtils.getAccessToken(wc, new Consumer(clientId), 
                                                                new CustomGrant());
         assertNotNull(at.getTokenKey());
+        JwsJwtCompactConsumer c = new JwsJwtCompactConsumer(at.getTokenKey());
+        JwtClaims claims = JwtUtils.jsonToClaims(c.getDecodedJwsPayload());
+        
+        Map<String, Object> cnfs = claims.getMapProperty(JwtConstants.CLAIM_CONFIRMATION);
+        assertNotNull(cnfs);
+        assertNotNull(cnfs.get(JoseConstants.HEADER_X509_THUMBPRINT_SHA256));
         
         String protectedRsAddress = "https://localhost:" + PORT + "/rsJwt/bookstore/books/123";
         WebClient wcRs = createRsWebClient(protectedRsAddress, at, "client.xml");
@@ -127,6 +177,19 @@ public class JAXRSOAuth2TlsTest extends AbstractBusClientServerTestBase {
         assertEquals(401, wcRsDiffClientCert.get().getStatus());
     }
     
+    private ClientRegistration newClientRegistration() {
+        ClientRegistration reg = new ClientRegistration();
+        reg.setApplicationType("web");
+        reg.setScope("openid");
+        reg.setClientName("dynamic_client");
+        reg.setGrantTypes(Collections.singletonList("custom_grant"));
+        reg.setRedirectUris(Collections.singletonList("https://a/b/c"));
+        reg.setTokenEndpointAuthMethod(OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS);
+        reg.setProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN, 
+                        "CN=whateverhost.com,OU=Morpit,O=ApacheTest,L=Syracuse,C=US");
+        return reg;
+    }
+    
     @Test
     public void testTwoWayTLSClientUnbound() throws Exception {
         String address = "https://localhost:" + PORT + "/oauth2/token";
@@ -156,6 +219,20 @@ public class JAXRSOAuth2TlsTest extends AbstractBusClientServerTestBase {
         wc.type(MediaType.APPLICATION_FORM_URLENCODED).accept(MediaType.APPLICATION_JSON);
         return wc;
     }
+    private WebClient createDynRegWebClient(String address) {
+        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+        bean.setAddress(address);
+        bean.setProvider(new JsonMapObjectProvider());
+
+        SpringBusFactory bf = new SpringBusFactory();
+        URL busFile = JAXRSOAuth2TlsTest.class.getResource("client.xml");
+        Bus springBus = bf.createBus(busFile.toString());
+        bean.setBus(springBus);
+
+        WebClient wc = bean.createWebClient();
+        wc.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
+        return wc;
+    }
     private WebClient createRsWebClient(String address, ClientAccessToken at, String clientContext) {
         JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
         bean.setAddress(address);

http://git-wip-us.apache.org/repos/asf/cxf/blob/6070ddee/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCDynamicRegistrationTest.java
----------------------------------------------------------------------
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCDynamicRegistrationTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCDynamicRegistrationTest.java
index 22b97a2..018b2e4 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCDynamicRegistrationTest.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCDynamicRegistrationTest.java
@@ -29,6 +29,7 @@ import org.apache.cxf.jaxrs.provider.json.JsonMapObjectProvider;
 import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
 import org.apache.cxf.rs.security.oauth2.services.ClientRegistration;
 import org.apache.cxf.rs.security.oauth2.services.ClientRegistrationResponse;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
 
 import org.junit.BeforeClass;
@@ -90,6 +91,13 @@ public class OIDCDynamicRegistrationTest extends AbstractBusClientServerTestBase
 
         wc.authorization(new ClientAccessToken("Bearer", regAccessToken));
         ClientRegistration clientRegResp = wc.get(ClientRegistration.class);
+        testCommonRegProperties(clientRegResp);
+
+        assertNull(clientRegResp.getTokenEndpointAuthMethod());
+        
+        assertEquals(200, wc.delete().getStatus());
+    }
+    private void testCommonRegProperties(ClientRegistration clientRegResp) {
         assertNotNull(clientRegResp);
         assertEquals("web", clientRegResp.getApplicationType());
         assertEquals("dynamic_client", clientRegResp.getClientName());
@@ -100,7 +108,45 @@ public class OIDCDynamicRegistrationTest extends AbstractBusClientServerTestBase
                      clientRegResp.getRedirectUris());
         assertEquals(Collections.singletonList("https://rp/logout"),
                      clientRegResp.getListStringProperty("post_logout_redirect_uris"));
+    }
 
+    @org.junit.Test
+    public void testRegisterClientInitialAccessTokenCodeGrantTls() throws Exception {
+        URL busFile = OIDCDynamicRegistrationTest.class.getResource("client.xml");
+        String address = "https://localhost:" + PORT + "/services/dynamicWithAt/register";
+        WebClient wc = WebClient.create(address, Collections.singletonList(new JsonMapObjectProvider()),
+                         busFile.toString());
+
+        wc.accept("application/json").type("application/json");
+        ClientRegistration reg = newClientRegistration();
+        reg.setTokenEndpointAuthMethod(OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS);
+        reg.setProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN, 
+                        "CN=whateverhost.com,OU=Morpit,O=ApacheTest,L=Syracuse,C=US");
+        
+        ClientRegistrationResponse resp = null;
+        assertEquals(401, wc.post(reg).getStatus());
+        
+        wc.authorization(new ClientAccessToken("Bearer", "123456789"));
+        resp = wc.post(reg, ClientRegistrationResponse.class);
+        
+        assertNotNull(resp.getClientId());
+        assertNull(resp.getClientSecret());
+        assertEquals(address + "/" + resp.getClientId(),
+                     resp.getRegistrationClientUri());
+        String regAccessToken = resp.getRegistrationAccessToken();
+        assertNotNull(regAccessToken);
+
+        wc.reset();
+        wc.path(resp.getClientId());
+        assertEquals(401, wc.get().getStatus());
+
+        wc.authorization(new ClientAccessToken("Bearer", regAccessToken));
+        ClientRegistration clientRegResp = wc.get(ClientRegistration.class);
+        testCommonRegProperties(clientRegResp);
+        assertEquals(OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS, clientRegResp.getTokenEndpointAuthMethod());
+        assertEquals("CN=whateverhost.com,OU=Morpit,O=ApacheTest,L=Syracuse,C=US", 
+                     clientRegResp.getProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN));
+        
         assertEquals(200, wc.delete().getStatus());
     }
 
@@ -111,6 +157,7 @@ public class OIDCDynamicRegistrationTest extends AbstractBusClientServerTestBase
         reg.setClientName("dynamic_client");
         reg.setGrantTypes(Collections.singletonList("authorization_code"));
         reg.setRedirectUris(Collections.singletonList("https://a/b/c"));
+        
         reg.setProperty("post_logout_redirect_uris", 
                         Collections.singletonList("https://rp/logout"));
         return reg;

http://git-wip-us.apache.org/repos/asf/cxf/blob/6070ddee/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/tls/serverTls.xml
----------------------------------------------------------------------
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/tls/serverTls.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/tls/serverTls.xml
index 1d3d2e5..9485580 100644
--- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/tls/serverTls.xml
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/tls/serverTls.xml
@@ -104,6 +104,11 @@ under the License.
        <property name="blockUnauthorizedRequests" value="false"/>
     </bean>
     
+    <bean id="dynRegServiceWithAt" class="org.apache.cxf.rs.security.oauth2.services.DynamicRegistrationService">
+      <property name="clientProvider" ref="dataProviderJwt"/>
+      <property name="initialAccessToken" value="123456789"/>
+    </bean>
+    
     <jaxrs:server id="tokenServer1" address="https://localhost:${testutil.ports.jaxrs-oauth2-tls}/oauth2">
         <jaxrs:serviceBeans>
             <ref bean="accessTokenService1"/>
@@ -116,7 +121,11 @@ under the License.
         <jaxrs:serviceBeans>
             <ref bean="accessTokenServiceJwt"/>
             <ref bean="tokenIntrospectionServiceJwt"/>
+            <ref bean="dynRegServiceWithAt"/>
         </jaxrs:serviceBeans>
+        <jaxrs:providers>
+           <bean class="org.apache.cxf.jaxrs.provider.json.JsonMapObjectProvider"/>
+        </jaxrs:providers>
         <jaxrs:properties>
             <entry key="rs.security.signature.properties" value="org/apache/cxf/systest/jaxrs/security/alice.rs.properties"/>
             <entry key="rs.security.signature.key.password.provider" value-ref="keyPasswordProvider"/>