Repository: gravitee-io/graviteeio-access-management
Pull request #605 (2019-06-16 02:18:00)

Implement default & allowed scopes on DCR
This is the last part of issue [#2326](https://github.com/gravitee-io/issues/issues/2326)
Give the possibility to limit scopes on the Dynamic Client Registration endpoint.
Give the possibility to apply some defaut scopes _(when no scopes are requested)_


Patch:
diff --git a/docker/management-ui/run.sh b/docker/management-ui/run.sh
index 4a1e1df9a7..a64f9c071b 100644
--- a/docker/management-ui/run.sh
+++ b/docker/management-ui/run.sh
@@ -1,7 +1,22 @@
 #!/bin/sh
+#
+# Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
 
 # generate configs
 /bin/confd -onetime -backend env
 
 # start nginx foreground
-exec /usr/sbin/nginx -g 'daemon off;'
\ No newline at end of file
+exec /usr/sbin/nginx -g 'daemon off;'
diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationRequest.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationRequest.java
index b92879d54d..e466465c0b 100644
--- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationRequest.java
+++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationRequest.java
@@ -25,6 +25,7 @@ import io.gravitee.am.model.oidc.JWKSet;
 import io.gravitee.am.service.utils.SetterUtils;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
@@ -397,7 +398,10 @@ public class DynamicClientRegistrationRequest {
 
     public Optional<List<String>> getScope() {
         if (this.scope == null) return null; //Keep null to avoid patch...
-        return Optional.of(Arrays.asList(scope.orElse("").split(SCOPE_DELIMITER)));
+        if (!this.scope.isPresent() || this.scope.get().trim().isEmpty()) {
+            return Optional.empty();
+        }
+        return Optional.of(Arrays.asList(scope.get().split(SCOPE_DELIMITER)));
     }
 
     public void setScope(Optional<String> scope) {
@@ -436,9 +440,9 @@ public class DynamicClientRegistrationRequest {
     public Client patch(Client client) {
         /* set openid request metadata */
         SetterUtils.safeSet(client::setRedirectUris, this.getRedirectUris());
-        SetterUtils.safeSetOrElse(client::setResponseTypes, this.getResponseTypes(), Client.DEFAULT_RESPONSE_TYPES);
-        SetterUtils.safeSetOrElse(client::setAuthorizedGrantTypes, this.getGrantTypes(), Client.DEFAULT_GRANT_TYPES);
-        SetterUtils.safeSetOrElse(client::setApplicationType, this.getApplicationType(), ApplicationType.WEB);
+        SetterUtils.safeSet(client::setResponseTypes, this.getResponseTypes());
+        SetterUtils.safeSet(client::setAuthorizedGrantTypes, this.getGrantTypes());
+        SetterUtils.safeSet(client::setApplicationType, this.getApplicationType());
         SetterUtils.safeSet(client::setContacts, this.getContacts());
         SetterUtils.safeSet(client::setClientName, this.getClientName());
         SetterUtils.safeSet(client::setLogoUri, this.getLogoUri());
diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/impl/DynamicClientRegistrationServiceImpl.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/impl/DynamicClientRegistrationServiceImpl.java
index 4e3b49a6ec..197fe6d630 100644
--- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/impl/DynamicClientRegistrationServiceImpl.java
+++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/impl/DynamicClientRegistrationServiceImpl.java
@@ -18,13 +18,13 @@ package io.gravitee.am.gateway.handler.oidc.service.clientregistration.impl;
 import io.gravitee.am.common.jwt.JWT;
 import io.gravitee.am.common.oidc.Scope;
 import io.gravitee.am.common.utils.SecureRandomString;
+import io.gravitee.am.gateway.handler.common.jwa.utils.JWAlgorithmUtils;
 import io.gravitee.am.gateway.handler.common.jwk.JWKService;
 import io.gravitee.am.gateway.handler.common.jwt.JWTService;
+import io.gravitee.am.gateway.handler.oidc.service.clientregistration.DynamicClientRegistrationRequest;
 import io.gravitee.am.gateway.handler.oidc.service.clientregistration.DynamicClientRegistrationService;
 import io.gravitee.am.gateway.handler.oidc.service.discovery.OpenIDDiscoveryService;
 import io.gravitee.am.gateway.handler.oidc.service.discovery.OpenIDProviderMetadata;
-import io.gravitee.am.gateway.handler.oidc.service.clientregistration.DynamicClientRegistrationRequest;
-import io.gravitee.am.gateway.handler.common.jwa.utils.JWAlgorithmUtils;
 import io.gravitee.am.gateway.handler.oidc.service.utils.SubjectTypeUtils;
 import io.gravitee.am.model.Client;
 import io.gravitee.am.model.Domain;
@@ -48,7 +48,15 @@ import org.springframework.beans.factory.annotation.Autowired;
 
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+import static io.gravitee.am.common.oidc.Scope.SCOPE_DELIMITER;
 
 /**
  * @author Alexandre FARIA (contact at alexandrefaria.net)
@@ -169,6 +177,7 @@ public class DynamicClientRegistrationServiceImpl implements DynamicClientRegist
         }
 
         return this.validateRedirectUri(request, isPatch)
+                .flatMap(this::validateScopes)
                 .flatMap(this::validateGrantType)
                 .flatMap(this::validateResponseType)
                 .flatMap(this::validateSubjectType)
@@ -201,10 +210,7 @@ public class DynamicClientRegistrationServiceImpl implements DynamicClientRegist
     private Single<DynamicClientRegistrationRequest> validateResponseType(DynamicClientRegistrationRequest request) {
         //if response_type provided, they must be valid.
         if(request.getResponseTypes()!=null) {
-            if(!request.getResponseTypes().isPresent()) {
-                request.setResponseTypes(Optional.of(Arrays.asList()));
-            }
-            if(!ResponseTypeUtils.isSupportedResponseType(request.getResponseTypes().get())) {
+            if(!ResponseTypeUtils.isSupportedResponseType(request.getResponseTypes().orElse(Collections.emptyList()))) {
                 return Single.error(new InvalidClientMetadataException("Invalid response type."));
             }
         }
@@ -214,7 +220,7 @@ public class DynamicClientRegistrationServiceImpl implements DynamicClientRegist
     private Single<DynamicClientRegistrationRequest> validateGrantType(DynamicClientRegistrationRequest request) {
         //if grant_type provided, they must be valid.
         if(request.getGrantTypes()!=null) {
-            if (!GrantTypeUtils.isSupportedGrantType(request.getGrantTypes().get())) {
+            if (!GrantTypeUtils.isSupportedGrantType(request.getGrantTypes().orElse(Collections.emptyList()))) {
                 return Single.error(new InvalidClientMetadataException("Missing or invalid grant type."));
             }
         }
@@ -223,7 +229,7 @@ public class DynamicClientRegistrationServiceImpl implements DynamicClientRegist
 
     private Single<DynamicClientRegistrationRequest> validateSubjectType(DynamicClientRegistrationRequest request) {
         //if subject_type is provided, it must be valid.
-        if(request.getSubjectType()!=null) {
+        if(request.getSubjectType()!=null && request.getSubjectType().isPresent()) {
             if(!SubjectTypeUtils.isValidSubjectType(request.getSubjectType().get())) {
                 return Single.error(new InvalidClientMetadataException("Unsupported subject type"));
             }
@@ -233,7 +239,7 @@ public class DynamicClientRegistrationServiceImpl implements DynamicClientRegist
 
     private Single<DynamicClientRegistrationRequest> validateUserinfoSigningAlgorithm(DynamicClientRegistrationRequest request) {
         //if userinfo_signed_response_alg is provided, it must be valid.
-        if(request.getUserinfoSignedResponseAlg()!=null) {
+        if(request.getUserinfoSignedResponseAlg()!=null && request.getUserinfoSignedResponseAlg().isPresent()) {
             if(!JWAlgorithmUtils.isValidUserinfoSigningAlg(request.getUserinfoSignedResponseAlg().get())) {
                 return Single.error(new InvalidClientMetadataException("Unsupported userinfo signing algorithm"));
             }
@@ -246,11 +252,11 @@ public class DynamicClientRegistrationServiceImpl implements DynamicClientRegist
             return Single.error(new InvalidClientMetadataException("When userinfo_encrypted_response_enc is included, userinfo_encrypted_response_alg MUST also be provided"));
         }
         //if userinfo_encrypted_response_alg is provided, it must be valid.
-        if(request.getUserinfoEncryptedResponseAlg()!=null) {
+        if(request.getUserinfoEncryptedResponseAlg()!=null && request.getUserinfoEncryptedResponseAlg().isPresent()) {
             if(!JWAlgorithmUtils.isValidUserinfoResponseAlg(request.getUserinfoEncryptedResponseAlg().get())) {
                 return Single.error(new InvalidClientMetadataException("Unsupported userinfo_encrypted_response_alg value"));
             }
-            if(request.getUserinfoEncryptedResponseEnc()!=null) {
+            if(request.getUserinfoEncryptedResponseEnc()!=null && request.getUserinfoEncryptedResponseEnc().isPresent()) {
                 if(!JWAlgorithmUtils.isValidUserinfoResponseEnc(request.getUserinfoEncryptedResponseEnc().get())) {
                     return Single.error(new InvalidClientMetadataException("Unsupported userinfo_encrypted_response_enc value"));
                 }
@@ -265,7 +271,7 @@ public class DynamicClientRegistrationServiceImpl implements DynamicClientRegist
 
     private Single<DynamicClientRegistrationRequest> validateIdTokenSigningAlgorithm(DynamicClientRegistrationRequest request) {
         //if userinfo_signed_response_alg is provided, it must be valid.
-        if(request.getIdTokenSignedResponseAlg()!=null) {
+        if(request.getIdTokenSignedResponseAlg()!=null && request.getIdTokenSignedResponseAlg().isPresent()) {
             if(!JWAlgorithmUtils.isValidIdTokenSigningAlg(request.getIdTokenSignedResponseAlg().get())) {
                 return Single.error(new InvalidClientMetadataException("Unsupported id_token signing algorithm"));
             }
@@ -278,11 +284,11 @@ public class DynamicClientRegistrationServiceImpl implements DynamicClientRegist
             return Single.error(new InvalidClientMetadataException("When id_token_encrypted_response_enc is included, id_token_encrypted_response_alg MUST also be provided"));
         }
         //if id_token_encrypted_response_alg is provided, it must be valid.
-        if(request.getIdTokenEncryptedResponseAlg()!=null) {
+        if(request.getIdTokenEncryptedResponseAlg()!=null && request.getIdTokenEncryptedResponseAlg().isPresent()) {
             if(!JWAlgorithmUtils.isValidIdTokenResponseAlg(request.getIdTokenEncryptedResponseAlg().get())) {
                 return Single.error(new InvalidClientMetadataException("Unsupported id_token_encrypted_response_alg value"));
             }
-            if(request.getIdTokenEncryptedResponseEnc()!=null) {
+            if(request.getIdTokenEncryptedResponseEnc()!=null && request.getIdTokenEncryptedResponseEnc().isPresent()) {
                 if(!JWAlgorithmUtils.isValidIdTokenResponseEnc(request.getIdTokenEncryptedResponseEnc().get())) {
                     return Single.error(new InvalidClientMetadataException("Unsupported id_token_encrypted_response_enc value"));
                 }
@@ -360,7 +366,7 @@ public class DynamicClientRegistrationServiceImpl implements DynamicClientRegist
         //Check jwks_uri
         if(request.getJwksUri()!=null && request.getJwksUri().isPresent()) {
             return jwkService.getKeys(request.getJwksUri().get())
-                    .switchIfEmpty(Maybe.error(new InvalidClientMetadataException("No JWK found behing jws uri...")))
+                    .switchIfEmpty(Maybe.error(new InvalidClientMetadataException("No JWK found behind jws uri...")))
                     .flatMapSingle(jwkSet -> {
                         /* Uncomment if we expect to save it as fallback
                         if(jwkSet!=null && jwkSet.isPresent()) {
@@ -374,6 +380,44 @@ public class DynamicClientRegistrationServiceImpl implements DynamicClientRegist
         return Single.just(request);
     }
 
+    /**
+     * Remove non allowed scopes (if feature is enabled) and then apply default scopes.
+     * The scopes validations are done later (validateMetadata) on the process.
+     * @param request DynamicClientRegistrationRequest
+     * @return DynamicClientRegistrationRequest
+     */
+    private Single<DynamicClientRegistrationRequest> validateScopes(DynamicClientRegistrationRequest request) {
+
+        final boolean hasAllowedScopes = domain.getOidc()!=null && domain.getOidc().getClientRegistrationSettings()!=null &&
+                domain.getOidc().getClientRegistrationSettings().isAllowedScopesEnabled() &&
+                domain.getOidc().getClientRegistrationSettings().getAllowedScopes()!=null;
+
+        final boolean hasDefaultScopes = domain.getOidc()!=null && domain.getOidc().getClientRegistrationSettings()!=null &&
+                domain.getOidc().getClientRegistrationSettings().getDefaultScopes()!=null &&
+                !domain.getOidc().getClientRegistrationSettings().getDefaultScopes().isEmpty();
+
+        //Remove from the request every non allowed scope
+        if(request.getScope()!=null && request.getScope().isPresent() && hasAllowedScopes) {
+
+            final Set<String> allowedScopes = new HashSet<>(domain.getOidc().getClientRegistrationSettings().getAllowedScopes());
+            final Set<String> requestedScopes = new HashSet<>(request.getScope().get());
+
+            //Remove non allowed scope
+            requestedScopes.retainAll(allowedScopes);
+
+            //Update the request
+            request.setScope(Optional.of(String.join(SCOPE_DELIMITER,requestedScopes)));
+        }
+
+        //Apply default scope if scope metadata is empty
+        if((request.getScope()==null || !request.getScope().isPresent() || request.getScope().get().isEmpty()) && hasDefaultScopes) {
+            //Add default scopes if needed
+            request.setScope(Optional.of(String.join(SCOPE_DELIMITER,domain.getOidc().getClientRegistrationSettings().getDefaultScopes())));
+        }
+
+        return Single.just(request);
+    }
+
     /**
      * Check Uri is well formatted
      * @param uri String
diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/discovery/OpenIDProviderMetadata.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/discovery/OpenIDProviderMetadata.java
index d681662966..9036df4d3c 100644
--- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/discovery/OpenIDProviderMetadata.java
+++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/discovery/OpenIDProviderMetadata.java
@@ -57,6 +57,9 @@ public class OpenIDProviderMetadata {
     @JsonProperty("registration_endpoint")
     private String registrationEndpoint;
 
+    @JsonProperty("registration_renew_secret_endpoint")
+    private String registrationRenewSecretEndpoint;
+
     @JsonProperty("scopes_supported")
     private List<String> scopesSupported;
 
@@ -219,6 +222,14 @@ public class OpenIDProviderMetadata {
         this.registrationEndpoint = registrationEndpoint;
     }
 
+    public String getRegistrationRenewSecretEndpoint() {
+        return registrationRenewSecretEndpoint;
+    }
+
+    public void setRegistrationRenewSecretEndpoint(String registrationRenewSecretEndpoint) {
+        this.registrationRenewSecretEndpoint = registrationRenewSecretEndpoint;
+    }
+
     public List<String> getScopesSupported() {
         return scopesSupported;
     }
diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/discovery/impl/OpenIDDiscoveryServiceImpl.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/discovery/impl/OpenIDDiscoveryServiceImpl.java
index 26e7fa5ad1..61ea1aa537 100644
--- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/discovery/impl/OpenIDDiscoveryServiceImpl.java
+++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/main/java/io/gravitee/am/gateway/handler/oidc/service/discovery/impl/OpenIDDiscoveryServiceImpl.java
@@ -73,6 +73,7 @@ public class OpenIDDiscoveryServiceImpl implements OpenIDDiscoveryService {
         openIDProviderMetadata.setIntrospectionEndpoint(getEndpointAbsoluteURL(basePath, INTROSPECTION_ENDPOINT));
         openIDProviderMetadata.setEndSessionEndpoint(getEndpointAbsoluteURL(basePath, ENDSESSION_ENDPOINT));
         openIDProviderMetadata.setRegistrationEndpoint(getEndpointAbsoluteURL(basePath, REGISTRATION_ENDPOINT));
+        openIDProviderMetadata.setRegistrationRenewSecretEndpoint(openIDProviderMetadata.getRegistrationEndpoint()+"/:client_id/renew_secret");
 
         // supported parameters
         openIDProviderMetadata.setScopesSupported(scopeService.getDiscoveryScope());
diff --git a/gravitee-am-model/src/main/java/io/gravitee/am/model/oidc/ClientRegistrationSettings.java b/gravitee-am-model/src/main/java/io/gravitee/am/model/oidc/ClientRegistrationSettings.java
index 43cbb626df..0ddb3b50d6 100644
--- a/gravitee-am-model/src/main/java/io/gravitee/am/model/oidc/ClientRegistrationSettings.java
+++ b/gravitee-am-model/src/main/java/io/gravitee/am/model/oidc/ClientRegistrationSettings.java
@@ -15,6 +15,8 @@
  */
 package io.gravitee.am.model.oidc;
 
+import java.util.List;
+
 /**
  * @author Alexandre FARIA (contact at alexandrefaria.net)
  * @author GraviteeSource Team
@@ -46,6 +48,21 @@ public class ClientRegistrationSettings {
      */
     private boolean isOpenDynamicClientRegistrationEnabled;
 
+    /**
+     * Define some default scopes to add on each client registration request
+     */
+    private List<String> defaultScopes;
+
+    /**
+     * Filter scopes on Client Registration through an allowed list of scopes enabled.
+     */
+    private boolean isAllowedScopesEnabled;
+
+    /**
+     * Define allowed scopes for each client registration request
+     */
+    private List<String> allowedScopes;
+
 
     public boolean isAllowLocalhostRedirectUri() {
         return allowLocalhostRedirectUri;
@@ -91,4 +108,28 @@ public class ClientRegistrationSettings {
         //By default all boolean are set to false.
         return new ClientRegistrationSettings();
     }
+
+    public List<String> getDefaultScopes() {
+        return defaultScopes;
+    }
+
+    public void setDefaultScopes(List<String> defaultScopes) {
+        this.defaultScopes = defaultScopes;
+    }
+
+    public boolean isAllowedScopesEnabled() {
+        return isAllowedScopesEnabled;
+    }
+
+    public void setAllowedScopesEnabled(boolean allowedScopesEnabled) {
+        isAllowedScopesEnabled = allowedScopesEnabled;
+    }
+
+    public List<String> getAllowedScopes() {
+        return allowedScopes;
+    }
+
+    public void setAllowedScopes(List<String> allowedScopes) {
+        this.allowedScopes = allowedScopes;
+    }
 }
diff --git a/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/MongoDomainRepository.java b/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/MongoDomainRepository.java
index 229f8adf18..a21cc6e4ea 100644
--- a/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/MongoDomainRepository.java
+++ b/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/MongoDomainRepository.java
@@ -226,6 +226,9 @@ public class MongoDomainRepository extends AbstractManagementMongoRepository imp
         result.setAllowWildCardRedirectUri(dcrMongo.isAllowWildCardRedirectUri());
         result.setDynamicClientRegistrationEnabled(dcrMongo.isDynamicClientRegistrationEnabled());
         result.setOpenDynamicClientRegistrationEnabled(dcrMongo.isOpenDynamicClientRegistrationEnabled());
+        result.setDefaultScopes(dcrMongo.getDefaultScopes());
+        result.setAllowedScopesEnabled(dcrMongo.isAllowedScopesEnabled());
+        result.setAllowedScopes(dcrMongo.getAllowedScopes());
 
         return result;
     }
@@ -252,6 +255,9 @@ public class MongoDomainRepository extends AbstractManagementMongoRepository imp
         result.setAllowWildCardRedirectUri(dcr.isAllowWildCardRedirectUri());
         result.setDynamicClientRegistrationEnabled(dcr.isDynamicClientRegistrationEnabled());
         result.setOpenDynamicClientRegistrationEnabled(dcr.isOpenDynamicClientRegistrationEnabled());
+        result.setDefaultScopes(dcr.getDefaultScopes());
+        result.setAllowedScopesEnabled(dcr.isAllowedScopesEnabled());
+        result.setAllowedScopes(dcr.getAllowedScopes());
 
         return result;
     }
diff --git a/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/IdentityProviderMongo.java b/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/IdentityProviderMongo.java
index 5d961e7b58..48ec22d117 100644
--- a/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/IdentityProviderMongo.java
+++ b/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/IdentityProviderMongo.java
@@ -19,8 +19,6 @@ import io.gravitee.am.repository.mongodb.common.model.Auditable;
 import org.bson.Document;
 import org.bson.codecs.pojo.annotations.BsonId;
 
-import java.util.Map;
-
 /**
  * @author David BRASSELY (david.brassely at graviteesource.com)
  * @author GraviteeSource Team
diff --git a/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/ScopeMongo.java b/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/ScopeMongo.java
index 1d9879731a..ddf63cccde 100644
--- a/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/ScopeMongo.java
+++ b/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/ScopeMongo.java
@@ -19,7 +19,6 @@ import io.gravitee.am.repository.mongodb.common.model.Auditable;
 import org.bson.codecs.pojo.annotations.BsonId;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author David BRASSELY (david.brassely at graviteesource.com)
diff --git a/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/oidc/ClientRegistrationSettingsMongo.java b/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/oidc/ClientRegistrationSettingsMongo.java
index 45c864694d..5bd4ea7c2c 100644
--- a/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/oidc/ClientRegistrationSettingsMongo.java
+++ b/gravitee-am-repository/gravitee-am-repository-mongodb/src/main/java/io/gravitee/am/repository/mongodb/management/internal/model/oidc/ClientRegistrationSettingsMongo.java
@@ -15,6 +15,8 @@
  */
 package io.gravitee.am.repository.mongodb.management.internal.model.oidc;
 
+import java.util.List;
+
 /**
  * @author Alexandre FARIA (contact at alexandrefaria.net)
  * @author GraviteeSource Team
@@ -26,6 +28,10 @@ public class ClientRegistrationSettingsMongo {
     private boolean allowWildCardRedirectUri;
     private boolean isDynamicClientRegistrationEnabled;
     private boolean isOpenDynamicClientRegistrationEnabled;
+    private List<String> defaultScopes;
+    private boolean isAllowedScopesEnabled;
+    private List<String> allowedScopes;
+
 
     public boolean isAllowLocalhostRedirectUri() {
         return allowLocalhostRedirectUri;
@@ -66,4 +72,28 @@ public class ClientRegistrationSettingsMongo {
     public void setAllowWildCardRedirectUri(boolean allowWildCardRedirectUri) {
         this.allowWildCardRedirectUri = allowWildCardRedirectUri;
     }
+
+    public List<String> getDefaultScopes() {
+        return defaultScopes;
+    }
+
+    public void setDefaultScopes(List<String> defaultScopes) {
+        this.defaultScopes = defaultScopes;
+    }
+
+    public boolean isAllowedScopesEnabled() {
+        return isAllowedScopesEnabled;
+    }
+
+    public void setAllowedScopesEnabled(boolean allowedScopesEnabled) {
+        isAllowedScopesEnabled = allowedScopesEnabled;
+    }
+
+    public List<String> getAllowedScopes() {
+        return allowedScopes;
+    }
+
+    public void setAllowedScopes(List<String> allowedScopes) {
+        this.allowedScopes = allowedScopes;
+    }
 }
diff --git a/gravitee-am-service/src/main/java/io/gravitee/am/service/model/openid/PatchClientRegistrationSettings.java b/gravitee-am-service/src/main/java/io/gravitee/am/service/model/openid/PatchClientRegistrationSettings.java
index 0bfb30dffc..3fb05eeb11 100644
--- a/gravitee-am-service/src/main/java/io/gravitee/am/service/model/openid/PatchClientRegistrationSettings.java
+++ b/gravitee-am-service/src/main/java/io/gravitee/am/service/model/openid/PatchClientRegistrationSettings.java
@@ -18,6 +18,8 @@ package io.gravitee.am.service.model.openid;
 import io.gravitee.am.model.oidc.ClientRegistrationSettings;
 import io.gravitee.am.service.utils.SetterUtils;
 
+import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 
 /**
@@ -53,6 +55,20 @@ public class PatchClientRegistrationSettings {
      */
     private Optional<Boolean> isOpenDynamicClientRegistrationEnabled;
 
+    /**
+     * Define some default scope to add on each client registration request
+     */
+    private Optional<List<String>> defaultScopes;
+
+    /**
+     * Filter scopes on Client Registration through an allowed list of scopes enabled.
+     */
+    private Optional<Boolean> isAllowedScopesEnabled;
+
+    /**
+     * Define allowed scopes for each client registration request
+     */
+    private Optional<List<String>> allowedScopes;
 
     public Optional<Boolean> getAllowLocalhostRedirectUri() {
         return allowLocalhostRedirectUri;
@@ -94,6 +110,29 @@ public class PatchClientRegistrationSettings {
         this.isOpenDynamicClientRegistrationEnabled = isOpenDynamicClientRegistrationEnabled;
     }
 
+    public Optional<List<String>> getDefaultScopes() {
+        return defaultScopes;
+    }
+
+    public void setDefaultScopes(Optional<List<String>> defaultScopes) {
+        this.defaultScopes = defaultScopes;
+    }
+
+    public Optional<Boolean> isAllowedScopesEnabled() {
+        return isAllowedScopesEnabled;
+    }
+
+    public void setIsAllowedScopesEnabled(Optional<Boolean> isAllowedScopesEnabled) {
+        this.isAllowedScopesEnabled = isAllowedScopesEnabled;
+    }
+
+    public Optional<List<String>> getAllowedScopes() {
+        return allowedScopes;
+    }
+
+    public void setAllowedScopes(Optional<List<String>> allowedScopes) {
+        this.allowedScopes = allowedScopes;
+    }
 
     public ClientRegistrationSettings patch(ClientRegistrationSettings toPatch) {
         ClientRegistrationSettings result=toPatch!=null?toPatch: ClientRegistrationSettings.defaultSettings();
@@ -102,7 +141,10 @@ public class PatchClientRegistrationSettings {
         SetterUtils.safeSet(result::setAllowHttpSchemeRedirectUri, this.getAllowHttpSchemeRedirectUri(), boolean.class);
         SetterUtils.safeSet(result::setAllowLocalhostRedirectUri, this.getAllowLocalhostRedirectUri(), boolean.class);
         SetterUtils.safeSet(result::setOpenDynamicClientRegistrationEnabled, this.isOpenDynamicClientRegistrationEnabled(), boolean.class);
-        SetterUtils.safeSet(result::setDynamicClientRegistrationEnabled,this.isDynamicClientRegistrationEnabled(), boolean.class);
+        SetterUtils.safeSet(result::setDynamicClientRegistrationEnabled, this.isDynamicClientRegistrationEnabled(), boolean.class);
+        SetterUtils.safeSet(result::setDefaultScopes, this.getDefaultScopes());
+        SetterUtils.safeSet(result::setAllowedScopesEnabled, this.isAllowedScopesEnabled, boolean.class);
+        SetterUtils.safeSet(result::setAllowedScopes, this.getAllowedScopes());
 
         return result;
     }
diff --git a/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/SetterUtils.java b/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/SetterUtils.java
index 1192671b0d..f8b9cd2e67 100644
--- a/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/SetterUtils.java
+++ b/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/SetterUtils.java
@@ -70,20 +70,6 @@ public class SetterUtils {
         }
     }
 
-    /**
-     * Safe setter, apply setter only if Optional is not null.
-     * Apply default value if Optional is empty.
-     * @param setter Consumer setter method.
-     * @param value Optional value.
-     * @param defaultValue Default value to apply if Optional is empty.
-     * @param <T> value class
-     */
-    public static <T> void safeSetOrElse(final Consumer<T> setter, final Optional<T> value, final T defaultValue) {
-        if (value != null) {
-            setter.accept(value.orElse(defaultValue));
-        }
-    }
-
     private static Object getDefaultValue(Class primitive) {
 
         if (primitive.equals(boolean.class)) {
diff --git a/gravitee-am-ui/src/app/app-routing.module.ts b/gravitee-am-ui/src/app/app-routing.module.ts
index 06deac1404..0d27e570ff 100644
--- a/gravitee-am-ui/src/app/app-routing.module.ts
+++ b/gravitee-am-ui/src/app/app-routing.module.ts
@@ -23,6 +23,9 @@ import {DomainDashboardComponent} from "./domain/dashboard/dashboard.component";
 import {DomainSettingsComponent} from "./domain/settings/settings.component";
 import {DomainSettingsGeneralComponent} from "./domain/settings/general/general.component";
 import {DomainSettingsOpenidClientRegistrationComponent} from "./domain/settings/openid/client-registration/client-registration.component";
+import {ClientRegistrationSettingsComponent} from "./domain/settings/openid/client-registration/settings/settings.component";
+import {ClientRegistrationDefaultScopeComponent} from "./domain/settings/openid/client-registration/default-scope/default-scope.component";
+import {ClientRegistrationAllowedScopeComponent} from "./domain/settings/openid/client-registration/allowed-scope/allowed-scope.component";
 import {DomainSettingsCertificatesComponent} from "./domain/settings/certificates/certificates.component";
 import {DomainSettingsProvidersComponent} from "./domain/settings/providers/providers.component";
 import {DomainSettingsRolesComponent} from "./domain/settings/roles/roles.component";
@@ -735,7 +738,13 @@ const routes: Routes = [
                 label: 'Client Registration',
                 section: 'Openid'
               }
-            }
+            },
+            children: [
+              { path: '', redirectTo: 'settings', pathMatch: 'full' },
+              { path: 'settings', component: ClientRegistrationSettingsComponent, resolve: {domain: DomainResolver} },
+              { path: 'default-scope', component: ClientRegistrationDefaultScopeComponent, resolve: {domain: DomainResolver, scopes: ScopesResolver}},
+              { path: 'allowed-scope', component: ClientRegistrationAllowedScopeComponent, resolve: {domain: DomainResolver, scopes: ScopesResolver}},
+            ]
           }
         ]
       }
diff --git a/gravitee-am-ui/src/app/app.module.ts b/gravitee-am-ui/src/app/app.module.ts
index d9bf13f0ff..66c937dd6f 100644
--- a/gravitee-am-ui/src/app/app.module.ts
+++ b/gravitee-am-ui/src/app/app.module.ts
@@ -90,6 +90,9 @@ import { DomainDashboardComponent } from "./domain/dashboard/dashboard.component
 import { DomainSettingsComponent } from './domain/settings/settings.component';
 import { DomainSettingsGeneralComponent } from "./domain/settings/general/general.component";
 import { DomainSettingsOpenidClientRegistrationComponent } from "./domain/settings/openid/client-registration/client-registration.component";
+import { ClientRegistrationSettingsComponent } from "./domain/settings/openid/client-registration/settings/settings.component";
+import { ClientRegistrationDefaultScopeComponent } from "./domain/settings/openid/client-registration/default-scope/default-scope.component";
+import { ClientRegistrationAllowedScopeComponent } from "./domain/settings/openid/client-registration/allowed-scope/allowed-scope.component";
 import { DomainSettingsRolesComponent } from "./domain/settings/roles/roles.component";
 import { DomainSettingsScopesComponent } from "./domain/settings/scopes/scopes.component";
 import { DomainSettingsCertificatesComponent, CertitificatePublicKeyDialog } from './domain/settings/certificates/certificates.component';
@@ -205,6 +208,7 @@ import { HttpRequestInterceptor } from "./interceptors/http-request.interceptor"
 import { PolicyFormComponent } from "./domain/settings/policies/policy/form/form.component";
 import { PolicyService } from "./services/policy.service";
 import { PoliciesResolver } from "./resolvers/policies.resolver";
+import { ScopeSelectionComponent} from "./domain/components/scope-selection/scope-selection.component";
 
 @NgModule({
   declarations: [
@@ -219,6 +223,9 @@ import { PoliciesResolver } from "./resolvers/policies.resolver";
     DomainSettingsComponent,
     DomainSettingsGeneralComponent,
     DomainSettingsOpenidClientRegistrationComponent,
+    ClientRegistrationSettingsComponent,
+    ClientRegistrationDefaultScopeComponent,
+    ClientRegistrationAllowedScopeComponent,
     DomainSettingsProvidersComponent,
     DomainSettingsScopesComponent,
     DomainSettingsRolesComponent,
@@ -321,7 +328,8 @@ import { PoliciesResolver } from "./resolvers/policies.resolver";
     TagComponent,
     AccountSettingsComponent,
     PolicyFormComponent,
-    PoliciesInfoDialog
+    PoliciesInfoDialog,
+    ScopeSelectionComponent
   ],
   imports: [
     BrowserModule,
diff --git a/gravitee-am-ui/src/app/domain/components/scope-selection/scope-selection.component.html b/gravitee-am-ui/src/app/domain/components/scope-selection/scope-selection.component.html
new file mode 100644
index 0000000000..452e290a45
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/components/scope-selection/scope-selection.component.html
@@ -0,0 +1,79 @@
+<!--
+
+    Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+            http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<div class="scope-container" fxLayout="column">
+
+  <mat-form-field>
+    <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
+  </mat-form-field>
+
+  <table mat-table [dataSource]="scopes" matSort matSortActive="select" matSortDirection="asc" class="mat-elevation-z8">
+
+    <!-- Checkbox Column -->
+    <ng-container matColumnDef="select">
+      <th mat-header-cell *matHeaderCellDef mat-sort-header>
+        <mat-checkbox (change)="$event ? masterToggle() : null"
+                      [checked]="selection.hasValue() && isAllSelected()"
+                      [indeterminate]="selection.hasValue() && !isAllSelected()"
+                      [aria-label]="checkboxLabel()">
+        </mat-checkbox>
+      </th>
+      <td mat-cell *matCellDef="let row">
+        <mat-checkbox (click)="$event.stopPropagation()"
+                      (change)="$event ? applyChange(row) : null"
+                      [checked]="selection.isSelected(row)"
+                      [aria-label]="checkboxLabel(row)">
+        </mat-checkbox>
+      </td>
+    </ng-container>
+
+    <!-- ID Column -->
+    <ng-container matColumnDef="id">
+      <th mat-header-cell *matHeaderCellDef> Id. </th>
+      <td mat-cell *matCellDef="let scope"> {{scope.id}} </td>
+    </ng-container>
+
+    <!-- Key Column -->
+    <ng-container matColumnDef="key">
+      <th mat-header-cell *matHeaderCellDef mat-sort-header> Key </th>
+      <td mat-cell *matCellDef="let scope"> {{scope.key}} </td>
+    </ng-container>
+
+    <!-- Name Column -->
+    <ng-container matColumnDef="name">
+      <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
+      <td mat-cell *matCellDef="let scope"> {{scope.name}} </td>
+    </ng-container>
+
+    <!-- Description Column -->
+    <ng-container matColumnDef="description">
+      <th mat-header-cell *matHeaderCellDef mat-sort-header> Description </th>
+      <td mat-cell *matCellDef="let scope"> {{scope.description}} </td>
+    </ng-container>
+
+    <!-- Description Column -->
+    <ng-container matColumnDef="discovery">
+      <th mat-header-cell *matHeaderCellDef mat-sort-header> Discovery </th>
+      <td mat-cell *matCellDef="let scope"> {{scope.discovery}} </td>
+    </ng-container>
+
+    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+    <tr mat-row *matRowDef="let row; columns: displayedColumns;"
+        (click)="selection.toggle(row)">
+    </tr>
+  </table>
+</div>
diff --git a/gravitee-am-ui/src/app/domain/components/scope-selection/scope-selection.component.scss b/gravitee-am-ui/src/app/domain/components/scope-selection/scope-selection.component.scss
new file mode 100644
index 0000000000..ae29a004bc
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/components/scope-selection/scope-selection.component.scss
@@ -0,0 +1,39 @@
+/*!*
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+.scope-container {
+  margin-bottom: 30px;
+  mat-hint {
+    font-size: 75%;
+  }
+}
+.mat-column-select {
+  overflow: initial;
+}
+
+.mat-form-field {
+  font-size: 14px;
+  width: 100%;
+}
+
+table {
+  width: 100%;
+  background: transparent;
+  box-shadow: none;
+}
+
+th.mat-sort-header-sorted {
+  color: black;
+}
diff --git a/gravitee-am-ui/src/app/domain/components/scope-selection/scope-selection.component.ts b/gravitee-am-ui/src/app/domain/components/scope-selection/scope-selection.component.ts
new file mode 100644
index 0000000000..8bc35cd494
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/components/scope-selection/scope-selection.component.ts
@@ -0,0 +1,110 @@
+/**
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {AfterViewInit, Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
+import {MatSort, MatTableDataSource} from '@angular/material';
+import {SelectionModel} from '@angular/cdk/collections';
+import {ActivatedRoute} from '@angular/router';
+import * as _ from 'lodash';
+
+export interface Scope {
+  id: string;
+  key: string;
+  name: string;
+  description: string;
+  discovery: boolean;
+}
+
+@Component({
+  selector: 'scope-selection',
+  templateUrl: './scope-selection.component.html',
+  styleUrls: ['./scope-selection.component.scss']
+})
+
+export class ScopeSelectionComponent implements OnInit, AfterViewInit {
+  @Output() onScopeSelection = new EventEmitter();
+  @Input() initialSelectedScopes: string[];
+
+  scopes: MatTableDataSource<Scope>;
+  selection: SelectionModel<Scope>;
+  displayedColumns: string[] = ['select', 'key', 'name', 'description'];
+
+  @ViewChild(MatSort) sort: MatSort;
+
+  constructor(private route: ActivatedRoute) {}
+
+  ngOnInit() {
+    const datasource = _.map(this.route.snapshot.data['scopes'],  scope => <Scope>{
+      id: scope.id, key: scope.key, name: scope.name, description: scope.description, discovery: scope.discovery
+    });
+    this.scopes = new MatTableDataSource(datasource);
+    const initialSelectedValues = _.intersectionWith(this.scopes.data, this.initialSelectedScopes, (scope, key) => scope.key === key);
+    this.selection = new SelectionModel<Scope>(true, _.compact(initialSelectedValues));
+  }
+
+  ngAfterViewInit() {
+    // implement custom sort to manage select checkbox
+    this.scopes.sortingDataAccessor = (scope, property) => {
+      switch (property) {
+        case 'select': {
+          return this.selection.isSelected(scope) ? 0 : 1;
+        }
+        default: {
+          return scope[property];
+        }
+      }
+    };
+    this.applySort();
+  }
+
+  applyChange(row) {
+    this.selection.toggle(row);
+    this.applySort();
+    this.onScopeSelection.emit(this.selection.selected);
+  }
+
+  /** Apply sort on table */
+  applySort() {
+    this.scopes.sort = this.sort;
+  }
+
+  /** Apply filter on table */
+  applyFilter(filterValue: string) {
+    this.scopes.filter = filterValue.trim().toLowerCase();
+  }
+
+  /** Whether the number of selected elements matches the total number of rows. */
+  isAllSelected() {
+    const numSelected = this.selection.selected.length;
+    const numRows = this.scopes.data.length;
+    return numSelected === numRows;
+  }
+
+  /** Selects all rows if they are not all selected; otherwise clear selection. */
+  masterToggle() {
+    this.isAllSelected() ?
+      this.selection.clear() :
+      this.scopes.data.forEach(row => this.selection.select(row));
+    this.onScopeSelection.emit(this.selection.selected);
+  }
+
+  /** The label for the checkbox on the passed row */
+  checkboxLabel(row?: Scope): string {
+    if (!row) {
+      return `${this.isAllSelected() ? 'select' : 'deselect'} all`;
+    }
+    return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.id + 1}`;
+  }
+}
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.html b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.html
new file mode 100644
index 0000000000..eea12420c8
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.html
@@ -0,0 +1,57 @@
+<!--
+
+    Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+            http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<div class="domain-client-registration-allowed-scope-container">
+  <div class="domain-client-registration-allowed-scope-content" *ngIf="dcrIsEnabled">
+    <div fxLayout="column" fxFlex="70">
+      <form (ngSubmit)="patch()" #allowedScopeForm="ngForm" fxLayout="column">
+
+        <div class="domain-client-registration-allowed-scope-state" fxLayout="column">
+          <mat-slide-toggle
+            (change)="enableAllowedScopesFilter($event)"
+            [checked]="isAllowedScopesEnabled">
+            Enable scopes restriction on client registration
+          </mat-slide-toggle>
+        </div>
+
+        <scope-selection
+          [initialSelectedScopes]="initialSelectedScopes"
+          (onScopeSelection)="onChange($event)"
+          *ngIf="isAllowedScopesEnabled">
+        </scope-selection>
+
+        <div class="domain-client-registration-allowed-scope-form-actions">
+          <button mat-raised-button [disabled]="(!allowedScopeForm.valid || allowedScopeForm.pristine) && !formChanged" type="submit">SAVE</button>
+        </div>
+      </form>
+    </div>
+    <div class="domain-client-registration-allowed-scope-description" fxFlex>
+      <h3>Allowed scopes</h3>
+      <div class="domain-client-registration-allowed-scope-description-content">
+        <p>
+          This section is used to define which scopes can be selected by third parties when they register a client through the Openid Connect Dynamic Client Registration endpoint.
+        </p>
+        <small><i>On the client registration process, access management will only retain the allowed scopes (if enabled).<br>
+          After applying this filter, if there is no more requested scopes, access management may add some default scopes.</i></small>
+      </div>
+    </div>
+  </div>
+  <app-emptystate *ngIf="!dcrIsEnabled"
+                  [message]="'Openid Connect Dynamic Client Registration is disabled.'"
+                  [subMessage]="'This feature can be enable through the Settings tab.'">
+  </app-emptystate>
+</div>
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.scss b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.scss
new file mode 100644
index 0000000000..0b88c104f3
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.scss
@@ -0,0 +1,60 @@
+.mat-column-select {
+  overflow: initial;
+}
+
+.mat-form-field {
+  font-size: 14px;
+  width: 100%;
+}
+
+table {
+  width: 100%;
+  background: transparent;
+  box-shadow: none;
+}
+
+th.mat-sort-header-sorted {
+  color: black;
+}
+
+.domain-client-registration-allowed-scope-container {
+  padding: 10px 10px 10px 10px;
+  h1 {
+    font-weight: 400;
+  }
+  .domain-client-registration-allowed-scope-content {
+    form {
+      padding: 20px;
+      background: #fafafa;
+      border-radius: 2px;
+      border: 1px solid rgb(226, 229, 231);
+
+      .domain-client-registration-allowed-scope-state {
+        margin-bottom: 30px;
+        mat-hint {
+          font-size: 75%;
+        }
+      }
+      .domain-client-registration-allowed-scope-form-actions {
+        margin-top: 20px;
+      }
+    }
+    .domain-client-registration-allowed-scope-description {
+      margin-left: 20px;
+      h3 {
+        font-weight: 400;
+      }
+      .domain-client-registration-allowed-scope-description-content {
+        border-top: 1px solid rgb(226, 229, 231);
+        p {
+          margin-top: 20px;
+          font-size: 14px;
+        }
+        small {
+          font-size: 12px;
+          color: rgba(0, 0, 0, 0.38);
+        }
+      }
+    }
+  }
+}
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.spec.ts b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.spec.ts
new file mode 100644
index 0000000000..b102f793d8
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.spec.ts
@@ -0,0 +1,16 @@
+/**
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.ts b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.ts
new file mode 100644
index 0000000000..c44328f0cc
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/allowed-scope/allowed-scope.component.ts
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {Component, OnInit} from '@angular/core';
+import {ActivatedRoute} from '@angular/router';
+import * as _ from 'lodash';
+import {DomainService} from '../../../../../services/domain.service';
+import {SnackbarService} from '../../../../../services/snackbar.service';
+import {Scope} from '../../../../components/scope-selection/scope-selection.component';
+
+@Component({
+  selector: 'app-openid-client-registration-allowed-scope',
+  templateUrl: './allowed-scope.component.html',
+  styleUrls: ['./allowed-scope.component.scss']
+})
+
+export class ClientRegistrationAllowedScopeComponent implements OnInit {
+  domain: any = {};
+  formChanged: boolean;
+  dcrIsEnabled: boolean;
+  isAllowedScopesEnabled: boolean;
+
+  initialSelectedScopes: string[];
+  selectedScopes: Scope[];
+
+  constructor(private domainService: DomainService, private route: ActivatedRoute,
+              private snackbarService: SnackbarService) {
+  }
+
+  ngOnInit() {
+    this.domain = this.route.snapshot.data['domain'];
+    this.dcrIsEnabled = this.domain.oidc.clientRegistrationSettings.isDynamicClientRegistrationEnabled;
+    this.isAllowedScopesEnabled = this.domain.oidc.clientRegistrationSettings.isAllowedScopesEnabled;
+    this.initialSelectedScopes = this.domain.oidc.clientRegistrationSettings.allowedScopes;
+  }
+
+  enableAllowedScopesFilter(event) {
+    this.isAllowedScopesEnabled = event.checked;
+    this.formChanged = true;
+  }
+
+  onChange(currentSelectedScopes) {
+    this.selectedScopes = currentSelectedScopes;
+    this.formChanged = true;
+  }
+
+  patch() {
+    const domain = {
+      oidc: {
+        clientRegistrationSettings: {
+          allowedScopes: _.map(this.selectedScopes, scope => scope.key),
+          isAllowedScopesEnabled: this.isAllowedScopesEnabled
+        }
+      }
+    };
+
+    this.domainService.patchOpenidDCRSettings(this.domain.id, domain).subscribe(response => {
+      this.domain = response;
+      this.snackbarService.open('Domain ' + this.domain.name + ' updated');
+      this.formChanged = false;
+    });
+  }
+}
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.html b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.html
index 138e6da616..b06a7e8342 100644
--- a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.html
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.html
@@ -15,68 +15,19 @@
     limitations under the License.
 
 -->
-<div class="domain-client-registration-container">
-  <h1>Client Registration</h1>
-  <div class="domain-client-registration-content">
-    <div fxLayout="column" fxFlex="70">
-      <form (ngSubmit)="patch()" #domainForm="ngForm" fxLayout="column">
-        <div class="domain-client-registration-state" fxLayout="column">
-          <mat-slide-toggle
-            (change)="enableDynamicClientRegistration($event)"
-            [checked]="domain.oidc.clientRegistrationSettings.isDynamicClientRegistrationEnabled">
-            Enable/Disable Dynamic Client Registration.
-          </mat-slide-toggle>
-          <mat-hint>
-            Enable application owner to self register their application through an openid connect endpoint.<br>
-            The endpoint is available under the oidc Discovery service. <i>/.well-known/openid-configuration</i>
-          </mat-hint>
-        </div>
-        <div class="domain-client-registration-state" fxLayout="column">
-          <mat-slide-toggle
-            (change)="enableOpenDynamicClientRegistration($event)"
-            [checked]="domain.oidc.clientRegistrationSettings.isOpenDynamicClientRegistrationEnabled">
-            Enable/Disable Open Dynamic Client Registration
-          </mat-slide-toggle>
-          <mat-hint>Enable application owner to self register their application without needing to be authenticated.</mat-hint>
-        </div>
-        <div class="domain-client-registration-state" fxLayout="column">
-          <mat-slide-toggle
-            (change)="allowLocalhostRedirectUri($event)"
-            [checked]="domain.oidc.clientRegistrationSettings.allowLocalhostRedirectUri">
-            Allow localhost redirect uris.
-          </mat-slide-toggle>
-          <mat-hint>Allow clients to be registered with redirect_uris using localhost as host.</mat-hint>
-        </div>
-        <div class="domain-client-registration-state" fxLayout="column">
-          <mat-slide-toggle
-            (change)="allowHttpSchemeRedirectUri($event)"
-            [checked]="domain.oidc.clientRegistrationSettings.allowHttpSchemeRedirectUri">
-            Allow unsecured (http) redirect uris.
-          </mat-slide-toggle>
-          <mat-hint>Allow clients to be registered with redirect_uris using unsecured (http) scheme.</mat-hint>
-        </div>
-        <div class="domain-client-registration-state" fxLayout="column">
-          <mat-slide-toggle
-            (change)="allowWildCardRedirectUri($event)"
-            [checked]="domain.oidc.clientRegistrationSettings.allowWildCardRedirectUri">
-            Allow wildcards redirect_uris.
-          </mat-slide-toggle>
-          <mat-hint>Allow clients to be registered with redirect_uris containing wildcards.</mat-hint>
-        </div>
-        <div class="domain-client-registration-form-actions">
-          <button mat-raised-button [disabled]="(!domainForm.valid || domainForm.pristine) && !formChanged" type="submit">SAVE</button>
-        </div>
-      </form>
-    </div>
+<div class="client-registration-container">
 
-    <div class="domain-client-registration-description" fxFlex>
-      <h3>Client Registration</h3>
-      <div class="domain-client-registration-description-content">
-        <p>
-          This section is used to define business rules regarding client (application) creation within the domain.
-        </p>
-        <small><i>For some security reasons, it is strongly recommended to not allow unsecured http scheme, localhost as well as wildcard in the redirect_uri.</i></small>
-      </div>
-    </div>
+  <h1>Client Registration Settings</h1>
+  <nav mat-tab-nav-bar>
+    <a mat-tab-link
+       *ngFor="let link of navLinks"
+       [routerLink]="link.href"
+       routerLinkActive #rla="routerLinkActive"
+       [active]="rla.isActive">
+      {{link.label}}
+    </a>
+  </nav>
+  <div class="client-registration-content">
+    <router-outlet></router-outlet>
   </div>
 </div>
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.scss b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.scss
index 5a05f24ec2..5484f8af0b 100644
--- a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.scss
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.scss
@@ -1,64 +1,17 @@
-.domain-client-registration-container {
+.client-registration-container {
   padding: 20px 70px 20px 50px;
-  h1 {
-    font-weight: 400;
-  }
-  .domain-client-registration-content {
-    form {
-      padding: 20px;
-      background: #fafafa;
-      border-radius: 2px;
-      border: 1px solid rgb(226, 229, 231);
-      .domain-client-registration-state {
-        margin-bottom: 30px;
-        mat-hint {
-          font-size: 75%;
-        }
-      }
-      .domain-client-registration-form-actions {
-        margin-top: 20px;
-      }
-    }
-    .domain-client-registration-description {
-      margin-left: 20px;
-      h3 {
-        font-weight: 400;
-      }
-      .domain-client-registration-description-content {
-        border-top: 1px solid rgb(226, 229, 231);
-        p {
-          margin-top: 20px;
-          font-size: 14px;
-        }
-        small {
-          font-size: 12px;
-          color: rgba(0, 0, 0, 0.38);
-        }
-      }
+  a.back-link {
+    color: #006CAB;
+    text-decoration: none;
+    &:hover {
+      color: #2196f3;
+      text-decoration: underline;
     }
   }
-}
-
-.clients-container {
   h1 {
     font-weight: 400;
   }
-  ngx-datatable {
-    font-size: 14px;
-    box-shadow: none;
-  }
-
-  .badge {
-    margin-left: 5px;
-    padding: 3px 6px;
-  }
-}
-
-.clients-actions {
-  margin-left: -10px;
-
-  button, a {
-    top: -9px;
-    color: grey;
+  .client-registration-content {
+    padding: 25px 0 20px;
   }
 }
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.ts b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.ts
index fe76d7549b..0471b7cbf9 100644
--- a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.ts
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/client-registration.component.ts
@@ -13,20 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {Component, OnInit, ViewChild} from '@angular/core';
-import { DomainService } from "../../../../services/domain.service";
-import { DialogService } from "../../../../services/dialog.service";
-import { ActivatedRoute, Router } from "@angular/router";
-import { SnackbarService } from "../../../../services/snackbar.service";
+import {Component, OnInit} from '@angular/core';
+import { ActivatedRoute } from "@angular/router";
 import { BreadcrumbService } from "../../../../../libraries/ng2-breadcrumb/components/breadcrumbService";
-import { SidenavService } from "../../../../components/sidenav/sidenav.service";
-import { ClientService } from "../../../../services/client.service";
-import { MatInput } from "@angular/material";
-
-export interface Client {
-  id: string;
-  clientId: string;
-}
 
 @Component({
   selector: 'app-openid-client-registration',
@@ -34,67 +23,27 @@ export interface Client {
   styleUrls: ['./client-registration.component.scss']
 })
 export class DomainSettingsOpenidClientRegistrationComponent implements OnInit {
-
-  @ViewChild('chipInput') chipInput: MatInput;
+  private domainId: string;
+  navLinks: any = [
+    {'href': 'settings' , 'label': 'Settings'},
+    {'href': 'default-scope' , 'label': 'Default Scopes'},
+    {'href': 'allowed-scope' , 'label': 'Allowed Scopes'}
+  ];
 
   formChanged: boolean = false;
   domain: any = {};
-  clientDcrDisabled: boolean = false;
-  disableToolTip: boolean = false;
-  toolTipMessage = "";
 
-  constructor(private domainService: DomainService, private dialogService: DialogService, private snackbarService: SnackbarService,
-              private router: Router, private route: ActivatedRoute, private breadcrumbService: BreadcrumbService, private sidenavService: SidenavService,
-              private clientService: ClientService) {
+  constructor(private route: ActivatedRoute, private breadcrumbService: BreadcrumbService) {
   }
 
   ngOnInit() {
-    this.domain = this.route.snapshot.parent.data['domain'];
-  }
-
-  enableDynamicClientRegistration(event) {
-    this.domain.oidc.clientRegistrationSettings.isDynamicClientRegistrationEnabled = event.checked;
-    //If disabled, ensure to disable open dynamic client registration too and disable clients toogle too.
-    if(!event.checked) {
-      this.domain.oidc.clientRegistrationSettings.isOpenDynamicClientRegistrationEnabled = event.checked;
-      this.clientDcrDisabled = !event.checked;
-      this.disableToolTip = event.checked;
-      this.toolTipMessage = "Disable until settings are saved and feature is enabled.";
-    }
-    this.formChanged = true;
-  }
-
-  enableOpenDynamicClientRegistration(event) {
-    this.domain.oidc.clientRegistrationSettings.isOpenDynamicClientRegistrationEnabled = event.checked;
-    //If enabled, ensure to enable dynamic client registration too.
-    if(event.checked) {
-      this.domain.oidc.clientRegistrationSettings.isDynamicClientRegistrationEnabled = event.checked;
-    }
-    this.formChanged = true;
-  }
-
-  allowLocalhostRedirectUri(event) {
-    this.domain.oidc.clientRegistrationSettings.allowLocalhostRedirectUri = event.checked;
-    this.formChanged = true;
-  }
-
-  allowHttpSchemeRedirectUri(event) {
-    this.domain.oidc.clientRegistrationSettings.allowHttpSchemeRedirectUri = event.checked;
-    this.formChanged = true;
-  }
-
-  allowWildCardRedirectUri(event) {
-    this.domain.oidc.clientRegistrationSettings.allowWildCardRedirectUri = event.checked;
-    this.formChanged = true;
+    this.domainId = this.route.snapshot.parent.data['domain'].name;
+    this.initBreadcrumb();
   }
 
-  patch() {
-    this.domainService.patchOpenidDCRSettings(this.domain.id, this.domain).subscribe(response => {
-      this.domain = response;
-      this.domainService.notify(this.domain);
-      this.sidenavService.notify(this.domain);
-      this.breadcrumbService.addFriendlyNameForRoute('/domains/'+this.domain.id, this.domain.name);
-      this.snackbarService.open("Domain " + this.domain.name + " updated");
-    });
+  initBreadcrumb() {
+    this.breadcrumbService.addFriendlyNameForRouteRegex('/domains/'+this.domainId+'/settings/openid/clientRegistration/settings', 'settings');
+    this.breadcrumbService.addFriendlyNameForRouteRegex('/domains/'+this.domainId+'/settings/openid/clientRegistration/default-scope', 'default scopes');
+    this.breadcrumbService.addFriendlyNameForRouteRegex('/domains/'+this.domainId+'/settings/openid/clientRegistration/allowed-scope', 'allowed scopes');
   }
 }
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.html b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.html
new file mode 100644
index 0000000000..983b43d8b8
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.html
@@ -0,0 +1,48 @@
+<!--
+
+    Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+            http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<div class="domain-client-registration-default-scope-container">
+  <div class="domain-client-registration-default-scope-content" *ngIf="dcrIsEnabled">
+    <div fxLayout="column" fxFlex="70">
+      <form (ngSubmit)="patch()" #defaultScopeForm="ngForm" fxLayout="column">
+
+        <scope-selection
+          [initialSelectedScopes]="initialSelectedScopes"
+          (onScopeSelection)="onChange($event)">
+        </scope-selection>
+
+        <div class="domain-client-registration-default-scope-form-actions">
+          <button mat-raised-button [disabled]="(!defaultScopeForm.valid || defaultScopeForm.pristine) && !formChanged" type="submit">SAVE</button>
+        </div>
+
+      </form>
+    </div>
+    <div class="domain-client-registration-default-scope-description" fxFlex>
+      <h3>Default scopes</h3>
+      <div class="domain-client-registration-default-scope-description-content">
+        <p>
+          This section is used to define some default scope to be automatically added when a client is created through the Openid Connect Dynamic Client Registration endpoint, without any requested scopes.
+        </p>
+        <small><i>As the <a href="https://tools.ietf.org/html/rfc7591#section-2" target="_blank">specification</a> state: If omitted, an authorization server MAY register a client with a default set of scopes.</i></small>
+      </div>
+    </div>
+  </div>
+  <app-emptystate *ngIf="!dcrIsEnabled"
+                  [message]="'Openid Connect Dynamic Client Registration is disabled.'"
+                  [subMessage]="'This feature can be enable through the Settings tab.'">
+  </app-emptystate>
+</div>
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.scss b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.scss
new file mode 100644
index 0000000000..4d1b95caf4
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.scss
@@ -0,0 +1,40 @@
+.domain-client-registration-default-scope-container {
+  padding: 10px 10px 10px 10px;
+  h1 {
+    font-weight: 400;
+  }
+  .domain-client-registration-default-scope-content {
+    form {
+      padding: 20px;
+      background: #fafafa;
+      border-radius: 2px;
+      border: 1px solid rgb(226, 229, 231);
+
+      ngx-datatable {
+        background: transparent;
+        box-shadow: none;
+      }
+
+      .domain-client-registration-default-scope-form-actions {
+        margin-top: 20px;
+      }
+    }
+    .domain-client-registration-default-scope-description {
+      margin-left: 20px;
+      h3 {
+        font-weight: 400;
+      }
+      .domain-client-registration-default-scope-description-content {
+        border-top: 1px solid rgb(226, 229, 231);
+        p {
+          margin-top: 20px;
+          font-size: 14px;
+        }
+        small {
+          font-size: 12px;
+          color: rgba(0, 0, 0, 0.38);
+        }
+      }
+    }
+  }
+}
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.spec.ts b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.spec.ts
new file mode 100644
index 0000000000..5f8969631f
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.spec.ts
@@ -0,0 +1,15 @@
+/**
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.ts b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.ts
new file mode 100644
index 0000000000..e1ab063310
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/default-scope/default-scope.component.ts
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {Component, OnInit} from '@angular/core';
+import {ActivatedRoute} from '@angular/router';
+import * as _ from 'lodash';
+import {DomainService} from '../../../../../services/domain.service';
+import {SnackbarService} from '../../../../../services/snackbar.service';
+import {Scope} from '../../../../components/scope-selection/scope-selection.component';
+
+@Component({
+  selector: 'app-openid-client-registration-default-scope',
+  templateUrl: './default-scope.component.html',
+  styleUrls: ['./default-scope.component.scss']
+})
+
+export class ClientRegistrationDefaultScopeComponent implements OnInit {
+  domain: any = {};
+  formChanged: boolean;
+  dcrIsEnabled: boolean;
+
+  initialSelectedScopes: string[];
+  selectedScopes: Scope[];
+
+  constructor(private domainService: DomainService, private route: ActivatedRoute,
+              private snackbarService: SnackbarService) {
+  }
+
+  ngOnInit() {
+    this.domain = this.route.snapshot.data['domain'];
+    this.dcrIsEnabled = this.domain.oidc.clientRegistrationSettings.isDynamicClientRegistrationEnabled;
+    this.initialSelectedScopes = this.domain.oidc.clientRegistrationSettings.defaultScopes;
+  }
+
+  onChange(currentSelectedScopes) {
+    this.selectedScopes = currentSelectedScopes;
+    this.formChanged = true;
+  }
+
+  patch() {
+    const domain = {
+      oidc: {
+        clientRegistrationSettings: {
+          defaultScopes: _.map(this.selectedScopes, scope => scope.key)
+        }
+      }
+    };
+
+    this.domainService.patchOpenidDCRSettings(this.domain.id, domain).subscribe(response => {
+      this.domain = response;
+      this.snackbarService.open('Domain ' + this.domain.name + ' updated');
+      this.formChanged = false;
+    });
+  }
+}
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.html b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.html
new file mode 100644
index 0000000000..f16799a425
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.html
@@ -0,0 +1,81 @@
+<!--
+
+    Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+            http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<div class="domain-client-registration-settings-container">
+  <div class="domain-client-registration-settings-content">
+    <div fxLayout="column" fxFlex="70">
+      <form (ngSubmit)="patch()" #domainForm="ngForm" fxLayout="column">
+        <div class="domain-client-registration-settings-state" fxLayout="column">
+          <mat-slide-toggle
+            (change)="enableDynamicClientRegistration($event)"
+            [checked]="domain.oidc.clientRegistrationSettings.isDynamicClientRegistrationEnabled">
+            Enable/Disable Dynamic Client Registration.
+          </mat-slide-toggle>
+          <mat-hint>
+            Enable application owner to self register their application through an openid connect endpoint.<br>
+            The endpoint is available under the oidc Discovery service. <i>/.well-known/openid-configuration</i>
+          </mat-hint>
+        </div>
+        <div class="domain-client-registration-settings-state" fxLayout="column">
+          <mat-slide-toggle
+            (change)="enableOpenDynamicClientRegistration($event)"
+            [checked]="domain.oidc.clientRegistrationSettings.isOpenDynamicClientRegistrationEnabled">
+            Enable/Disable Open Dynamic Client Registration
+          </mat-slide-toggle>
+          <mat-hint>Enable application owner to self register their application without needing to be authenticated.</mat-hint>
+        </div>
+        <div class="domain-client-registration-settings-state" fxLayout="column">
+          <mat-slide-toggle
+            (change)="allowLocalhostRedirectUri($event)"
+            [checked]="domain.oidc.clientRegistrationSettings.allowLocalhostRedirectUri">
+            Allow localhost redirect uris.
+          </mat-slide-toggle>
+          <mat-hint>Allow clients to be registered with redirect_uris using localhost as host.</mat-hint>
+        </div>
+        <div class="domain-client-registration-settings-state" fxLayout="column">
+          <mat-slide-toggle
+            (change)="allowHttpSchemeRedirectUri($event)"
+            [checked]="domain.oidc.clientRegistrationSettings.allowHttpSchemeRedirectUri">
+            Allow unsecured (http) redirect uris.
+          </mat-slide-toggle>
+          <mat-hint>Allow clients to be registered with redirect_uris using unsecured (http) scheme.</mat-hint>
+        </div>
+        <div class="domain-client-registration-settings-state" fxLayout="column">
+          <mat-slide-toggle
+            (change)="allowWildCardRedirectUri($event)"
+            [checked]="domain.oidc.clientRegistrationSettings.allowWildCardRedirectUri">
+            Allow wildcards redirect_uris.
+          </mat-slide-toggle>
+          <mat-hint>Allow clients to be registered with redirect_uris containing wildcards.</mat-hint>
+        </div>
+        <div class="domain-client-registration-settings-form-actions">
+          <button mat-raised-button [disabled]="(!domainForm.valid || domainForm.pristine) && !formChanged" type="submit">SAVE</button>
+        </div>
+      </form>
+    </div>
+
+    <div class="domain-client-registration-settings-description" fxFlex>
+      <h3>Client Registration</h3>
+      <div class="domain-client-registration-settings-description-content">
+        <p>
+          This section is used to define business rules regarding client (application) creation within the domain.
+        </p>
+        <small><i>For some security reasons, it is strongly recommended to not allow unsecured http scheme, localhost as well as wildcard in the redirect_uri.</i></small>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.scss b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.scss
new file mode 100644
index 0000000000..fdb4d7ece4
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.scss
@@ -0,0 +1,40 @@
+.domain-client-registration-settings-container {
+  padding: 10px 10px 10px 10px;
+  h1 {
+    font-weight: 400;
+  }
+  .domain-client-registration-settings-content {
+    form {
+      padding: 20px;
+      background: #fafafa;
+      border-radius: 2px;
+      border: 1px solid rgb(226, 229, 231);
+      .domain-client-registration-settings-state {
+        margin-bottom: 30px;
+        mat-hint {
+          font-size: 75%;
+        }
+      }
+      .domain-client-registration-settings-form-actions {
+        margin-top: 20px;
+      }
+    }
+    .domain-client-registration-settings-description {
+      margin-left: 20px;
+      h3 {
+        font-weight: 400;
+      }
+      .domain-client-registration-settings-description-content {
+        border-top: 1px solid rgb(226, 229, 231);
+        p {
+          margin-top: 20px;
+          font-size: 14px;
+        }
+        small {
+          font-size: 12px;
+          color: rgba(0, 0, 0, 0.38);
+        }
+      }
+    }
+  }
+}
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.spec.ts b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.spec.ts
new file mode 100644
index 0000000000..5f8969631f
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.spec.ts
@@ -0,0 +1,15 @@
+/**
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
diff --git a/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.ts b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.ts
new file mode 100644
index 0000000000..50c9ec7105
--- /dev/null
+++ b/gravitee-am-ui/src/app/domain/settings/openid/client-registration/settings/settings.component.ts
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {Component, OnInit} from '@angular/core';
+import { DomainService } from "../../../../../services/domain.service";
+import { DialogService } from "../../../../../services/dialog.service";
+import { ActivatedRoute, Router } from "@angular/router";
+import { SnackbarService } from "../../../../../services/snackbar.service";
+import { BreadcrumbService } from "../../../../../../libraries/ng2-breadcrumb/components/breadcrumbService";
+import { SidenavService } from "../../../../../components/sidenav/sidenav.service";
+
+@Component({
+  selector: 'app-openid-client-registration-settings',
+  templateUrl: './settings.component.html',
+  styleUrls: ['./settings.component.scss']
+})
+export class ClientRegistrationSettingsComponent implements OnInit {
+
+  formChanged = false;
+  domain: any = {};
+  clientDcrDisabled = false;
+  disableToolTip = false;
+  toolTipMessage = '';
+
+  constructor(private domainService: DomainService, private dialogService: DialogService, private snackbarService: SnackbarService,
+              private router: Router, private route: ActivatedRoute, private breadcrumbService: BreadcrumbService, private sidenavService: SidenavService)
+  {}
+
+  ngOnInit() {
+    this.domain = this.route.snapshot.data['domain'];
+  }
+
+  enableDynamicClientRegistration(event) {
+    this.domain.oidc.clientRegistrationSettings.isDynamicClientRegistrationEnabled = event.checked;
+    // If disabled, ensure to disable open dynamic client registration too and disable clients toogle too.
+    if (!event.checked) {
+      this.domain.oidc.clientRegistrationSettings.isOpenDynamicClientRegistrationEnabled = event.checked;
+      this.clientDcrDisabled = !event.checked;
+      this.disableToolTip = event.checked;
+      this.toolTipMessage = "Disable until settings are saved and feature is enabled.";
+    }
+    this.formChanged = true;
+  }
+
+  enableOpenDynamicClientRegistration(event) {
+    this.domain.oidc.clientRegistrationSettings.isOpenDynamicClientRegistrationEnabled = event.checked;
+    // If enabled, ensure to enable dynamic client registration too.
+    if (event.checked) {
+      this.domain.oidc.clientRegistrationSettings.isDynamicClientRegistrationEnabled = event.checked;
+    }
+    this.formChanged = true;
+  }
+
+  allowLocalhostRedirectUri(event) {
+    this.domain.oidc.clientRegistrationSettings.allowLocalhostRedirectUri = event.checked;
+    this.formChanged = true;
+  }
+
+  allowHttpSchemeRedirectUri(event) {
+    this.domain.oidc.clientRegistrationSettings.allowHttpSchemeRedirectUri = event.checked;
+    this.formChanged = true;
+  }
+
+  allowWildCardRedirectUri(event) {
+    this.domain.oidc.clientRegistrationSettings.allowWildCardRedirectUri = event.checked;
+    this.formChanged = true;
+  }
+
+  patch() {
+    this.domainService.patchOpenidDCRSettings(this.domain.id, this.domain).subscribe(response => {
+      this.domain = response;
+      this.domainService.notify(this.domain);
+      this.sidenavService.notify(this.domain);
+      this.breadcrumbService.addFriendlyNameForRoute('/domains/' + this.domain.id, this.domain.name);
+      this.snackbarService.open('Domain ' + this.domain.name + ' updated');
+      this.formChanged = false;
+    });
+  }
+}
diff --git a/gravitee-am-ui/src/app/resolvers/domain.resolver.ts b/gravitee-am-ui/src/app/resolvers/domain.resolver.ts
index 9652c3ec20..c205c85807 100644
--- a/gravitee-am-ui/src/app/resolvers/domain.resolver.ts
+++ b/gravitee-am-ui/src/app/resolvers/domain.resolver.ts
@@ -27,7 +27,7 @@ export class DomainResolver implements Resolve<any> {
   resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any>|Promise<any>|any {
     let domainId = AppConfig.settings.authentication.domainId;
     if (!state.url.startsWith('/settings')) {
-      domainId = (route.paramMap.get('domainId')) ? route.paramMap.get('domainId') : route.parent.paramMap.get('domainId') ? route.parent.paramMap.get('domainId') : route.parent.parent.paramMap.get('domainId');
+      domainId = (route.paramMap.get('domainId')) ? route.paramMap.get('domainId') : route.parent.paramMap.get('domainId') ? route.parent.paramMap.get('domainId') : route.parent.parent.paramMap.get('domainId') ? route.parent.parent.paramMap.get('domainId') : route.parent.parent.parent.paramMap.get('domainId');
     }
     return this.domainService.get(domainId);
   }
diff --git a/postman/collections/graviteeio-am-openid-dcr-collection.json b/postman/collections/graviteeio-am-openid-dcr-collection.json
index ae0dfb8dfd..ac70cbee18 100644
--- a/postman/collections/graviteeio-am-openid-dcr-collection.json
+++ b/postman/collections/graviteeio-am-openid-dcr-collection.json
@@ -503,12 +503,14 @@
 									"    pm.expect(body).to.have.property(\"revocation_endpoint\");",
 									"    pm.expect(body).to.have.property(\"userinfo_endpoint\");",
 									"    pm.expect(body).to.have.property(\"registration_endpoint\");",
+									"    pm.expect(body).to.have.property(\"registration_renew_secret_endpoint\");",
 									"",
 									"    pm.environment.set('authorizationEndpoint', body.authorization_endpoint);",
 									"    pm.environment.set('tokenEndpoint', body.token_endpoint);",
 									"    pm.environment.set('userinfoEndpoint', body.userinfo_endpoint);",
 									"    pm.environment.set('revocationEndpoint', body.revocation_endpoint);",
 									"    pm.environment.set('registrationEndpoint', body.registration_endpoint);",
+									"    pm.environment.set('registrationRenewSecretEndpoint', body.registration_renew_secret_endpoint);",
 									"});"
 								],
 								"type": "text/javascript"
@@ -897,6 +899,10 @@
 									"    var body = pm.response.json();",
 									"    pm.expect(body.client_id).to.eql(pm.environment.get('newClientIdForDCRTests'));",
 									"    pm.expect(body.client_secret).to.not.eql(pm.environment.get('newClientSecretForDCRTests'));",
+									"",
+									"    let renewSecretEndpoint = pm.environment.get('registrationClientUri')+'/renew_secret';",
+									"    let discoveryRenewSecret = pm.environment.get('registrationRenewSecretEndpoint').replace(':client_id',pm.environment.get('newClientIdForDCRTests'));",
+									"    pm.expect(renewSecretEndpoint).to.be.eql(discoveryRenewSecret);",
 									"});",
 									"",
 									"pm.test(\"One time Token\", function() {",
@@ -2600,61 +2606,24 @@
 								}
 							},
 							"response": []
-						}
-					],
-					"event": [
-						{
-							"listen": "prerequest",
-							"script": {
-								"id": "6344fd45-5776-4bab-a90c-033893e6debb",
-								"type": "text/javascript",
-								"exec": [
-									""
-								]
-							}
 						},
 						{
-							"listen": "test",
-							"script": {
-								"id": "03904ca6-6d82-43ab-8190-f3210787a262",
-								"type": "text/javascript",
-								"exec": [
-									""
-								]
-							}
-						}
-					],
-					"_postman_isSubFolder": true
-				},
-				{
-					"name": "Invalid update requests",
-					"item": [
-						{
-							"name": "Register client",
+							"name": "Invalid jwks_uri",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
-										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"id": "c557fd6b-d770-4568-8db7-ccb3267b0256",
 										"exec": [
-											"pm.test(\"Status code is 201\", function () {",
-											"    pm.response.to.have.status(201);",
+											"pm.test(\"Status code is 400\", function () {",
+											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Has default attributes\", function () {",
+											"pm.test(\"Invalid scope\", function () {",
+											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
-											"    pm.expect(body).to.have.property('response_types');",
-											"    pm.expect(body).to.have.property('grant_types');",
-											"    pm.expect(body).to.have.property('client_name');",
-											"    pm.expect(body).to.have.property('client_id');",
-											"    pm.expect(body).to.have.property('client_secret');",
-											"    pm.expect(body.response_types).to.eql(['code']);",
-											"    pm.expect(body.grant_types).to.eql(['authorization_code']);",
-											"    pm.expect(body.client_name).to.eql('Unknown Client');",
-											"    ",
-											"    pm.environment.set('newClientForDCRTests', body.id);",
-											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
-											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
+											"    pm.expect(body.error_description).to.include('Unable to parse jwks from');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -2677,7 +2646,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n   \"application_type\": \"web\",\n   \"redirect_uris\":\n     [\"https://client.example.org/callback\",\n      \"https://client.example.org/callback2\"],\n   \"logo_uri\": \"https://client.example.org/logo.png\",\n   \"token_endpoint_auth_method\": \"client_secret_basic\",\n   \"userinfo_encrypted_response_alg\": \"RSA-OAEP-256\",\n   \"userinfo_encrypted_response_enc\": \"A128CBC-HS256\",\n   \"contacts\": [\"ve7jtb@example.org\", \"mary@example.org\"],\n   \"request_uris\":\n     [\"https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA\"]\n  }"
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n  \"client_name\": \"My Example Client\",\n   \"jwks_uri\": \"https://unbound/uri\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationEndpoint}}",
@@ -2689,72 +2658,22 @@
 							"response": []
 						},
 						{
-							"name": "Invalid access token",
-							"event": [
-								{
-									"listen": "test",
-									"script": {
-										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
-										"exec": [
-											"pm.test(\"Status code is 401\", function () {",
-											"    pm.response.to.have.status(401);",
-											"});",
-											"",
-											"pm.test(\"Invalid bearer\", function () {",
-											"    pm.response.to.be.header('Content-Type', 'application/json');",
-											"    var body = pm.response.json();",
-											"    pm.expect(body.error).to.eql('invalid_token');",
-											"    pm.expect(body.error_description).to.eql('The access token is invalid');",
-											"});"
-										],
-										"type": "text/javascript"
-									}
-								}
-							],
-							"request": {
-								"method": "PUT",
-								"header": [
-									{
-										"key": "Content-Type",
-										"type": "text",
-										"value": "application/json"
-									},
-									{
-										"key": "Authorization",
-										"type": "text",
-										"value": "Bearer wrongToken"
-									}
-								],
-								"body": {
-									"mode": "raw",
-									"raw": "{\n   \"client_name\": \"Should have not been updated\"\n}"
-								},
-								"url": {
-									"raw": "{{registrationClientUri}}",
-									"host": [
-										"{{registrationClientUri}}"
-									]
-								}
-							},
-							"response": []
-						},
-						{
-							"name": "Invalid redirect uri",
+							"name": "duplicate jwk and jwks_uri",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
-										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"id": "c557fd6b-d770-4568-8db7-ccb3267b0256",
 										"exec": [
 											"pm.test(\"Status code is 400\", function () {",
 											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Redirect uris are missing\", function () {",
+											"pm.test(\"Invalid scope\", function () {",
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
-											"    pm.expect(body.error).to.eql('invalid_redirect_uri');",
-											"    pm.expect(body.error_description).to.eql('Missing or invalid redirect_uris.');",
+											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
+											"    pm.expect(body.error_description).to.be.eql('The jwks_uri and jwks parameters MUST NOT be used together.');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -2762,7 +2681,7 @@
 								}
 							],
 							"request": {
-								"method": "PUT",
+								"method": "POST",
 								"header": [
 									{
 										"key": "Content-Type",
@@ -2772,89 +2691,76 @@
 									{
 										"key": "Authorization",
 										"type": "text",
-										"value": "Bearer {{registrationAccessToken}}"
+										"value": "Bearer {{access_token}}"
 									}
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n   \"client_name\": \"Should have not been updated\"\n}\n"
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n  \"client_name\": \"My Example Client\",\n   \"jwks_uri\": \"https://unbound/uri\",\n   \"jwks\": {\n        \"keys\": [\n\t\t\t{  \n                \"kty\": \"EC\",\n                \"use\": \"sig\",\n                \"crv\": \"P-256\",\n                \"kid\": \"elliptic-curve-signature\",\n                \"x\": \"R4JmPwezbzLuyGkonWIkezzplUfed5b6F5PL4j0zdf8\",\n                \"y\": \"QQRGKwRV9jHSlHjUhOQ0FqdQEddFBPCHZXpoFjvGmcY\"\n\t\t\t}\n        ]\n    }\n}"
 								},
 								"url": {
-									"raw": "{{registrationClientUri}}",
+									"raw": "{{registrationEndpoint}}",
 									"host": [
-										"{{registrationClientUri}}"
+										"{{registrationEndpoint}}"
 									]
 								}
 							},
 							"response": []
-						},
+						}
+					],
+					"event": [
 						{
-							"name": "Invalid redirect uri - can not be empty",
-							"event": [
-								{
-									"listen": "test",
-									"script": {
-										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
-										"exec": [
-											"pm.test(\"Status code is 400\", function () {",
-											"    pm.response.to.have.status(400);",
-											"});",
-											"",
-											"pm.test(\"Redirect uris are missing\", function () {",
-											"    pm.response.to.be.header('Content-Type', 'application/json');",
-											"    var body = pm.response.json();",
-											"    pm.expect(body.error).to.eql('invalid_redirect_uri');",
-											"    pm.expect(body.error_description).to.eql('Missing or invalid redirect_uris.');",
-											"});"
-										],
-										"type": "text/javascript"
-									}
-								}
-							],
-							"request": {
-								"method": "PATCH",
-								"header": [
-									{
-										"key": "Content-Type",
-										"type": "text",
-										"value": "application/json"
-									},
-									{
-										"key": "Authorization",
-										"type": "text",
-										"value": "Bearer {{registrationAccessToken}}"
-									}
-								],
-								"body": {
-									"mode": "raw",
-									"raw": "{\n   \"client_name\": \"Client with implicit flow should not allow empty redirect_uris\",\n   \"grant_types\": [\"implicit\"],\n   \"response_types\": [\"token\"],\n   \"redirect_uris\": []\n}\n"
-								},
-								"url": {
-									"raw": "{{registrationClientUri}}",
-									"host": [
-										"{{registrationClientUri}}"
-									]
-								}
-							},
-							"response": []
+							"listen": "prerequest",
+							"script": {
+								"id": "6344fd45-5776-4bab-a90c-033893e6debb",
+								"type": "text/javascript",
+								"exec": [
+									""
+								]
+							}
 						},
 						{
-							"name": "Invalid redirect uri - localhost",
+							"listen": "test",
+							"script": {
+								"id": "03904ca6-6d82-43ab-8190-f3210787a262",
+								"type": "text/javascript",
+								"exec": [
+									""
+								]
+							}
+						}
+					],
+					"_postman_isSubFolder": true
+				},
+				{
+					"name": "Invalid update requests",
+					"item": [
+						{
+							"name": "Register client",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
 										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
 										"exec": [
-											"pm.test(\"Status code is 400\", function () {",
-											"    pm.response.to.have.status(400);",
+											"pm.test(\"Status code is 201\", function () {",
+											"    pm.response.to.have.status(201);",
 											"});",
 											"",
-											"pm.test(\"Redirect uris localhost forbidden\", function () {",
-											"    pm.response.to.be.header('Content-Type', 'application/json');",
+											"pm.test(\"Has default attributes\", function () {",
 											"    var body = pm.response.json();",
-											"    pm.expect(body.error).to.eql('invalid_redirect_uri');",
-											"    pm.expect(body.error_description).to.eql('localhost is forbidden');",
+											"    pm.expect(body).to.have.property('response_types');",
+											"    pm.expect(body).to.have.property('grant_types');",
+											"    pm.expect(body).to.have.property('client_name');",
+											"    pm.expect(body).to.have.property('client_id');",
+											"    pm.expect(body).to.have.property('client_secret');",
+											"    pm.expect(body.response_types).to.eql(['code']);",
+											"    pm.expect(body.grant_types).to.eql(['authorization_code']);",
+											"    pm.expect(body.client_name).to.eql('Unknown Client');",
+											"    ",
+											"    pm.environment.set('newClientForDCRTests', body.id);",
+											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
 											"});"
 										],
 										"type": "text/javascript"
@@ -2862,7 +2768,7 @@
 								}
 							],
 							"request": {
-								"method": "PUT",
+								"method": "POST",
 								"header": [
 									{
 										"key": "Content-Type",
@@ -2872,39 +2778,39 @@
 									{
 										"key": "Authorization",
 										"type": "text",
-										"value": "Bearer {{registrationAccessToken}}"
+										"value": "Bearer {{access_token}}"
 									}
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{  \"redirect_uris\": [\n    \"https://localhost/callback\",\n    \"https://localhost/callback2\"\n   ],\n   \"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n   \"application_type\": \"web\",\n   \"redirect_uris\":\n     [\"https://client.example.org/callback\",\n      \"https://client.example.org/callback2\"],\n   \"logo_uri\": \"https://client.example.org/logo.png\",\n   \"token_endpoint_auth_method\": \"client_secret_basic\",\n   \"userinfo_encrypted_response_alg\": \"RSA-OAEP-256\",\n   \"userinfo_encrypted_response_enc\": \"A128CBC-HS256\",\n   \"contacts\": [\"ve7jtb@example.org\", \"mary@example.org\"],\n   \"request_uris\":\n     [\"https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA\"]\n  }"
 								},
 								"url": {
-									"raw": "{{registrationClientUri}}",
+									"raw": "{{registrationEndpoint}}",
 									"host": [
-										"{{registrationClientUri}}"
+										"{{registrationEndpoint}}"
 									]
 								}
 							},
 							"response": []
 						},
 						{
-							"name": "Invalid response type",
+							"name": "Invalid access token",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
 										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
 										"exec": [
-											"pm.test(\"Status code is 400\", function () {",
-											"    pm.response.to.have.status(400);",
+											"pm.test(\"Status code is 401\", function () {",
+											"    pm.response.to.have.status(401);",
 											"});",
 											"",
-											"pm.test(\"Invalid response type\", function () {",
+											"pm.test(\"Invalid bearer\", function () {",
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
-											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('Invalid response type.');",
+											"    pm.expect(body.error).to.eql('invalid_token');",
+											"    pm.expect(body.error_description).to.eql('The access token is invalid');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -2922,12 +2828,12 @@
 									{
 										"key": "Authorization",
 										"type": "text",
-										"value": "Bearer {{registrationAccessToken}}"
+										"value": "Bearer wrongToken"
 									}
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n  \"response_types\": [\n\t\"unknown\"\n   ],\n   \"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n   \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -2939,7 +2845,7 @@
 							"response": []
 						},
 						{
-							"name": "Invalid grant type",
+							"name": "Invalid redirect uri",
 							"event": [
 								{
 									"listen": "test",
@@ -2950,11 +2856,11 @@
 											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Invalid grant type\", function () {",
+											"pm.test(\"Redirect uris are missing\", function () {",
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
-											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('Missing or invalid grant type.');",
+											"    pm.expect(body.error).to.eql('invalid_redirect_uri');",
+											"    pm.expect(body.error_description).to.eql('Missing or invalid redirect_uris.');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -2977,7 +2883,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n  \"grant_types\": [\n\t\"unknown\"\n   ],\n   \"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n   \"client_name\": \"Should have not been updated\"\n}\n"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -2989,7 +2895,7 @@
 							"response": []
 						},
 						{
-							"name": "Invalid grant type - refresh_token alone",
+							"name": "Invalid redirect uri - can not be empty",
 							"event": [
 								{
 									"listen": "test",
@@ -3000,11 +2906,11 @@
 											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Invalid grant type\", function () {",
+											"pm.test(\"Redirect uris are missing\", function () {",
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
-											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.include('refresh_token grant type must be associated with one of');",
+											"    pm.expect(body.error).to.eql('invalid_redirect_uri');",
+											"    pm.expect(body.error_description).to.eql('Missing or invalid redirect_uris.');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3012,7 +2918,7 @@
 								}
 							],
 							"request": {
-								"method": "PUT",
+								"method": "PATCH",
 								"header": [
 									{
 										"key": "Content-Type",
@@ -3027,7 +2933,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n  \"redirect_uris\": [],\n  \"response_types\": [],\n  \"grant_types\": [\"refresh_token\"],\n  \"client_name\": \"My Example Client\",\n  \"token_endpoint_auth_method\": \"client_secret_basic\",\n  \"logo_uri\": \"https://client.example.org/logo.png\"\n}"
+									"raw": "{\n   \"client_name\": \"Client with implicit flow should not allow empty redirect_uris\",\n   \"grant_types\": [\"implicit\"],\n   \"response_types\": [\"token\"],\n   \"redirect_uris\": []\n}\n"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3039,7 +2945,7 @@
 							"response": []
 						},
 						{
-							"name": "Invalid subject  type",
+							"name": "Invalid redirect uri - localhost",
 							"event": [
 								{
 									"listen": "test",
@@ -3050,11 +2956,11 @@
 											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Invalid grant type\", function () {",
+											"pm.test(\"Redirect uris localhost forbidden\", function () {",
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
-											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('Unsupported subject type');",
+											"    pm.expect(body.error).to.eql('invalid_redirect_uri');",
+											"    pm.expect(body.error_description).to.eql('localhost is forbidden');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3077,7 +2983,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"subject_type\": \"pairwise\",\n   \"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{  \"redirect_uris\": [\n    \"https://localhost/callback\",\n    \"https://localhost/callback2\"\n   ],\n   \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3089,7 +2995,7 @@
 							"response": []
 						},
 						{
-							"name": "Invalid userinfo signing algorithm",
+							"name": "Invalid response type",
 							"event": [
 								{
 									"listen": "test",
@@ -3104,7 +3010,7 @@
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
 											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('Unsupported userinfo signing algorithm');",
+											"    pm.expect(body.error_description).to.eql('Invalid response type.');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3127,7 +3033,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"userinfo_signed_response_alg\":\"unknown\",\n   \"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n  \"response_types\": [\n\t\"unknown\"\n   ],\n   \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3139,7 +3045,7 @@
 							"response": []
 						},
 						{
-							"name": "Missing userinfo response alg",
+							"name": "Invalid grant type",
 							"event": [
 								{
 									"listen": "test",
@@ -3154,7 +3060,7 @@
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
 											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('When userinfo_encrypted_response_enc is included, userinfo_encrypted_response_alg MUST also be provided');",
+											"    pm.expect(body.error_description).to.eql('Missing or invalid grant type.');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3172,12 +3078,12 @@
 									{
 										"key": "Authorization",
 										"type": "text",
-										"value": "Bearer {{access_token}}"
+										"value": "Bearer {{registrationAccessToken}}"
 									}
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"userinfo_encrypted_response_enc\":\"unknown\",\n   \"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n  \"grant_types\": [\n\t\"unknown\"\n   ],\n   \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3189,7 +3095,7 @@
 							"response": []
 						},
 						{
-							"name": "Invalid userinfo response enc",
+							"name": "Invalid grant type - refresh_token alone",
 							"event": [
 								{
 									"listen": "test",
@@ -3204,7 +3110,7 @@
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
 											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('Unsupported userinfo_encrypted_response_enc value');",
+											"    pm.expect(body.error_description).to.include('refresh_token grant type must be associated with one of');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3222,12 +3128,12 @@
 									{
 										"key": "Authorization",
 										"type": "text",
-										"value": "Bearer {{access_token}}"
+										"value": "Bearer {{registrationAccessToken}}"
 									}
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n\t\"redirect_uris\": [\n    \t\"https://client.example.org/callback\",\n    \t\"https://client.example.org/callback2\"],\n\t\"userinfo_encrypted_response_alg\":\"RSA-OAEP-256\",\n\t\"userinfo_encrypted_response_enc\":\"unknown\",\n\t\"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n  \"redirect_uris\": [],\n  \"response_types\": [],\n  \"grant_types\": [\"refresh_token\"],\n  \"client_name\": \"My Example Client\",\n  \"token_endpoint_auth_method\": \"client_secret_basic\",\n  \"logo_uri\": \"https://client.example.org/logo.png\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3239,7 +3145,7 @@
 							"response": []
 						},
 						{
-							"name": "Invalid id_token signing algorithm",
+							"name": "Invalid subject  type",
 							"event": [
 								{
 									"listen": "test",
@@ -3250,11 +3156,11 @@
 											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Invalid response type\", function () {",
+											"pm.test(\"Invalid grant type\", function () {",
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
 											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('Unsupported id_token signing algorithm');",
+											"    pm.expect(body.error_description).to.eql('Unsupported subject type');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3277,7 +3183,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"id_token_signed_response_alg\":\"unknown\",\n   \"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"subject_type\": \"pairwise\",\n   \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3289,7 +3195,7 @@
 							"response": []
 						},
 						{
-							"name": "Missing id_token response alg",
+							"name": "Invalid userinfo signing algorithm",
 							"event": [
 								{
 									"listen": "test",
@@ -3300,11 +3206,11 @@
 											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Invalid grant type\", function () {",
+											"pm.test(\"Invalid response type\", function () {",
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
 											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('When id_token_encrypted_response_enc is included, id_token_encrypted_response_alg MUST also be provided');",
+											"    pm.expect(body.error_description).to.eql('Unsupported userinfo signing algorithm');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3322,12 +3228,12 @@
 									{
 										"key": "Authorization",
 										"type": "text",
-										"value": "Bearer {{access_token}}"
+										"value": "Bearer {{registrationAccessToken}}"
 									}
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"id_token_encrypted_response_enc\":\"unknown\",\n   \"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"userinfo_signed_response_alg\":\"unknown\",\n   \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3339,7 +3245,7 @@
 							"response": []
 						},
 						{
-							"name": "Invalid id_token response alg",
+							"name": "Missing userinfo response alg",
 							"event": [
 								{
 									"listen": "test",
@@ -3354,7 +3260,7 @@
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
 											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('Unsupported id_token_encrypted_response_alg value');",
+											"    pm.expect(body.error_description).to.eql('When userinfo_encrypted_response_enc is included, userinfo_encrypted_response_alg MUST also be provided');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3377,7 +3283,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"id_token_encrypted_response_alg\":\"unknown\",\n   \"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"userinfo_encrypted_response_enc\":\"unknown\",\n   \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3389,7 +3295,7 @@
 							"response": []
 						},
 						{
-							"name": "Invalid id_token response enc",
+							"name": "Invalid userinfo response enc",
 							"event": [
 								{
 									"listen": "test",
@@ -3404,7 +3310,7 @@
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
 											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('Unsupported id_token_encrypted_response_enc value');",
+											"    pm.expect(body.error_description).to.eql('Unsupported userinfo_encrypted_response_enc value');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3427,7 +3333,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n\t\"redirect_uris\": [\n    \t\"https://client.example.org/callback\",\n    \t\"https://client.example.org/callback2\"],\n\t\"id_token_encrypted_response_alg\":\"RSA-OAEP-256\",\n\t\"id_token_encrypted_response_enc\":\"unknown\",\n\t\"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n\t\"redirect_uris\": [\n    \t\"https://client.example.org/callback\",\n    \t\"https://client.example.org/callback2\"],\n\t\"userinfo_encrypted_response_alg\":\"RSA-OAEP-256\",\n\t\"userinfo_encrypted_response_enc\":\"unknown\",\n\t\"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3439,7 +3345,7 @@
 							"response": []
 						},
 						{
-							"name": "Invalid scope",
+							"name": "Invalid id_token signing algorithm",
 							"event": [
 								{
 									"listen": "test",
@@ -3450,11 +3356,11 @@
 											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Invalid scope\", function () {",
+											"pm.test(\"Invalid response type\", function () {",
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
 											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
-											"    pm.expect(body.error_description).to.eql('scope unkown-domain-scope is not valid.');",
+											"    pm.expect(body.error_description).to.eql('Unsupported id_token signing algorithm');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3477,7 +3383,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n  \"scope\": \"unkown-domain-scope\",\n  \"client_name\": \"Should have not been updated\"\n}"
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"id_token_signed_response_alg\":\"unknown\",\n   \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3489,24 +3395,30 @@
 							"response": []
 						},
 						{
-							"name": "Delete client - with registration token",
+							"name": "Missing id_token response alg",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
 										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
 										"exec": [
-											"pm.test(\"Status code is 204\", function () {",
-											"    pm.response.to.have.status(204);",
+											"pm.test(\"Status code is 400\", function () {",
+											"    pm.response.to.have.status(400);",
 											"});",
-											""
+											"",
+											"pm.test(\"Invalid grant type\", function () {",
+											"    pm.response.to.be.header('Content-Type', 'application/json');",
+											"    var body = pm.response.json();",
+											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
+											"    pm.expect(body.error_description).to.eql('When id_token_encrypted_response_enc is included, id_token_encrypted_response_alg MUST also be provided');",
+											"});"
 										],
 										"type": "text/javascript"
 									}
 								}
 							],
 							"request": {
-								"method": "DELETE",
+								"method": "PUT",
 								"header": [
 									{
 										"key": "Content-Type",
@@ -3516,12 +3428,12 @@
 									{
 										"key": "Authorization",
 										"type": "text",
-										"value": "Bearer {{registrationAccessToken}}"
+										"value": "Bearer {{access_token}}"
 									}
 								],
 								"body": {
 									"mode": "raw",
-									"raw": ""
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"id_token_encrypted_response_enc\":\"unknown\",\n   \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3531,48 +3443,24 @@
 								}
 							},
 							"response": []
-						}
-					],
-					"_postman_isSubFolder": true
-				}
-			]
-		},
-		{
-			"name": "Case - Nominal",
-			"item": [
-				{
-					"name": "web application",
-					"item": [
+						},
 						{
-							"name": "Register client - web application",
+							"name": "Invalid id_token response alg",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
 										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
 										"exec": [
-											"pm.test(\"Status code is 201\", function () {",
-											"    pm.response.to.have.status(201);",
+											"pm.test(\"Status code is 400\", function () {",
+											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Has default attributes\", function () {",
+											"pm.test(\"Invalid grant type\", function () {",
+											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
-											"    pm.expect(body).to.have.property('application_type');",
-											"    pm.expect(body).to.have.property('response_types');",
-											"    pm.expect(body).to.have.property('grant_types');",
-											"    pm.expect(body).to.have.property('client_name');",
-											"    pm.expect(body).to.have.property('client_id');",
-											"    pm.expect(body).to.have.property('client_secret');",
-											"    pm.expect(body.application_type).to.eql('web');",
-											"    pm.expect(body.response_types).to.eql(['code']);",
-											"    pm.expect(body.grant_types).to.eql(['authorization_code']);",
-											"    pm.expect(body.client_name).to.eql('Unknown Client');",
-											"    ",
-											"    pm.environment.set('newClientForDCRTests', body.id);",
-											"    pm.environment.set('newClientIdForDCRTests', body.client_id);",
-											"    pm.environment.set('newClientSecretForDCRTests', body.client_secret);",
-											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
-											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
+											"    pm.expect(body.error_description).to.eql('Unsupported id_token_encrypted_response_alg value');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3580,7 +3468,7 @@
 								}
 							],
 							"request": {
-								"method": "POST",
+								"method": "PUT",
 								"header": [
 									{
 										"key": "Content-Type",
@@ -3595,41 +3483,34 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n   \"redirect_uris\":\n     [\"https://client.example.org/callback\",\n      \"https://client.example.org/callback2\"],\n   \"logo_uri\": \"https://client.example.org/logo.png\",\n   \"subject_type\": \"public\",\n   \"token_endpoint_auth_method\": \"client_secret_basic\",\n   \"userinfo_encrypted_response_alg\": \"RSA-OAEP-256\",\n   \"userinfo_encrypted_response_enc\": \"A128CBC-HS256\",\n   \"contacts\": [\"ve7jtb@example.org\", \"mary@example.org\"],\n   \"request_uris\":\n     [\"https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA\"]\n  }"
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n   \"id_token_encrypted_response_alg\":\"unknown\",\n   \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
-									"raw": "{{registrationEndpoint}}",
+									"raw": "{{registrationClientUri}}",
 									"host": [
-										"{{registrationEndpoint}}"
+										"{{registrationClientUri}}"
 									]
 								}
 							},
 							"response": []
 						},
 						{
-							"name": "Get client - with registration token",
+							"name": "Invalid id_token response enc",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
 										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
 										"exec": [
-											"pm.test(\"Status code is 200\", function () {",
-											"    pm.response.to.have.status(200);",
+											"pm.test(\"Status code is 400\", function () {",
+											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Get client with response types\", function () {",
+											"pm.test(\"Invalid grant type\", function () {",
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
-											"    pm.expect(body).to.have.property(\"redirect_uris\");",
-											"    pm.expect(body).to.have.property(\"grant_types\");",
-											"    pm.expect(body.response_types).to.eql([ 'code' ]);",
-											"    pm.expect(body.grant_types).to.eql([ 'authorization_code' ]);",
-											"    pm.expect(body.client_name).to.eql('Unknown Client');",
-											"    ",
-											"    //The Authorization Server need not include the registration_access_token or registration_client_uri value in this response unless they have been updated.",
-											"    pm.expect(body).to.not.have.property('registration_access_token');",
-											"    pm.expect(body).to.not.have.property('registration_client_uri');",
+											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
+											"    pm.expect(body.error_description).to.eql('Unsupported id_token_encrypted_response_enc value');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3637,7 +3518,7 @@
 								}
 							],
 							"request": {
-								"method": "GET",
+								"method": "PUT",
 								"header": [
 									{
 										"key": "Content-Type",
@@ -3647,12 +3528,12 @@
 									{
 										"key": "Authorization",
 										"type": "text",
-										"value": "Bearer {{registrationAccessToken}}"
+										"value": "Bearer {{access_token}}"
 									}
 								],
 								"body": {
 									"mode": "raw",
-									"raw": ""
+									"raw": "{\n\t\"redirect_uris\": [\n    \t\"https://client.example.org/callback\",\n    \t\"https://client.example.org/callback2\"],\n\t\"id_token_encrypted_response_alg\":\"RSA-OAEP-256\",\n\t\"id_token_encrypted_response_enc\":\"unknown\",\n\t\"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3664,32 +3545,22 @@
 							"response": []
 						},
 						{
-							"name": "Patch client - with registration token",
+							"name": "Invalid scope",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
 										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
 										"exec": [
-											"pm.test(\"Status code is 200\", function () {",
-											"    pm.response.to.have.status(200);",
+											"pm.test(\"Status code is 400\", function () {",
+											"    pm.response.to.have.status(400);",
 											"});",
 											"",
-											"pm.test(\"Get client with response types\", function () {",
+											"pm.test(\"Invalid scope\", function () {",
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
-											"    pm.expect(body.client_name).to.eql('Client patched via DCR');",
-											"    pm.expect(body).to.have.property(\"response_types\");",
-											"    pm.expect(body.response_types).to.eql(['token', 'code', 'code id_token']);",
-											"    pm.expect(body.grant_types).to.eql([ 'implicit','authorization_code' ]);",
-											"});",
-											"",
-											"pm.test(\"One time Token\", function() {",
-											"    var body = pm.response.json();",
-											"    pm.expect(body).to.have.property('registration_access_token');",
-											"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
-											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
-											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+											"    pm.expect(body.error).to.eql('invalid_client_metadata');",
+											"    pm.expect(body.error_description).to.eql('scope unkown-domain-scope is not valid.');",
 											"});"
 										],
 										"type": "text/javascript"
@@ -3697,7 +3568,7 @@
 								}
 							],
 							"request": {
-								"method": "PATCH",
+								"method": "PUT",
 								"header": [
 									{
 										"key": "Content-Type",
@@ -3712,7 +3583,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n   \"client_name\": \"Client patched via DCR\",\n   \"response_types\" : [\"token\", \"code\", \"code id_token\"]\n}"
+									"raw": "{\n  \"redirect_uris\": [\n    \"https://client.example.org/callback\",\n    \"https://client.example.org/callback2\"],\n  \"scope\": \"unkown-domain-scope\",\n  \"client_name\": \"Should have not been updated\"\n}"
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3724,39 +3595,24 @@
 							"response": []
 						},
 						{
-							"name": "Update client - with registration token",
+							"name": "Delete client - with registration token",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
 										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
 										"exec": [
-											"pm.test(\"Status code is 200\", function () {",
-											"    pm.response.to.have.status(200);",
-											"});",
-											"",
-											"pm.test(\"Get client with response types\", function () {",
-											"    pm.response.to.be.header('Content-Type', 'application/json');",
-											"    var body = pm.response.json();",
-											"    pm.expect(body.client_name).to.eql('Client name updated via DCR');",
-											"    pm.expect(body).to.have.property(\"response_types\");",
-											"    pm.expect(body.response_types).to.eql(['code']);",
+											"pm.test(\"Status code is 204\", function () {",
+											"    pm.response.to.have.status(204);",
 											"});",
-											"",
-											"pm.test(\"One time Token\", function() {",
-											"    var body = pm.response.json();",
-											"    pm.expect(body).to.have.property('registration_access_token');",
-											"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
-											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
-											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
-											"});"
+											""
 										],
 										"type": "text/javascript"
 									}
 								}
 							],
 							"request": {
-								"method": "PUT",
+								"method": "DELETE",
 								"header": [
 									{
 										"key": "Content-Type",
@@ -3771,7 +3627,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n    \"redirect_uris\": [\n        \"https://client.example.org/callback\",\n        \"https://client.example.org/callback2\"\n    ],\n    \"response_types\": [\n        \"code\"\n    ],\n    \"grant_types\": [\n        \"authorization_code\"\n    ],\n    \"application_type\": \"web\",\n    \"contacts\": [\n        \"marie@example.org\",\n        \"jeanne@example.org\"\n    ],\n\t\"client_name\": \"Client name updated via DCR\",\n    \"logo_uri\": \"https://client.example.org/logo.png\",\n    \"subject_type\": \"public\",\n    \"userinfo_encrypted_response_alg\": \"RSA-OAEP-256\",\n    \"userinfo_encrypted_response_enc\": \"A128CBC-HS256\",\n    \"token_endpoint_auth_method\": \"client_secret_basic\",\n    \"require_auth_time\": false,\n    \"request_uris\": [\n        \"https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA\"\n    ],\n    \"scope\": \"openid\"\n}"
+									"raw": ""
 								},
 								"url": {
 									"raw": "{{registrationClientUri}}",
@@ -3781,30 +3637,46 @@
 								}
 							},
 							"response": []
-						},
+						}
+					],
+					"_postman_isSubFolder": true
+				}
+			]
+		},
+		{
+			"name": "Case - Nominal",
+			"item": [
+				{
+					"name": "web application",
+					"item": [
 						{
-							"name": "Renew client secret - with registration token",
+							"name": "Register client - web application",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
 										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
 										"exec": [
-											"pm.test(\"Status code is 200\", function () {",
-											"    pm.response.to.have.status(200);",
-											"});",
-											"",
-											"pm.test(\"Get client with response types\", function () {",
-											"    pm.response.to.be.header('Content-Type', 'application/json');",
-											"    var body = pm.response.json();",
-											"    pm.expect(body.client_id).to.eql(pm.environment.get('newClientIdForDCRTests'));",
-											"    pm.expect(body.client_secret).to.not.eql(pm.environment.get('newClientSecretForDCRTests'));",
+											"pm.test(\"Status code is 201\", function () {",
+											"    pm.response.to.have.status(201);",
 											"});",
 											"",
-											"pm.test(\"One time Token\", function() {",
+											"pm.test(\"Has default attributes\", function () {",
 											"    var body = pm.response.json();",
-											"    pm.expect(body).to.have.property('registration_access_token');",
-											"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+											"    pm.expect(body).to.have.property('application_type');",
+											"    pm.expect(body).to.have.property('response_types');",
+											"    pm.expect(body).to.have.property('grant_types');",
+											"    pm.expect(body).to.have.property('client_name');",
+											"    pm.expect(body).to.have.property('client_id');",
+											"    pm.expect(body).to.have.property('client_secret');",
+											"    pm.expect(body.application_type).to.eql('web');",
+											"    pm.expect(body.response_types).to.eql(['code']);",
+											"    pm.expect(body.grant_types).to.eql(['authorization_code']);",
+											"    pm.expect(body.client_name).to.eql('Unknown Client');",
+											"    ",
+											"    pm.environment.set('newClientForDCRTests', body.id);",
+											"    pm.environment.set('newClientIdForDCRTests', body.client_id);",
+											"    pm.environment.set('newClientSecretForDCRTests', body.client_secret);",
 											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
 											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
 											"});"
@@ -3824,44 +3696,282 @@
 									{
 										"key": "Authorization",
 										"type": "text",
-										"value": "Bearer {{registrationAccessToken}}"
+										"value": "Bearer {{access_token}}"
 									}
 								],
 								"body": {
 									"mode": "raw",
-									"raw": ""
+									"raw": "{\n   \"redirect_uris\":\n     [\"https://client.example.org/callback\",\n      \"https://client.example.org/callback2\"],\n   \"logo_uri\": \"https://client.example.org/logo.png\",\n   \"subject_type\": \"public\",\n   \"token_endpoint_auth_method\": \"client_secret_basic\",\n   \"userinfo_encrypted_response_alg\": \"RSA-OAEP-256\",\n   \"userinfo_encrypted_response_enc\": \"A128CBC-HS256\",\n   \"contacts\": [\"ve7jtb@example.org\", \"mary@example.org\"],\n   \"request_uris\":\n     [\"https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA\"]\n  }"
 								},
 								"url": {
-									"raw": "{{registrationClientUri}}/renew_secret",
+									"raw": "{{registrationEndpoint}}",
 									"host": [
-										"{{registrationClientUri}}"
-									],
-									"path": [
-										"renew_secret"
+										"{{registrationEndpoint}}"
 									]
 								}
 							},
 							"response": []
 						},
 						{
-							"name": "Delete client - with registration token",
+							"name": "Get client - with registration token",
 							"event": [
 								{
 									"listen": "test",
 									"script": {
 										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
 										"exec": [
-											"pm.test(\"Status code is 204\", function () {",
-											"    pm.response.to.have.status(204);",
+											"pm.test(\"Status code is 200\", function () {",
+											"    pm.response.to.have.status(200);",
 											"});",
-											""
+											"",
+											"pm.test(\"Get client with response types\", function () {",
+											"    pm.response.to.be.header('Content-Type', 'application/json');",
+											"    var body = pm.response.json();",
+											"    pm.expect(body).to.have.property(\"redirect_uris\");",
+											"    pm.expect(body).to.have.property(\"grant_types\");",
+											"    pm.expect(body.response_types).to.eql([ 'code' ]);",
+											"    pm.expect(body.grant_types).to.eql([ 'authorization_code' ]);",
+											"    pm.expect(body.client_name).to.eql('Unknown Client');",
+											"    ",
+											"    //The Authorization Server need not include the registration_access_token or registration_client_uri value in this response unless they have been updated.",
+											"    pm.expect(body).to.not.have.property('registration_access_token');",
+											"    pm.expect(body).to.not.have.property('registration_client_uri');",
+											"});"
 										],
 										"type": "text/javascript"
 									}
 								}
 							],
 							"request": {
-								"method": "DELETE",
+								"method": "GET",
+								"header": [
+									{
+										"key": "Content-Type",
+										"type": "text",
+										"value": "application/json"
+									},
+									{
+										"key": "Authorization",
+										"type": "text",
+										"value": "Bearer {{registrationAccessToken}}"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": ""
+								},
+								"url": {
+									"raw": "{{registrationClientUri}}",
+									"host": [
+										"{{registrationClientUri}}"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Patch client - with registration token",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"exec": [
+											"pm.test(\"Status code is 200\", function () {",
+											"    pm.response.to.have.status(200);",
+											"});",
+											"",
+											"pm.test(\"Get client with response types\", function () {",
+											"    pm.response.to.be.header('Content-Type', 'application/json');",
+											"    var body = pm.response.json();",
+											"    pm.expect(body.client_name).to.eql('Client patched via DCR');",
+											"    pm.expect(body).to.have.property(\"response_types\");",
+											"    pm.expect(body.response_types).to.eql(['token', 'code', 'code id_token']);",
+											"    pm.expect(body.grant_types).to.eql([ 'implicit','authorization_code' ]);",
+											"});",
+											"",
+											"pm.test(\"One time Token\", function() {",
+											"    var body = pm.response.json();",
+											"    pm.expect(body).to.have.property('registration_access_token');",
+											"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "PATCH",
+								"header": [
+									{
+										"key": "Content-Type",
+										"type": "text",
+										"value": "application/json"
+									},
+									{
+										"key": "Authorization",
+										"type": "text",
+										"value": "Bearer {{registrationAccessToken}}"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n   \"client_name\": \"Client patched via DCR\",\n   \"response_types\" : [\"token\", \"code\", \"code id_token\"]\n}"
+								},
+								"url": {
+									"raw": "{{registrationClientUri}}",
+									"host": [
+										"{{registrationClientUri}}"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Update client - with registration token",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"exec": [
+											"pm.test(\"Status code is 200\", function () {",
+											"    pm.response.to.have.status(200);",
+											"});",
+											"",
+											"pm.test(\"Get client with response types\", function () {",
+											"    pm.response.to.be.header('Content-Type', 'application/json');",
+											"    var body = pm.response.json();",
+											"    pm.expect(body.client_name).to.eql('Client name updated via DCR');",
+											"    pm.expect(body).to.have.property(\"response_types\");",
+											"    pm.expect(body.response_types).to.eql(['code']);",
+											"});",
+											"",
+											"pm.test(\"One time Token\", function() {",
+											"    var body = pm.response.json();",
+											"    pm.expect(body).to.have.property('registration_access_token');",
+											"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "PUT",
+								"header": [
+									{
+										"key": "Content-Type",
+										"type": "text",
+										"value": "application/json"
+									},
+									{
+										"key": "Authorization",
+										"type": "text",
+										"value": "Bearer {{registrationAccessToken}}"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n    \"redirect_uris\": [\n        \"https://client.example.org/callback\",\n        \"https://client.example.org/callback2\"\n    ],\n    \"response_types\": [\n        \"code\"\n    ],\n    \"grant_types\": [\n        \"authorization_code\"\n    ],\n    \"application_type\": \"web\",\n    \"contacts\": [\n        \"marie@example.org\",\n        \"jeanne@example.org\"\n    ],\n\t\"client_name\": \"Client name updated via DCR\",\n    \"logo_uri\": \"https://client.example.org/logo.png\",\n    \"subject_type\": \"public\",\n    \"userinfo_encrypted_response_alg\": \"RSA-OAEP-256\",\n    \"userinfo_encrypted_response_enc\": \"A128CBC-HS256\",\n    \"token_endpoint_auth_method\": \"client_secret_basic\",\n    \"require_auth_time\": false,\n    \"request_uris\": [\n        \"https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA\"\n    ],\n    \"scope\": \"openid\"\n}"
+								},
+								"url": {
+									"raw": "{{registrationClientUri}}",
+									"host": [
+										"{{registrationClientUri}}"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Renew client secret - with registration token",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"exec": [
+											"pm.test(\"Status code is 200\", function () {",
+											"    pm.response.to.have.status(200);",
+											"});",
+											"",
+											"pm.test(\"Get client with response types\", function () {",
+											"    pm.response.to.be.header('Content-Type', 'application/json');",
+											"    var body = pm.response.json();",
+											"    pm.expect(body.client_id).to.eql(pm.environment.get('newClientIdForDCRTests'));",
+											"    pm.expect(body.client_secret).to.not.eql(pm.environment.get('newClientSecretForDCRTests'));",
+											"",
+											"    let renewSecretEndpoint = pm.environment.get('registrationClientUri')+'/renew_secret';",
+											"    let discoveryRenewSecret = pm.environment.get('registrationRenewSecretEndpoint').replace(':client_id',pm.environment.get('newClientIdForDCRTests'));",
+											"    pm.expect(renewSecretEndpoint).to.be.eql(discoveryRenewSecret);",
+											"});",
+											"",
+											"pm.test(\"One time Token\", function() {",
+											"    var body = pm.response.json();",
+											"    pm.expect(body).to.have.property('registration_access_token');",
+											"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"type": "text",
+										"value": "application/json"
+									},
+									{
+										"key": "Authorization",
+										"type": "text",
+										"value": "Bearer {{registrationAccessToken}}"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": ""
+								},
+								"url": {
+									"raw": "{{registrationClientUri}}/renew_secret",
+									"host": [
+										"{{registrationClientUri}}"
+									],
+									"path": [
+										"renew_secret"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Delete client - with registration token",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"exec": [
+											"pm.test(\"Status code is 204\", function () {",
+											"    pm.response.to.have.status(204);",
+											"});",
+											""
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "DELETE",
 								"header": [
 									{
 										"key": "Content-Type",
@@ -3916,7 +4026,7 @@
 											"    pm.expect(body.response_types).to.eql([]);",
 											"    pm.expect(body.application_type).to.eql('server');",
 											"    pm.expect(body.grant_types).to.eql(['client_credentials']);",
-											"    pm.expect(body.client_name).to.eql('Unknown Client');",
+											"    pm.expect(body.client_name).to.eql('machina');",
 											"    ",
 											"    pm.environment.set('newClientForDCRTests', body.id);",
 											"    pm.environment.set('newClientIdForDCRTests', body.client_id);",
@@ -3945,7 +4055,7 @@
 								],
 								"body": {
 									"mode": "raw",
-									"raw": "{\n\t\"application_type\": \"server\",\n\t\"redirect_uris\": null,\n\t\"grant_types\": [\"client_credentials\"],\n\t\"response_types\": null\n}"
+									"raw": "{\n\t\"application_type\": \"server\",\n\t\"redirect_uris\": null,\n\t\"grant_types\": [\"client_credentials\"],\n\t\"response_types\": [],\n\t\"client_name\":\"machina\",\n\t\"scope\":null\n}"
 								},
 								"url": {
 									"raw": "{{registrationEndpoint}}",
@@ -4137,8 +4247,7 @@
 											"    pm.response.to.be.header('Content-Type', 'application/json');",
 											"    var body = pm.response.json();",
 											"    pm.expect(body.client_name).to.eql('Client name updated via DCR');",
-											"    pm.expect(body).to.have.property(\"response_types\");",
-											"    pm.expect(body.response_types).to.eql([]);",
+											"    pm.expect(body).not.to.have.property(\"response_types\");",
 											"    pm.expect(body).to.have.property(\"grant_types\");",
 											"    pm.expect(body.grant_types).to.eql([\"client_credentials\"]);",
 											"});",
@@ -4199,6 +4308,10 @@
 											"    var body = pm.response.json();",
 											"    pm.expect(body.client_id).to.eql(pm.environment.get('newClientIdForDCRTests'));",
 											"    pm.expect(body.client_secret).to.not.eql(pm.environment.get('newClientSecretForDCRTests'));",
+											"",
+											"    let renewSecretEndpoint = pm.environment.get('registrationClientUri')+'/renew_secret';",
+											"    let discoveryRenewSecret = pm.environment.get('registrationRenewSecretEndpoint').replace(':client_id',pm.environment.get('newClientIdForDCRTests'));",
+											"    pm.expect(renewSecretEndpoint).to.be.eql(discoveryRenewSecret);",
 											"});",
 											"",
 											"pm.test(\"One time Token\", function() {",
@@ -4289,6 +4402,449 @@
 						}
 					],
 					"_postman_isSubFolder": true
+				},
+				{
+					"name": "case with all metadatas",
+					"item": [
+						{
+							"name": "Register client - client application",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"exec": [
+											"pm.test(\"Status code is 201\", function () {",
+											"    pm.response.to.have.status(201);",
+											"});",
+											"",
+											"pm.test(\"Has default attributes\", function () {",
+											"    var body = pm.response.json();",
+											"    //Check expecting metadata",
+											"    pm.expect(body).to.have.property('grant_types');",
+											"    pm.expect(body).to.have.property('application_type');",
+											"    pm.expect(body).to.have.property('client_name');",
+											"    pm.expect(body).to.have.property('require_auth_time');",
+											"    pm.expect(body).to.have.property('client_id');",
+											"    pm.expect(body).to.have.property('client_secret');",
+											"    pm.expect(body).to.have.property('registration_access_token');",
+											"    pm.expect(body).to.have.property('registration_client_uri');",
+											"    pm.expect(body).to.have.property('client_secret_expires_at');",
+											"    ",
+											"    //Check expecting values",
+											"    pm.expect(body.application_type).to.eql('server');",
+											"    pm.expect(body.grant_types).to.eql(['client_credentials']);",
+											"    pm.expect(body.client_name).to.eql('test all metadatas');",
+											"    pm.expect(body.require_auth_time).to.eql(false);",
+											"    ",
+											"    //Track just created client",
+											"    pm.environment.set('newClientForDCRTests', body.id);",
+											"    pm.environment.set('newClientIdForDCRTests', body.client_id);",
+											"    pm.environment.set('newClientSecretForDCRTests', body.client_secret);",
+											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+											"    ",
+											"    //Expect null values to not be returned.",
+											"    pm.expect(body).not.to.have.property('redirect_uris');",
+											"    pm.expect(body).not.to.have.property(\"response_types\");",
+											"    pm.expect(body).not.to.have.property('contacts');",
+											"    pm.expect(body).not.to.have.property(\"logo_uri\");",
+											"    pm.expect(body).not.to.have.property('client_uri');",
+											"    pm.expect(body).not.to.have.property(\"policy_uri\");",
+											"    pm.expect(body).not.to.have.property('tos_uri');",
+											"    pm.expect(body).not.to.have.property(\"jwks_uri\");",
+											"    pm.expect(body).not.to.have.property('sector_identifier_uri');",
+											"    pm.expect(body).not.to.have.property(\"subject_type\");",
+											"    pm.expect(body).not.to.have.property('id_token_signed_response_alg');",
+											"    pm.expect(body).not.to.have.property(\"id_token_encrypted_response_alg\");",
+											"    pm.expect(body).not.to.have.property('id_token_encrypted_response_enc');",
+											"    pm.expect(body).not.to.have.property(\"userinfo_signed_response_alg\");",
+											"    pm.expect(body).not.to.have.property('userinfo_encrypted_response_alg');",
+											"    pm.expect(body).not.to.have.property(\"userinfo_encrypted_response_enc\");",
+											"    pm.expect(body).not.to.have.property('request_object_signing_alg');",
+											"    pm.expect(body).not.to.have.property(\"request_object_encryption_alg\");",
+											"    pm.expect(body).not.to.have.property('request_object_encryption_enc');",
+											"    pm.expect(body).not.to.have.property(\"token_endpoint_auth_method\");",
+											"    pm.expect(body).not.to.have.property('token_endpoint_auth_signing_alg');",
+											"    pm.expect(body).not.to.have.property(\"default_max_age\");",
+											"    pm.expect(body).not.to.have.property(\"default_acr_values\");",
+											"    pm.expect(body).not.to.have.property(\"initiate_login_uri\");",
+											"    pm.expect(body).not.to.have.property('request_uris');",
+											"    pm.expect(body).not.to.have.property(\"scope\");",
+											"    pm.expect(body).not.to.have.property('software_id');",
+											"    pm.expect(body).not.to.have.property(\"software_version\");",
+											"    pm.expect(body).not.to.have.property(\"software_statement\");",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"type": "text",
+										"value": "application/json"
+									},
+									{
+										"key": "Authorization",
+										"type": "text",
+										"value": "Bearer {{access_token}}"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{  \n   \"redirect_uris\":null,\n   \"response_types\":null,\n   \"grant_types\":[\"client_credentials\"],\n   \"application_type\":\"server\",\n   \"contacts\":null,\n   \"client_name\":\"test all metadatas\",\n   \"logo_uri\":null,\n   \"client_uri\":null,\n   \"policy_uri\":null,\n   \"tos_uri\":null,\n   \"jwks_uri\":null,\n   \"sector_identifier_uri\":null,\n   \"subject_type\":null,\n   \"id_token_signed_response_alg\":null,\n   \"id_token_encrypted_response_alg\":null,\n   \"id_token_encrypted_response_enc\":null,\n   \"userinfo_signed_response_alg\":null,\n   \"userinfo_encrypted_response_alg\":null,\n   \"userinfo_encrypted_response_enc\":null,\n   \"request_object_signing_alg\":null,\n   \"request_object_encryption_alg\":null,\n   \"request_object_encryption_enc\":null,\n   \"token_endpoint_auth_method\":null,\n   \"token_endpoint_auth_signing_alg\":null,\n   \"default_max_age\":null,\n   \"require_auth_time\":null,\n   \"default_acr_values\":null,\n   \"initiate_login_uri\":null,\n   \"request_uris\":null,\n   \"scope\":null,\n   \"software_id\":null,\n   \"software_version\":null,\n   \"software_statement\":null\n}"
+								},
+								"url": {
+									"raw": "{{registrationEndpoint}}",
+									"host": [
+										"{{registrationEndpoint}}"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Get client - with registration token",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"exec": [
+											"pm.test(\"Status code is 200\", function () {",
+											"    pm.response.to.have.status(200);",
+											"});",
+											"",
+											"pm.test(\"Get client with response types\", function () {",
+											"    pm.response.to.be.header('Content-Type', 'application/json');",
+											"    var body = pm.response.json();",
+											"    pm.expect(body).to.have.property(\"grant_types\");",
+											"    pm.expect(body.grant_types).to.eql([ 'client_credentials' ]);",
+											"    ",
+											"    //The Authorization Server need not include the registration_access_token ",
+											"    //or registration_client_uri value in this response unless they have been updated.",
+											"    pm.expect(body).to.not.have.property('registration_access_token');",
+											"    pm.expect(body).to.not.have.property('registration_client_uri');",
+											"    ",
+											"    //Expect null values to not be returned.",
+											"    pm.expect(body).not.to.have.property('redirect_uris');",
+											"    pm.expect(body).not.to.have.property(\"response_types\");",
+											"    pm.expect(body).not.to.have.property('contacts');",
+											"    pm.expect(body).not.to.have.property(\"logo_uri\");",
+											"    pm.expect(body).not.to.have.property('client_uri');",
+											"    pm.expect(body).not.to.have.property(\"policy_uri\");",
+											"    pm.expect(body).not.to.have.property('tos_uri');",
+											"    pm.expect(body).not.to.have.property(\"jwks_uri\");",
+											"    pm.expect(body).not.to.have.property('sector_identifier_uri');",
+											"    pm.expect(body).not.to.have.property(\"subject_type\");",
+											"    pm.expect(body).not.to.have.property('id_token_signed_response_alg');",
+											"    pm.expect(body).not.to.have.property(\"id_token_encrypted_response_alg\");",
+											"    pm.expect(body).not.to.have.property('id_token_encrypted_response_enc');",
+											"    pm.expect(body).not.to.have.property(\"userinfo_signed_response_alg\");",
+											"    pm.expect(body).not.to.have.property('userinfo_encrypted_response_alg');",
+											"    pm.expect(body).not.to.have.property(\"userinfo_encrypted_response_enc\");",
+											"    pm.expect(body).not.to.have.property('request_object_signing_alg');",
+											"    pm.expect(body).not.to.have.property(\"request_object_encryption_alg\");",
+											"    pm.expect(body).not.to.have.property('request_object_encryption_enc');",
+											"    pm.expect(body).not.to.have.property(\"token_endpoint_auth_method\");",
+											"    pm.expect(body).not.to.have.property('token_endpoint_auth_signing_alg');",
+											"    pm.expect(body).not.to.have.property(\"default_max_age\");",
+											"    pm.expect(body).not.to.have.property(\"default_acr_values\");",
+											"    pm.expect(body).not.to.have.property(\"initiate_login_uri\");",
+											"    pm.expect(body).not.to.have.property('request_uris');",
+											"    pm.expect(body).not.to.have.property(\"scope\");",
+											"    pm.expect(body).not.to.have.property('software_id');",
+											"    pm.expect(body).not.to.have.property(\"software_version\");",
+											"    pm.expect(body).not.to.have.property(\"software_statement\");",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "GET",
+								"header": [
+									{
+										"key": "Content-Type",
+										"type": "text",
+										"value": "application/json"
+									},
+									{
+										"key": "Authorization",
+										"type": "text",
+										"value": "Bearer {{registrationAccessToken}}"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": ""
+								},
+								"url": {
+									"raw": "{{registrationClientUri}}",
+									"host": [
+										"{{registrationClientUri}}"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Patch client - with registration token",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"exec": [
+											"pm.test(\"Status code is 200\", function () {",
+											"    pm.response.to.have.status(200);",
+											"});",
+											"",
+											"pm.test(\"Get client with response types\", function () {",
+											"    pm.response.to.be.header('Content-Type', 'application/json');",
+											"    var body = pm.response.json();",
+											"    //Check expecting metadata",
+											"    pm.expect(body).to.have.property('grant_types');",
+											"    pm.expect(body).to.have.property('application_type');",
+											"    pm.expect(body).to.have.property('client_name');",
+											"    pm.expect(body).to.have.property('require_auth_time');",
+											"    pm.expect(body).to.have.property('client_id');",
+											"    pm.expect(body).to.have.property('client_secret');",
+											"    pm.expect(body).to.have.property('registration_access_token');",
+											"    pm.expect(body).to.have.property('registration_client_uri');",
+											"    pm.expect(body).to.have.property('client_secret_expires_at');",
+											"    ",
+											"    //Check expecting values",
+											"    pm.expect(body.application_type).to.eql('server');",
+											"    pm.expect(body.grant_types).to.eql(['client_credentials']);",
+											"    pm.expect(body.client_name).to.eql('test');",
+											"    pm.expect(body.require_auth_time).to.eql(false);",
+											"    ",
+											"    //Expect null values to not be returned.",
+											"    pm.expect(body).not.to.have.property('redirect_uris');",
+											"    pm.expect(body).not.to.have.property(\"response_types\");",
+											"    pm.expect(body).not.to.have.property('contacts');",
+											"    pm.expect(body).not.to.have.property(\"logo_uri\");",
+											"    pm.expect(body).not.to.have.property('client_uri');",
+											"    pm.expect(body).not.to.have.property(\"policy_uri\");",
+											"    pm.expect(body).not.to.have.property('tos_uri');",
+											"    pm.expect(body).not.to.have.property(\"jwks_uri\");",
+											"    pm.expect(body).not.to.have.property('sector_identifier_uri');",
+											"    pm.expect(body).not.to.have.property(\"subject_type\");",
+											"    pm.expect(body).not.to.have.property('id_token_signed_response_alg');",
+											"    pm.expect(body).not.to.have.property(\"id_token_encrypted_response_alg\");",
+											"    pm.expect(body).not.to.have.property('id_token_encrypted_response_enc');",
+											"    pm.expect(body).not.to.have.property(\"userinfo_signed_response_alg\");",
+											"    pm.expect(body).not.to.have.property('userinfo_encrypted_response_alg');",
+											"    pm.expect(body).not.to.have.property(\"userinfo_encrypted_response_enc\");",
+											"    pm.expect(body).not.to.have.property('request_object_signing_alg');",
+											"    pm.expect(body).not.to.have.property(\"request_object_encryption_alg\");",
+											"    pm.expect(body).not.to.have.property('request_object_encryption_enc');",
+											"    pm.expect(body).not.to.have.property(\"token_endpoint_auth_method\");",
+											"    pm.expect(body).not.to.have.property('token_endpoint_auth_signing_alg');",
+											"    pm.expect(body).not.to.have.property(\"default_max_age\");",
+											"    pm.expect(body).not.to.have.property(\"default_acr_values\");",
+											"    pm.expect(body).not.to.have.property(\"initiate_login_uri\");",
+											"    pm.expect(body).not.to.have.property('request_uris');",
+											"    pm.expect(body).not.to.have.property(\"scope\");",
+											"    pm.expect(body).not.to.have.property('software_id');",
+											"    pm.expect(body).not.to.have.property(\"software_version\");",
+											"    pm.expect(body).not.to.have.property(\"software_statement\");",
+											"});",
+											"",
+											"pm.test(\"One time Token\", function() {",
+											"    var body = pm.response.json();",
+											"    pm.expect(body).to.have.property('registration_access_token');",
+											"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "PATCH",
+								"header": [
+									{
+										"key": "Content-Type",
+										"type": "text",
+										"value": "application/json"
+									},
+									{
+										"key": "Authorization",
+										"type": "text",
+										"value": "Bearer {{registrationAccessToken}}"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{  \n   \"redirect_uris\":null,\n   \"response_types\":null,\n   \"grant_types\":[\"client_credentials\"],\n   \"application_type\":\"server\",\n   \"contacts\":null,\n   \"client_name\":\"test\",\n   \"logo_uri\":null,\n   \"client_uri\":null,\n   \"policy_uri\":null,\n   \"tos_uri\":null,\n   \"jwks_uri\":null,\n   \"sector_identifier_uri\":null,\n   \"subject_type\":null,\n   \"id_token_signed_response_alg\":null,\n   \"id_token_encrypted_response_alg\":null,\n   \"id_token_encrypted_response_enc\":null,\n   \"userinfo_signed_response_alg\":null,\n   \"userinfo_encrypted_response_alg\":null,\n   \"userinfo_encrypted_response_enc\":null,\n   \"request_object_signing_alg\":null,\n   \"request_object_encryption_alg\":null,\n   \"request_object_encryption_enc\":null,\n   \"token_endpoint_auth_method\":null,\n   \"token_endpoint_auth_signing_alg\":null,\n   \"default_max_age\":null,\n   \"require_auth_time\":null,\n   \"default_acr_values\":null,\n   \"initiate_login_uri\":null,\n   \"request_uris\":null,\n   \"scope\":null,\n   \"software_id\":null,\n   \"software_version\":null,\n   \"software_statement\":null\n}"
+								},
+								"url": {
+									"raw": "{{registrationClientUri}}",
+									"host": [
+										"{{registrationClientUri}}"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Update client - with registration token",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"exec": [
+											"pm.test(\"Status code is 200\", function () {",
+											"    pm.response.to.have.status(200);",
+											"});",
+											"",
+											"pm.test(\"Get client with response types\", function () {",
+											"    pm.response.to.be.header('Content-Type', 'application/json');",
+											"    var body = pm.response.json();",
+											"    //Check expecting metadata",
+											"    pm.expect(body).to.have.property('grant_types');",
+											"    pm.expect(body).to.have.property('application_type');",
+											"    pm.expect(body).to.have.property('client_name');",
+											"    pm.expect(body).to.have.property('require_auth_time');",
+											"    pm.expect(body).to.have.property('client_id');",
+											"    pm.expect(body).to.have.property('client_secret');",
+											"    pm.expect(body).to.have.property('registration_access_token');",
+											"    pm.expect(body).to.have.property('registration_client_uri');",
+											"    pm.expect(body).to.have.property('client_secret_expires_at');",
+											"    ",
+											"    //Check expecting values",
+											"    pm.expect(body.application_type).to.eql('server');",
+											"    pm.expect(body.grant_types).to.eql(['client_credentials']);",
+											"    pm.expect(body.client_name).to.eql('test');",
+											"    pm.expect(body.require_auth_time).to.eql(false);",
+											"    ",
+											"    //Expect null values to not be returned.",
+											"    pm.expect(body).not.to.have.property('redirect_uris');",
+											"    pm.expect(body).not.to.have.property(\"response_types\");",
+											"    pm.expect(body).not.to.have.property('contacts');",
+											"    pm.expect(body).not.to.have.property(\"logo_uri\");",
+											"    pm.expect(body).not.to.have.property('client_uri');",
+											"    pm.expect(body).not.to.have.property(\"policy_uri\");",
+											"    pm.expect(body).not.to.have.property('tos_uri');",
+											"    pm.expect(body).not.to.have.property(\"jwks_uri\");",
+											"    pm.expect(body).not.to.have.property('sector_identifier_uri');",
+											"    pm.expect(body).not.to.have.property(\"subject_type\");",
+											"    pm.expect(body).not.to.have.property('id_token_signed_response_alg');",
+											"    pm.expect(body).not.to.have.property(\"id_token_encrypted_response_alg\");",
+											"    pm.expect(body).not.to.have.property('id_token_encrypted_response_enc');",
+											"    pm.expect(body).not.to.have.property(\"userinfo_signed_response_alg\");",
+											"    pm.expect(body).not.to.have.property('userinfo_encrypted_response_alg');",
+											"    pm.expect(body).not.to.have.property(\"userinfo_encrypted_response_enc\");",
+											"    pm.expect(body).not.to.have.property('request_object_signing_alg');",
+											"    pm.expect(body).not.to.have.property(\"request_object_encryption_alg\");",
+											"    pm.expect(body).not.to.have.property('request_object_encryption_enc');",
+											"    pm.expect(body).not.to.have.property(\"token_endpoint_auth_method\");",
+											"    pm.expect(body).not.to.have.property('token_endpoint_auth_signing_alg');",
+											"    pm.expect(body).not.to.have.property(\"default_max_age\");",
+											"    pm.expect(body).not.to.have.property(\"default_acr_values\");",
+											"    pm.expect(body).not.to.have.property(\"initiate_login_uri\");",
+											"    pm.expect(body).not.to.have.property('request_uris');",
+											"    pm.expect(body).not.to.have.property(\"scope\");",
+											"    pm.expect(body).not.to.have.property('software_id');",
+											"    pm.expect(body).not.to.have.property(\"software_version\");",
+											"    pm.expect(body).not.to.have.property(\"software_statement\");",
+											"});",
+											"",
+											"pm.test(\"One time Token\", function() {",
+											"    var body = pm.response.json();",
+											"    pm.expect(body).to.have.property('registration_access_token');",
+											"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+											"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+											"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "PUT",
+								"header": [
+									{
+										"key": "Content-Type",
+										"type": "text",
+										"value": "application/json"
+									},
+									{
+										"key": "Authorization",
+										"type": "text",
+										"value": "Bearer {{registrationAccessToken}}"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{  \n   \"redirect_uris\":null,\n   \"response_types\":null,\n   \"grant_types\":[\"client_credentials\"],\n   \"application_type\":\"server\",\n   \"contacts\":null,\n   \"client_name\":\"test\",\n   \"logo_uri\":null,\n   \"client_uri\":null,\n   \"policy_uri\":null,\n   \"tos_uri\":null,\n   \"jwks_uri\":null,\n   \"sector_identifier_uri\":null,\n   \"subject_type\":null,\n   \"id_token_signed_response_alg\":null,\n   \"id_token_encrypted_response_alg\":null,\n   \"id_token_encrypted_response_enc\":null,\n   \"userinfo_signed_response_alg\":null,\n   \"userinfo_encrypted_response_alg\":null,\n   \"userinfo_encrypted_response_enc\":null,\n   \"request_object_signing_alg\":null,\n   \"request_object_encryption_alg\":null,\n   \"request_object_encryption_enc\":null,\n   \"token_endpoint_auth_method\":null,\n   \"token_endpoint_auth_signing_alg\":null,\n   \"default_max_age\":null,\n   \"require_auth_time\":null,\n   \"default_acr_values\":null,\n   \"initiate_login_uri\":null,\n   \"request_uris\":null,\n   \"scope\":null,\n   \"software_id\":null,\n   \"software_version\":null,\n   \"software_statement\":null\n}"
+								},
+								"url": {
+									"raw": "{{registrationClientUri}}",
+									"host": [
+										"{{registrationClientUri}}"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Delete client - with registration token",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+										"exec": [
+											"pm.test(\"Status code is 204\", function () {",
+											"    pm.response.to.have.status(204);",
+											"});",
+											""
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "DELETE",
+								"header": [
+									{
+										"key": "Content-Type",
+										"type": "text",
+										"value": "application/json"
+									},
+									{
+										"key": "Authorization",
+										"type": "text",
+										"value": "Bearer {{registrationAccessToken}}"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": ""
+								},
+								"url": {
+									"raw": "{{registrationClientUri}}",
+									"host": [
+										"{{registrationClientUri}}"
+									]
+								}
+							},
+							"response": []
+						}
+					],
+					"_postman_isSubFolder": true
 				}
 			]
 		},
@@ -48835,6 +49391,460 @@
 				}
 			]
 		},
+		{
+			"name": "Case - Default and Allowed Scopes",
+			"item": [
+				{
+					"name": "Enable Default and Allowed scopes",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"id": "bfe78ac1-144a-4bbd-abf9-55e160e723bf",
+								"exec": [
+									"pm.test(\"Status code is 200\", function () {",
+									"    pm.response.to.have.status(200);",
+									"});",
+									"",
+									"pm.test(\"DCR enabled for domain\", function () {",
+									"    var jsonData = pm.response.json();",
+									"    pm.expect(jsonData.oidc.clientRegistrationSettings.isAllowedScopesEnabled).to.eql(true);",
+									"    pm.expect(jsonData.oidc.clientRegistrationSettings.allowedScopes).to.eql([\"email\"]);",
+									"    pm.expect(jsonData.oidc.clientRegistrationSettings.defaultScopes).to.eql([\"openid\",\"profile\"]);",
+									"});",
+									"",
+									"// wait for sync process",
+									"setTimeout(function(){}, 5000);"
+								],
+								"type": "text/javascript"
+							}
+						}
+					],
+					"request": {
+						"method": "PATCH",
+						"header": [
+							{
+								"key": "Content-Type",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"value": "Bearer {{token}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n  \"oidc\": {\n    \"clientRegistrationSettings\": {\n      \"isAllowedScopesEnabled\": true,\n      \"allowedScopes\" : [\n\t\t\"email\"\n\t  ],\n\t  \"defaultScopes\" : [\n\t\t\"openid\",\n\t\t\"profile\"\n\t  ]\n    }\n  }\n}"
+						},
+						"url": {
+							"raw": "{{management_url}}/management/domains/{{domain}}",
+							"host": [
+								"{{management_url}}"
+							],
+							"path": [
+								"management",
+								"domains",
+								"{{domain}}"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "Allowed Scopes filter - scopes reduced",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+								"exec": [
+									"pm.test(\"Status code is 201\", function () {",
+									"    pm.response.to.have.status(201);",
+									"});",
+									"",
+									"pm.test(\"Has default attributes\", function () {",
+									"    var body = pm.response.json();",
+									"    pm.expect(body).to.have.property('scope');",
+									"    pm.expect(body.scope).to.eql('email');//scopes have been filtered to keep only allowed ones",
+									"",
+									"    pm.environment.set('newClientForDCRTests', body.id);",
+									"    pm.environment.set('newClientIdForDCRTests', body.client_id);",
+									"    pm.environment.set('newClientSecretForDCRTests', body.client_secret);",
+									"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+									"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+									"});"
+								],
+								"type": "text/javascript"
+							}
+						}
+					],
+					"request": {
+						"method": "POST",
+						"header": [
+							{
+								"key": "Content-Type",
+								"type": "text",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"type": "text",
+								"value": "Bearer {{access_token}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n   \"redirect_uris\":\n     [\"https://client.example.org/callback\",\n      \"https://client.example.org/callback2\"],\n   \"scope\": \"phone email\"\n  }"
+						},
+						"url": {
+							"raw": "{{registrationEndpoint}}",
+							"host": [
+								"{{registrationEndpoint}}"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "All scopes rejected - Default scopes applied",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+								"exec": [
+									"pm.test(\"Status code is 200\", function () {",
+									"    pm.response.to.have.status(200);",
+									"});",
+									"",
+									"pm.test(\"Get client with response types\", function () {",
+									"    pm.response.to.be.header('Content-Type', 'application/json');",
+									"    var body = pm.response.json();",
+									"",
+									"    pm.expect(body).to.have.property('scope');",
+									"    pm.expect(body.scope).to.eql('openid profile');//no scopes retained, expecting default scopes.",
+									"});",
+									"",
+									"pm.test(\"One time Token\", function() {",
+									"    var body = pm.response.json();",
+									"    pm.expect(body).to.have.property('registration_access_token');",
+									"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+									"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+									"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+									"});"
+								],
+								"type": "text/javascript"
+							}
+						}
+					],
+					"request": {
+						"method": "PATCH",
+						"header": [
+							{
+								"key": "Content-Type",
+								"type": "text",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"type": "text",
+								"value": "Bearer {{registrationAccessToken}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n   \"scope\": \"phone address\"\n}"
+						},
+						"url": {
+							"raw": "{{registrationClientUri}}",
+							"host": [
+								"{{registrationClientUri}}"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "Reset scope to email",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+								"exec": [
+									"pm.test(\"Status code is 200\", function () {",
+									"    pm.response.to.have.status(200);",
+									"});",
+									"",
+									"pm.test(\"Get client with response types\", function () {",
+									"    pm.response.to.be.header('Content-Type', 'application/json');",
+									"    var body = pm.response.json();",
+									"",
+									"    pm.expect(body).to.have.property('scope');",
+									"    pm.expect(body.scope).to.eql('email');",
+									"});",
+									"",
+									"pm.test(\"One time Token\", function() {",
+									"    var body = pm.response.json();",
+									"    pm.expect(body).to.have.property('registration_access_token');",
+									"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+									"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+									"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+									"});"
+								],
+								"type": "text/javascript"
+							}
+						}
+					],
+					"request": {
+						"method": "PATCH",
+						"header": [
+							{
+								"key": "Content-Type",
+								"type": "text",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"type": "text",
+								"value": "Bearer {{registrationAccessToken}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n   \"scope\": \"email\"\n}"
+						},
+						"url": {
+							"raw": "{{registrationClientUri}}",
+							"host": [
+								"{{registrationClientUri}}"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "No scopes - Default scopes applied",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+								"exec": [
+									"pm.test(\"Status code is 200\", function () {",
+									"    pm.response.to.have.status(200);",
+									"});",
+									"",
+									"pm.test(\"Get client with response types\", function () {",
+									"    pm.response.to.be.header('Content-Type', 'application/json');",
+									"    var body = pm.response.json();",
+									"    pm.expect(body.client_name).to.eql('Client name updated via DCR');",
+									"    pm.expect(body.scope).to.eql('openid profile');//no scopes into the request, expecting default scopes.",
+									"});",
+									"",
+									"pm.test(\"One time Token\", function() {",
+									"    var body = pm.response.json();",
+									"    pm.expect(body).to.have.property('registration_access_token');",
+									"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+									"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+									"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+									"});"
+								],
+								"type": "text/javascript"
+							}
+						}
+					],
+					"request": {
+						"method": "PUT",
+						"header": [
+							{
+								"key": "Content-Type",
+								"type": "text",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"type": "text",
+								"value": "Bearer {{registrationAccessToken}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n    \"redirect_uris\": [\n        \"https://client.example.org/callback\",\n        \"https://client.example.org/callback2\"\n    ],\n    \"response_types\": [\n        \"code\"\n    ],\n    \"grant_types\": [\n        \"authorization_code\"\n    ],\n    \"application_type\": \"web\",\n    \"contacts\": [\n        \"marie@example.org\",\n        \"jeanne@example.org\"\n    ],\n\t\"client_name\": \"Client name updated via DCR\",\n    \"logo_uri\": \"https://client.example.org/logo.png\",\n    \"subject_type\": \"public\",\n    \"userinfo_encrypted_response_alg\": \"RSA-OAEP-256\",\n    \"userinfo_encrypted_response_enc\": \"A128CBC-HS256\",\n    \"token_endpoint_auth_method\": \"client_secret_basic\",\n    \"require_auth_time\": false,\n    \"request_uris\": [\n        \"https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA\"\n    ]\n}"
+						},
+						"url": {
+							"raw": "{{registrationClientUri}}",
+							"host": [
+								"{{registrationClientUri}}"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "Reset scope to email",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+								"exec": [
+									"pm.test(\"Status code is 200\", function () {",
+									"    pm.response.to.have.status(200);",
+									"});",
+									"",
+									"pm.test(\"Get client with response types\", function () {",
+									"    pm.response.to.be.header('Content-Type', 'application/json');",
+									"    var body = pm.response.json();",
+									"",
+									"    pm.expect(body).to.have.property('scope');",
+									"    pm.expect(body.scope).to.eql('email');",
+									"});",
+									"",
+									"pm.test(\"One time Token\", function() {",
+									"    var body = pm.response.json();",
+									"    pm.expect(body).to.have.property('registration_access_token');",
+									"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+									"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+									"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+									"});"
+								],
+								"type": "text/javascript"
+							}
+						}
+					],
+					"request": {
+						"method": "PATCH",
+						"header": [
+							{
+								"key": "Content-Type",
+								"type": "text",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"type": "text",
+								"value": "Bearer {{registrationAccessToken}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n   \"scope\": \"email\"\n}"
+						},
+						"url": {
+							"raw": "{{registrationClientUri}}",
+							"host": [
+								"{{registrationClientUri}}"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "Scopes null - Default scopes applied",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+								"exec": [
+									"pm.test(\"Status code is 200\", function () {",
+									"    pm.response.to.have.status(200);",
+									"});",
+									"",
+									"pm.test(\"Get client with response types\", function () {",
+									"    pm.response.to.be.header('Content-Type', 'application/json');",
+									"    var body = pm.response.json();",
+									"",
+									"    pm.expect(body).to.have.property('scope');",
+									"    pm.expect(body.scope).to.eql('openid profile');//no scopes retained, expecting default scopes.",
+									"});",
+									"",
+									"pm.test(\"One time Token\", function() {",
+									"    var body = pm.response.json();",
+									"    pm.expect(body).to.have.property('registration_access_token');",
+									"    pm.expect(body.registration_access_token).to.not.eql(pm.environment.get('registrationAccessToken'));",
+									"    pm.environment.set('registrationAccessToken', body.registration_access_token);",
+									"    pm.environment.set('registrationClientUri', body.registration_client_uri);",
+									"});"
+								],
+								"type": "text/javascript"
+							}
+						}
+					],
+					"request": {
+						"method": "PATCH",
+						"header": [
+							{
+								"key": "Content-Type",
+								"type": "text",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"type": "text",
+								"value": "Bearer {{registrationAccessToken}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n   \"scope\": null\n}"
+						},
+						"url": {
+							"raw": "{{registrationClientUri}}",
+							"host": [
+								"{{registrationClientUri}}"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "Delete client - with registration token",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"id": "d83b2401-3844-4147-bbb3-abe08b43a342",
+								"exec": [
+									"pm.test(\"Status code is 204\", function () {",
+									"    pm.response.to.have.status(204);",
+									"});",
+									""
+								],
+								"type": "text/javascript"
+							}
+						}
+					],
+					"request": {
+						"method": "DELETE",
+						"header": [
+							{
+								"key": "Content-Type",
+								"type": "text",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"type": "text",
+								"value": "Bearer {{registrationAccessToken}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": ""
+						},
+						"url": {
+							"raw": "{{registrationClientUri}}",
+							"host": [
+								"{{registrationClientUri}}"
+							]
+						}
+					},
+					"response": []
+				}
+			]
+		},
 		{
 			"name": "Delete domain",
 			"event": [


Test patch:
diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationRequestTest.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationRequestTest.java
index 2fc8ee9440..50d5587937 100644
--- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationRequestTest.java
+++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationRequestTest.java
@@ -69,7 +69,27 @@ public class DynamicClientRegistrationRequestTest {
         assertEquals("Refresh token validity should have been kept",3600, result.getRefreshTokenValiditySeconds());
         assertEquals("Default Max Age should have been kept",Integer.valueOf(1),result.getDefaultMaxAge());
         assertArrayEquals("Grant types should have been replaced",Arrays.asList("grant1","grant2").toArray(),result.getAuthorizedGrantTypes().toArray());
-        assertArrayEquals("Response type should have been replaced by default values",Arrays.asList("code").toArray(),result.getResponseTypes().toArray());
+        assertNull("Response type should have been set to null", result.getResponseTypes());
+        assertArrayEquals("Scopes should have been replaced",Arrays.asList("scope1","scope2").toArray(), result.getScopes().toArray());
+    }
+
+    @Test
+    public void testPatch_nullValues() {
+        patcher.setResponseTypes(null);
+
+        //Apply patch
+        Client result = patcher.patch(toPatch);
+
+        //Checks
+        assertNotNull(result);
+        assertEquals("Client name should have been replaced","expectedClientName",result.getClientName());
+        assertEquals("Client secret should have been kept","expectedSecret", result.getClientSecret());
+        assertNull("Client uri should have been erased",result.getClientUri());
+        assertEquals("Access token validity should have been kept",7200,result.getAccessTokenValiditySeconds());
+        assertEquals("Refresh token validity should have been kept",3600, result.getRefreshTokenValiditySeconds());
+        assertEquals("Default Max Age should have been kept",Integer.valueOf(1),result.getDefaultMaxAge());
+        assertArrayEquals("Grant types should have been replaced",Arrays.asList("grant1","grant2").toArray(),result.getAuthorizedGrantTypes().toArray());
+        assertArrayEquals("Response type should have not been replaced",Arrays.asList("old","old2").toArray(),result.getResponseTypes().toArray());
         assertArrayEquals("Scopes should have been replaced",Arrays.asList("scope1","scope2").toArray(), result.getScopes().toArray());
     }
 
@@ -87,7 +107,33 @@ public class DynamicClientRegistrationRequestTest {
         assertEquals("Refresh token validity should have been kept",3600, result.getRefreshTokenValiditySeconds());
         assertArrayEquals("Grant types should have been replaced",Arrays.asList("grant1","grant2").toArray(),result.getAuthorizedGrantTypes().toArray());
         assertArrayEquals("Scopes should have been replaced",Arrays.asList("scope1","scope2").toArray(), result.getScopes().toArray());
-        assertNull("Response type should be set to null", result.getResponseTypes());
+        assertNull("Response type should have been set to null", result.getResponseTypes());
         assertNull("Default max age should be set to null", result.getDefaultMaxAge());
     }
+
+    @Test
+    public void testUpdate_nullValues() {
+        patcher.setResponseTypes(null);
+
+        //Apply update
+        Client result = patcher.update(toPatch);
+
+        //Checks
+        assertNotNull(result);
+        assertEquals("Client name should have been replaced","expectedClientName",result.getClientName());
+        assertEquals("Client secret should have been kept","expectedSecret", result.getClientSecret());
+        assertNull("Client uri should have been erased",result.getClientUri());
+        assertEquals("Access token validity should have been kept",7200,result.getAccessTokenValiditySeconds());
+        assertEquals("Refresh token validity should have been kept",3600, result.getRefreshTokenValiditySeconds());
+        assertArrayEquals("Grant types should have been replaced",Arrays.asList("grant1","grant2").toArray(),result.getAuthorizedGrantTypes().toArray());
+        assertArrayEquals("Scopes should have been replaced",Arrays.asList("scope1","scope2").toArray(), result.getScopes().toArray());
+        assertNull("Response type should have been set to null", result.getResponseTypes());
+        assertNull("Default max age should be set to null", result.getDefaultMaxAge());
+    }
+
+    @Test
+    public void testGetScope() {
+        patcher.setScope(Optional.of(""));
+        assertFalse(patcher.getScope().isPresent());
+    }
 }
diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationServiceTest.java b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationServiceTest.java
index 5d5334126b..e0705b30f5 100644
--- a/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationServiceTest.java
+++ b/gravitee-am-gateway/gravitee-am-gateway-handler/gravitee-am-gateway-handler-oidc/src/test/java/io/gravitee/am/gateway/handler/oidc/service/clientregistration/DynamicClientRegistrationServiceTest.java
@@ -25,6 +25,7 @@ import io.gravitee.am.model.Client;
 import io.gravitee.am.model.Domain;
 import io.gravitee.am.model.IdentityProvider;
 import io.gravitee.am.model.oidc.JWKSet;
+import io.gravitee.am.model.oidc.OIDCSettings;
 import io.gravitee.am.service.CertificateService;
 import io.gravitee.am.service.IdentityProviderService;
 import io.gravitee.am.service.exception.InvalidClientMetadataException;
@@ -36,6 +37,7 @@ import io.vertx.reactivex.core.buffer.Buffer;
 import io.vertx.reactivex.ext.web.client.HttpRequest;
 import io.vertx.reactivex.ext.web.client.HttpResponse;
 import io.vertx.reactivex.ext.web.client.WebClient;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
@@ -175,11 +177,12 @@ public class DynamicClientRegistrationServiceTest {
     @Test
     public void validateClientRegistrationRequest_emptyRedirectUriRequest() {
         DynamicClientRegistrationRequest request = new DynamicClientRegistrationRequest();
-        request.setRedirectUris(Optional.empty());
+        //Allow null values on redirect_uris (ex client_credentials...)
+        request.setRedirectUris(Optional.empty());//"redirect_uris": null
 
         TestObserver testObserver = dcrService.validateClientRegistrationRequest(request).test();
-        testObserver.assertError(InvalidRedirectUriException.class);
-        testObserver.assertNotComplete();
+        testObserver.assertNoErrors();
+        testObserver.assertComplete();
     }
 
     @Test
@@ -188,8 +191,96 @@ public class DynamicClientRegistrationServiceTest {
         request.setRedirectUris(Optional.of(Arrays.asList()));
 
         TestObserver testObserver = dcrService.validateClientRegistrationRequest(request).test();
-        testObserver.assertError(InvalidRedirectUriException.class);
-        testObserver.assertNotComplete();
+        testObserver.assertNoErrors();
+        testObserver.assertComplete();
+    }
+
+    @Test
+    public void validateClientRegistrationRequest_notAllowedScopes() {
+        DynamicClientRegistrationRequest request = new DynamicClientRegistrationRequest();
+        request.setRedirectUris(Optional.of(Arrays.asList()));
+        request.setScope(Optional.of("not allowed"));
+
+        OIDCSettings oidc = OIDCSettings.defaultSettings();
+        oidc.getClientRegistrationSettings().setAllowedScopesEnabled(true);
+        oidc.getClientRegistrationSettings().setAllowedScopes(Arrays.asList("openid","profile"));
+        when(domain.getOidc()).thenReturn(oidc);
+
+        TestObserver testObserver = dcrService.validateClientRegistrationRequest(request).test();
+        testObserver.assertNoErrors();
+        testObserver.assertComplete();
+        //scope is not allowed, so expecting to erase scope (no scope)
+        testObserver.assertValue(o -> !((DynamicClientRegistrationRequest)o).getScope().isPresent());
+    }
+
+    @Test
+    public void validateClientRegistrationRequest_notAllowedScopes_defaultScopes() {
+        DynamicClientRegistrationRequest request = new DynamicClientRegistrationRequest();
+        request.setRedirectUris(Optional.of(Arrays.asList()));
+        request.setScope(Optional.of("not allowed"));
+
+        OIDCSettings oidc = OIDCSettings.defaultSettings();
+        oidc.getClientRegistrationSettings().setAllowedScopesEnabled(true);
+        oidc.getClientRegistrationSettings().setAllowedScopes(Arrays.asList("openid","profile"));
+        oidc.getClientRegistrationSettings().setDefaultScopes(Arrays.asList("phone","email"));
+        when(domain.getOidc()).thenReturn(oidc);
+
+        TestObserver testObserver = dcrService.validateClientRegistrationRequest(request).test();
+        testObserver.assertNoErrors();
+        testObserver.assertComplete();
+        testObserver.assertValue(o -> ((DynamicClientRegistrationRequest)o).getScope().get().size()==2);
+        testObserver.assertValue(o -> ((DynamicClientRegistrationRequest)o).getScope().get().containsAll(Arrays.asList("phone","email")));
+    }
+
+    @Test
+    public void validateClientRegistrationRequest_filteredScopes() {
+        DynamicClientRegistrationRequest request = new DynamicClientRegistrationRequest();
+        request.setRedirectUris(Optional.of(Arrays.asList()));
+        request.setScope(Optional.of("openid not allowed"));
+
+        OIDCSettings oidc = OIDCSettings.defaultSettings();
+        oidc.getClientRegistrationSettings().setAllowedScopesEnabled(true);
+        oidc.getClientRegistrationSettings().setAllowedScopes(Arrays.asList("openid","profile"));
+        when(domain.getOidc()).thenReturn(oidc);
+
+        TestObserver testObserver = dcrService.validateClientRegistrationRequest(request).test();
+        testObserver.assertNoErrors();
+        testObserver.assertComplete();
+        testObserver.assertValue(o -> ((DynamicClientRegistrationRequest)o).getScope().get().size()==1);
+        testObserver.assertValue(o -> ((DynamicClientRegistrationRequest)o).getScope().get().get(0).equals("openid"));
+    }
+
+    @Test
+    public void validateClientRegistrationRequest_defaultScopes_notUsed() {
+        DynamicClientRegistrationRequest request = new DynamicClientRegistrationRequest();
+        request.setRedirectUris(Optional.of(Arrays.asList()));
+        request.setScope(Optional.of("openid not allowed"));
+
+        OIDCSettings oidc = OIDCSettings.defaultSettings();
+        oidc.getClientRegistrationSettings().setDefaultScopes(Arrays.asList("phone","email"));
+        when(domain.getOidc()).thenReturn(oidc);
+
+        TestObserver testObserver = dcrService.validateClientRegistrationRequest(request).test();
+        testObserver.assertNoErrors();
+        testObserver.assertComplete();
+        testObserver.assertValue(o -> ((DynamicClientRegistrationRequest)o).getScope().get().size()==3);
+        testObserver.assertValue(o -> ((DynamicClientRegistrationRequest)o).getScope().get().containsAll(Arrays.asList("openid","not","allowed")));
+    }
+
+    @Test
+    public void validateClientRegistrationRequest_defaultScopes() {
+        DynamicClientRegistrationRequest request = new DynamicClientRegistrationRequest();
+        request.setRedirectUris(Optional.of(Arrays.asList()));
+
+        OIDCSettings oidc = OIDCSettings.defaultSettings();
+        oidc.getClientRegistrationSettings().setDefaultScopes(Arrays.asList("phone","email"));
+        when(domain.getOidc()).thenReturn(oidc);
+
+        TestObserver testObserver = dcrService.validateClientRegistrationRequest(request).test();
+        testObserver.assertNoErrors();
+        testObserver.assertComplete();
+        testObserver.assertValue(o -> ((DynamicClientRegistrationRequest)o).getScope().get().size()==2);
+        testObserver.assertValue(o -> ((DynamicClientRegistrationRequest)o).getScope().get().containsAll(Arrays.asList("phone","email")));
     }
 
     @Test
@@ -227,18 +318,6 @@ public class DynamicClientRegistrationServiceTest {
         testObserver.assertNotComplete();
     }
 
-    @Test
-    public void validateClientRegistrationRequest_RefreshTokenGrantTypeOnly() {
-        DynamicClientRegistrationRequest request = new DynamicClientRegistrationRequest();
-        request.setRedirectUris(Optional.of(Arrays.asList("https://graviee.io/callback")));
-        request.setGrantTypes(Optional.of(Arrays.asList("refresh_token")));
-
-        TestObserver testObserver = dcrService.validateClientRegistrationRequest(request).test();
-        testObserver.assertError(InvalidClientMetadataException.class);
-        testObserver.assertError(err -> ((Throwable)err).getMessage().startsWith("refresh_token grant type must be associated with"));
-        testObserver.assertNotComplete();
-    }
-
     @Test
     public void validateClientRegistrationRequest_unsupportedSubjectTypePayload() {
         DynamicClientRegistrationRequest request = new DynamicClientRegistrationRequest();
@@ -503,7 +582,7 @@ public class DynamicClientRegistrationServiceTest {
 
         TestObserver<DynamicClientRegistrationRequest> testObserver = dcrService.validateClientRegistrationRequest(request).test();
         testObserver.assertError(InvalidClientMetadataException.class);
-        testObserver.assertErrorMessage("No JWK found behing jws uri...");
+        testObserver.assertErrorMessage("No JWK found behind jws uri...");
         testObserver.assertNotComplete();
     }
 
@@ -558,6 +637,16 @@ public class DynamicClientRegistrationServiceTest {
         testObserver.assertComplete();
     }
 
+    @Test
+    public void validatePatchRequest_emptyRedirectUri() {
+        DynamicClientRegistrationRequest request = new DynamicClientRegistrationRequest();
+        request.setRedirectUris(Optional.empty());
+
+        TestObserver testObserver = dcrService.validateClientPatchRequest(request).test();
+        testObserver.assertNoErrors();
+        testObserver.assertComplete();
+    }
+
     @Test
     public void validatePatchRequest() {
         DynamicClientRegistrationRequest request = new DynamicClientRegistrationRequest();
diff --git a/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/GrantTypeUtilsTest.java b/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/GrantTypeUtilsTest.java
index 6ac38a4640..f6fc9e347f 100644
--- a/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/GrantTypeUtilsTest.java
+++ b/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/GrantTypeUtilsTest.java
@@ -23,6 +23,7 @@ import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 import java.util.Arrays;
+import java.util.Optional;
 
 import static org.junit.Assert.*;
 
@@ -98,6 +99,19 @@ public class GrantTypeUtilsTest {
         testObserver.assertError(InvalidClientMetadataException.class);
     }
 
+    @Test
+    public void validateGrantTypes_refreshToken_ko() {
+        Client client = new Client();
+        client.setAuthorizedGrantTypes(Arrays.asList("refresh_token"));
+        client.setResponseTypes(Arrays.asList());
+
+        TestObserver<Client> testObserver = GrantTypeUtils.validateGrantTypes(client).test();
+
+        testObserver.assertError(InvalidClientMetadataException.class);
+        testObserver.assertError(err -> ((Throwable)err).getMessage().startsWith("refresh_token grant type must be associated with"));
+        testObserver.assertNotComplete();
+    }
+
     @Test
     public void validateGrantTypes_refreshToken_ok() {
         Client client = new Client();
diff --git a/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/SetterUtilsTest.java b/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/SetterUtilsTest.java
index 0abca30d9a..b81e9fbfc4 100644
--- a/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/SetterUtilsTest.java
+++ b/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/SetterUtilsTest.java
@@ -115,29 +115,6 @@ public class SetterUtilsTest {
         assertEquals("double non default value",Double.MAX_VALUE,basic.getDouble(),1e-15);
     }
 
-    @Test
-    public void testSafeSetOrElse_optionalIsNull() {
-        BasicDto basic = new BasicDto();
-        SetterUtils.safeSetOrElse(basic::setString,null,"orElse");
-        assertNull("was expecting a null value",basic.getString());
-    }
-
-    @Test
-    public void testSafeSetOrElse_optionalIsEmpty() {
-        BasicDto basic = new BasicDto();
-        SetterUtils.safeSetOrElse(basic::setString,Optional.empty(),"orElse");
-        assertNotNull("was expecting a non null value",basic.getString());
-        assertEquals("orElse",basic.getString());
-    }
-
-    @Test
-    public void testSafeSetOrElse_optionalIsNotEmpty() {
-        BasicDto basic = new BasicDto();
-        SetterUtils.safeSetOrElse(basic::setString,Optional.of("succeed"),"wasEmpty");
-        assertNotNull(basic.getString());
-        assertEquals("succeed",basic.getString());
-    }
-
     @Test
     public void testSet_optionalIsNull() {
         BasicDto basic = new BasicDto();