keycloak-memoizeit

Changes

Details

diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java
index 25969a6..73aa0f5 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java
@@ -160,6 +160,12 @@ public class OAuthRequestAuthenticator {
         String scope = getQueryParamValue(OAuth2Constants.SCOPE);
         url = UriUtils.stripQueryParam(url, OAuth2Constants.SCOPE);
 
+        String prompt = getQueryParamValue(OAuth2Constants.PROMPT);
+        url = UriUtils.stripQueryParam(url, OAuth2Constants.PROMPT);
+
+        String maxAge = getQueryParamValue(OAuth2Constants.MAX_AGE);
+        url = UriUtils.stripQueryParam(url, OAuth2Constants.MAX_AGE);
+
         KeycloakUriBuilder redirectUriBuilder = deployment.getAuthUrl().clone()
                 .queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
                 .queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
@@ -172,6 +178,12 @@ public class OAuthRequestAuthenticator {
         if (idpHint != null && idpHint.length() > 0) {
             redirectUriBuilder.queryParam(AdapterConstants.KC_IDP_HINT,idpHint);
         }
+        if (prompt != null && prompt.length() > 0) {
+            redirectUriBuilder.queryParam(OAuth2Constants.PROMPT, prompt);
+        }
+        if (maxAge != null && maxAge.length() > 0) {
+            redirectUriBuilder.queryParam(OAuth2Constants.MAX_AGE, maxAge);
+        }
 
         scope = TokenUtil.attachOIDCScope(scope);
         redirectUriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js
index a678528..563f7ca 100755
--- a/adapters/oidc/js/src/main/resources/keycloak.js
+++ b/adapters/oidc/js/src/main/resources/keycloak.js
@@ -224,6 +224,10 @@
                 url += '&prompt=' + encodeURIComponent(options.prompt);
             }
 
+            if (options && options.maxAge) {
+                url += '&max_age=' + encodeURIComponent(options.maxAge);
+            }
+
             if (options && options.loginHint) {
                 url += '&login_hint=' + encodeURIComponent(options.loginHint);
             }
diff --git a/core/src/main/java/org/keycloak/OAuth2Constants.java b/core/src/main/java/org/keycloak/OAuth2Constants.java
index 6c00831..188d759 100644
--- a/core/src/main/java/org/keycloak/OAuth2Constants.java
+++ b/core/src/main/java/org/keycloak/OAuth2Constants.java
@@ -73,6 +73,10 @@ public interface OAuth2Constants {
 
     String UI_LOCALES_PARAM = "ui_locales";
 
+    String PROMPT = "prompt";
+
+    String MAX_AGE = "max_age";
+
 
 }
 
diff --git a/core/src/main/java/org/keycloak/OAuthErrorException.java b/core/src/main/java/org/keycloak/OAuthErrorException.java
index eb173f2..f0bb862 100755
--- a/core/src/main/java/org/keycloak/OAuthErrorException.java
+++ b/core/src/main/java/org/keycloak/OAuthErrorException.java
@@ -29,11 +29,13 @@ public class OAuthErrorException extends Exception {
     public static final String ACCESS_DENIED = "access_denied";
     public static final String UNSUPPORTED_RESPONSE_TYPE = "unsupported_response_type";
     public static final String SERVER_ERROR = "server_error";
-    public static final String TEMPORARILY_UNAVAILABKE = "temporarily_unavailable";
+    public static final String TEMPORARILY_UNAVAILABLE = "temporarily_unavailable";
 
     // OpenID Connect 1
     public static final String INTERACTION_REQUIRED = "interaction_required";
     public static final String LOGIN_REQUIRED = "login_required";
+    public static final String REQUEST_NOT_SUPPORTED = "request_not_supported";
+    public static final String REQUEST_URI_NOT_SUPPORTED = "request_uri_not_supported";
 
     // Others
     public static final String INVALID_CLIENT = "invalid_client";
diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/PolicyEnforcerConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/PolicyEnforcerConfig.java
index 5145ec7..b2c5757 100644
--- a/core/src/main/java/org/keycloak/representations/adapters/config/PolicyEnforcerConfig.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/config/PolicyEnforcerConfig.java
@@ -18,6 +18,7 @@
 package org.keycloak.representations.adapters.config;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 import java.util.ArrayList;
@@ -30,24 +31,30 @@ import java.util.List;
 public class PolicyEnforcerConfig {
 
     @JsonProperty("create-resources")
-    private Boolean createResources;
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private Boolean createResources = Boolean.FALSE;
 
     @JsonProperty("enforcement-mode")
     private EnforcementMode enforcementMode = EnforcementMode.ENFORCING;
 
     @JsonProperty("user-managed-access")
+    @JsonInclude(JsonInclude.Include.NON_NULL)
     private UmaProtocolConfig umaProtocolConfig;
 
     @JsonProperty("entitlement")
+    @JsonInclude(JsonInclude.Include.NON_NULL)
     private EntitlementProtocolConfig entitlementProtocolConfig;
 
     @JsonProperty("paths")
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
     private List<PathConfig> paths = new ArrayList<>();
 
     @JsonProperty("online-introspection")
-    private Boolean onlineIntrospection;
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private Boolean onlineIntrospection = Boolean.FALSE;
 
     @JsonProperty("on-deny-redirect-to")
+    @JsonInclude(JsonInclude.Include.NON_NULL)
     private String accessDeniedPath;
 
     public Boolean isCreateResources() {
@@ -55,10 +62,6 @@ public class PolicyEnforcerConfig {
     }
 
     public List<PathConfig> getPaths() {
-        if (this.paths == null) {
-            return null;
-        }
-
         return Collections.unmodifiableList(this.paths);
     }
 
@@ -82,6 +85,14 @@ public class PolicyEnforcerConfig {
         return onlineIntrospection;
     }
 
+    public void setCreateResources(Boolean createResources) {
+        this.createResources = createResources;
+    }
+
+    public void setOnlineIntrospection(Boolean onlineIntrospection) {
+        this.onlineIntrospection = onlineIntrospection;
+    }
+
     public void setPaths(List<PathConfig> paths) {
         this.paths = paths;
     }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
index 10c108d..6bdf96f 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
@@ -369,7 +369,7 @@ public class CachedPolicyStore implements PolicyStore {
 
                 if (getId() == null) return false;
 
-                if (o == null || getClass() != o.getClass()) return false;
+                if (!Policy.class.isInstance(o)) return false;
 
                 Policy that = (Policy) o;
 
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/entities/CachedPolicy.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/entities/CachedPolicy.java
index fd2b488..99493bf 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/entities/CachedPolicy.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/entities/CachedPolicy.java
@@ -200,7 +200,7 @@ public class CachedPolicy implements Policy {
 
         if (o == null || getClass() != o.getClass()) return false;
 
-        AbstractIdentifiableEntity that = (AbstractIdentifiableEntity) o;
+        Policy that = (Policy) o;
 
         if (!getId().equals(that.getId())) return false;
 
diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java
index a5a6b27..540dc31 100644
--- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java
@@ -236,9 +236,9 @@ public class PolicyEntity implements Policy {
 
         if (this.id == null) return false;
 
-        if (o == null || getClass() != o.getClass()) return false;
+        if (!Policy.class.isInstance(o)) return false;
 
-        AbstractIdentifiableEntity that = (AbstractIdentifiableEntity) o;
+        Policy that = (Policy) o;
 
         if (!getId().equals(that.getId())) return false;
 
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
index 784438c..431a638 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
@@ -37,7 +37,9 @@ import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
 import org.keycloak.connections.jpa.util.JpaUtils;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.KeycloakSessionTask;
 import org.keycloak.models.dblock.DBLockProvider;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.provider.ServerInfoAwareProviderFactory;
 import org.keycloak.models.dblock.DBLockManager;
 import org.keycloak.timer.TimerProvider;
@@ -93,8 +95,6 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
                 if (emf == null) {
                     logger.debug("Initializing JPA connections");
 
-                    Connection connection = null;
-
                     Map<String, Object> properties = new HashMap<String, Object>();
 
                     String unitName = "keycloak-default";
@@ -126,23 +126,26 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
                     }
 
 
-                    String databaseSchema = config.get("databaseSchema");
-                    if (databaseSchema == null) {
+                    String databaseSchema;
+                    String databaseSchemaConf = config.get("databaseSchema");
+                    if (databaseSchemaConf == null) {
                         throw new RuntimeException("Property 'databaseSchema' needs to be specified in the configuration");
                     }
                     
-                    if (databaseSchema.equals("development-update")) {
+                    if (databaseSchemaConf.equals("development-update")) {
                         properties.put("hibernate.hbm2ddl.auto", "update");
                         databaseSchema = null;
-                    } else if (databaseSchema.equals("development-validate")) {
+                    } else if (databaseSchemaConf.equals("development-validate")) {
                         properties.put("hibernate.hbm2ddl.auto", "validate");
                         databaseSchema = null;
+                    } else {
+                        databaseSchema = databaseSchemaConf;
                     }
 
                     properties.put("hibernate.show_sql", config.getBoolean("showSql", false));
                     properties.put("hibernate.format_sql", config.getBoolean("formatSql", true));
 
-                    connection = getConnection();
+                    Connection connection = getConnection();
                     try{ 
 	                    prepareOperationalInfo(connection);
 
@@ -161,19 +164,27 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
 
                             // Check if having DBLock before trying to initialize hibernate
                             DBLockProvider dbLock = new DBLockManager(session).getDBLock();
-                            if (!dbLock.hasLock()) {
-                                throw new IllegalStateException("Trying to update database, but don't have a DB lock acquired");
+                            if (dbLock.hasLock()) {
+                                updateOrValidateDB(databaseSchema, connection, updater, schema);
+                            } else {
+                                logger.trace("Don't have DBLock retrieved before upgrade. Needs to acquire lock first in separate transaction");
+
+                                KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
+
+                                    @Override
+                                    public void run(KeycloakSession lockSession) {
+                                        DBLockManager dbLockManager = new DBLockManager(lockSession);
+                                        DBLockProvider dbLock2 = dbLockManager.getDBLock();
+                                        dbLock2.waitForLock();
+                                        try {
+                                            updateOrValidateDB(databaseSchema, connection, updater, schema);
+                                        } finally {
+                                            dbLock2.releaseLock();
+                                        }
+                                    }
+
+                                });
                             }
-	
-	                        if (databaseSchema.equals("update")) {
-                                updater.update(connection, schema);
-	                        } else if (databaseSchema.equals("validate")) {
-	                            updater.validate(connection, schema);
-	                        } else {
-	                            throw new RuntimeException("Invalid value for databaseSchema: " + databaseSchema);
-	                        }
-	
-	                        logger.trace("Database update completed");
 	                    }
 
                         int globalStatsInterval = config.getInt("globalStatsInterval", -1);
@@ -272,6 +283,20 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
     }
 
 
+    // Needs to be called with acquired DBLock
+    protected void updateOrValidateDB(String databaseSchema, Connection connection, JpaUpdaterProvider updater, String schema) {
+        if (databaseSchema.equals("update")) {
+            updater.update(connection, schema);
+            logger.trace("Database update completed");
+        } else if (databaseSchema.equals("validate")) {
+            updater.validate(connection, schema);
+            logger.trace("Database validation completed");
+        } else {
+            throw new RuntimeException("Invalid value for databaseSchema: " + databaseSchema);
+        }
+    }
+
+
     @Override
     public Connection getConnection() {
         try {
diff --git a/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
index 7fc3439..d8d87f5 100755
--- a/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
@@ -34,8 +34,10 @@ import org.keycloak.connections.mongo.impl.context.TransactionMongoStoreInvocati
 import org.keycloak.connections.mongo.updater.MongoUpdaterProvider;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.KeycloakSessionTask;
 import org.keycloak.models.dblock.DBLockManager;
 import org.keycloak.models.dblock.DBLockProvider;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.provider.ServerInfoAwareProviderFactory;
 
 import com.mongodb.DB;
@@ -174,8 +176,26 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
             }
 
             DBLockProvider dbLock = new DBLockManager(session).getDBLock();
-            if (!dbLock.hasLock()) {
-                throw new IllegalStateException("Trying to update database, but don't have a DB lock acquired");
+            if (dbLock.hasLock()) {
+                updateOrValidateDB(databaseSchema, session, mongoUpdater);
+            } else {
+                logger.trace("Don't have DBLock retrieved before upgrade. Needs to acquire lock first in separate transaction");
+
+                KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
+
+                    @Override
+                    public void run(KeycloakSession lockSession) {
+                        DBLockManager dbLockManager = new DBLockManager(lockSession);
+                        DBLockProvider dbLock2 = dbLockManager.getDBLock();
+                        dbLock2.waitForLock();
+                        try {
+                            updateOrValidateDB(databaseSchema, session, mongoUpdater);
+                        } finally {
+                            dbLock2.releaseLock();
+                        }
+                    }
+
+                });
             }
 
             if (databaseSchema.equals("update")) {
@@ -197,6 +217,16 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
         return entityClasses;
     }
 
+    protected void updateOrValidateDB(String databaseSchema, KeycloakSession session, MongoUpdaterProvider mongoUpdater) {
+        if (databaseSchema.equals("update")) {
+            mongoUpdater.update(session, db);
+        } else if (databaseSchema.equals("validate")) {
+            mongoUpdater.validate(session, db);
+        } else {
+            throw new RuntimeException("Invalid value for databaseSchema: " + databaseSchema);
+        }
+    }
+
     @Override
     public void close() {
         if (client != null) {
diff --git a/server-spi/src/main/java/org/keycloak/protocol/LoginProtocol.java b/server-spi/src/main/java/org/keycloak/protocol/LoginProtocol.java
index 6cc1be4..086a8ed 100755
--- a/server-spi/src/main/java/org/keycloak/protocol/LoginProtocol.java
+++ b/server-spi/src/main/java/org/keycloak/protocol/LoginProtocol.java
@@ -74,4 +74,11 @@ public interface LoginProtocol extends Provider {
     Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession);
     Response finishLogout(UserSessionModel userSession);
 
+    /**
+     * @param userSession
+     * @param clientSession
+     * @return true if SSO cookie authentication can't be used. User will need to "actively" reauthenticate
+     */
+    boolean requireReauthentication(UserSessionModel userSession, ClientSessionModel clientSession);
+
 }
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java
index 24d708a..6c961e1 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java
@@ -25,6 +25,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.LoginProtocol;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.AuthenticationManager;
@@ -36,8 +37,6 @@ import org.keycloak.util.TokenUtil;
  */
 public class CookieAuthenticator implements Authenticator {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
-
     @Override
     public boolean requiresUser() {
         return false;
@@ -50,11 +49,13 @@ public class CookieAuthenticator implements Authenticator {
         if (authResult == null) {
             context.attempted();
         } else {
+            ClientSessionModel clientSession = context.getClientSession();
+            LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, clientSession.getAuthMethod());
+
             // Cookie re-authentication is skipped if re-authentication is required
-            if (requireReauthentication(authResult.getSession(), context.getClientSession())) {
+            if (protocol.requireReauthentication(authResult.getSession(), clientSession)) {
                 context.attempted();
             } else {
-                ClientSessionModel clientSession = context.getClientSession();
                 clientSession.setNote(AuthenticationManager.SSO_AUTH, "true");
 
                 context.setUser(authResult.getUser());
@@ -83,32 +84,4 @@ public class CookieAuthenticator implements Authenticator {
     public void close() {
 
     }
-
-    protected boolean requireReauthentication(UserSessionModel userSession, ClientSessionModel clientSession) {
-        return isPromptLogin(clientSession) || isAuthTimeExpired(userSession, clientSession);
-    }
-
-    protected boolean isPromptLogin(ClientSessionModel clientSession) {
-        String prompt = clientSession.getNote(OIDCLoginProtocol.PROMPT_PARAM);
-        return TokenUtil.hasPrompt(prompt, OIDCLoginProtocol.PROMPT_VALUE_LOGIN);
-    }
-
-    protected boolean isAuthTimeExpired(UserSessionModel userSession, ClientSessionModel clientSession) {
-        String authTime = userSession.getNote(AuthenticationManager.AUTH_TIME);
-        String maxAge = clientSession.getNote(OIDCLoginProtocol.MAX_AGE_PARAM);
-        if (maxAge == null) {
-            return false;
-        }
-
-        int authTimeInt = authTime==null ? 0 : Integer.parseInt(authTime);
-        int maxAgeInt = Integer.parseInt(maxAge);
-
-        if (authTimeInt + maxAgeInt < Time.currentTime()) {
-            logger.debugf("Authentication time is expired in CookieAuthenticator. userSession=%s, clientId=%s, maxAge=%d, authTime=%d", userSession.getId(),
-                    clientSession.getClient().getId(), maxAgeInt, authTimeInt);
-            return true;
-        }
-
-        return false;
-    }
 }
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
index 1b54d56..d2d623c 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
@@ -42,6 +42,7 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import java.io.IOException;
@@ -177,6 +178,27 @@ public class PolicyService {
         return Response.ok(toRepresentation(model, authorization)).build();
     }
 
+    @Path("/search")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response find(@QueryParam("name") String name) {
+        this.auth.requireView();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+
+        if (name == null) {
+            return Response.status(Status.BAD_REQUEST).build();
+        }
+
+        Policy model = storeFactory.getPolicyStore().findByName(name, this.resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.OK).build();
+        }
+
+        return Response.ok(toRepresentation(model, authorization)).build();
+    }
+
     @GET
     @Produces("application/json")
     @NoCache
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java b/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java
index 7d19e83..59ba844 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java
@@ -448,7 +448,7 @@ public class ResourceServerService {
     private PolicyRepresentation createDefaultPolicy() {
         PolicyRepresentation defaultPolicy = new PolicyRepresentation();
 
-        defaultPolicy.setName("Only From Realm Policy");
+        defaultPolicy.setName("Default Policy");
         defaultPolicy.setDescription("A policy that grants access only for users within this realm");
         defaultPolicy.setType("js");
         defaultPolicy.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
@@ -456,21 +456,7 @@ public class ResourceServerService {
 
         HashMap<String, String> defaultPolicyConfig = new HashMap<>();
 
-        defaultPolicyConfig.put("code", "var context = $evaluation.getContext();\n" +
-                "\n" +
-                "// using attributes from the evaluation context to obtain the realm\n" +
-                "var contextAttributes = context.getAttributes();\n" +
-                "var realmName = contextAttributes.getValue('kc.realm.name').asString(0);\n" +
-                "\n" +
-                "// using attributes from the identity to obtain the issuer\n" +
-                "var identity = context.getIdentity();\n" +
-                "var identityAttributes = identity.getAttributes();\n" +
-                "var issuer = identityAttributes.getValue('iss').asString(0);\n" +
-                "\n" +
-                "// only users from the realm have access granted \n" +
-                "if (issuer.endsWith(realmName)) {\n" +
-                "    $evaluation.grant();\n" +
-                "}");
+        defaultPolicyConfig.put("code", "// by default, grants any permission associated with this policy\n$evaluation.grant();\n");
 
         defaultPolicy.setConfig(defaultPolicyConfig);
 
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
index 9078408..8bb4a9b 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
@@ -39,11 +39,14 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import java.util.List;
 import java.util.stream.Collectors;
 
+import static org.keycloak.authorization.admin.util.Models.toRepresentation;
+
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
@@ -148,7 +151,28 @@ public class ResourceSetService {
             return Response.status(Status.NOT_FOUND).build();
         }
 
-        return Response.ok(Models.toRepresentation(model, this.resourceServer, authorization)).build();
+        return Response.ok(toRepresentation(model, this.resourceServer, authorization)).build();
+    }
+
+    @Path("/search")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response find(@QueryParam("name") String name) {
+        this.auth.requireView();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+
+        if (name == null) {
+            return Response.status(Status.BAD_REQUEST).build();
+        }
+
+        Resource model = storeFactory.getResourceStore().findByName(name, this.resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.OK).build();
+        }
+
+        return Response.ok(toRepresentation(model, this.resourceServer, authorization)).build();
     }
 
     @GET
@@ -160,7 +184,7 @@ public class ResourceSetService {
 
         return Response.ok(
                 storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream()
-                        .map(resource -> Models.toRepresentation(resource, this.resourceServer, authorization))
+                        .map(resource -> toRepresentation(resource, this.resourceServer, authorization))
                         .collect(Collectors.toList()))
                 .build();
     }
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
index 08bbed9..97b8541 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
@@ -17,6 +17,7 @@
  */
 package org.keycloak.authorization.admin;
 
+import org.jboss.resteasy.annotations.cache.NoCache;
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.Resource;
@@ -36,6 +37,7 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import java.util.Arrays;
@@ -134,6 +136,27 @@ public class ScopeService {
         return Response.ok(toRepresentation(model, this.authorization)).build();
     }
 
+    @Path("/search")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response find(@QueryParam("name") String name) {
+        this.auth.requireView();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+
+        if (name == null) {
+            return Response.status(Status.BAD_REQUEST).build();
+        }
+
+        Scope model = storeFactory.getScopeStore().findByName(name, this.resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.OK).build();
+        }
+
+        return Response.ok(toRepresentation(model, authorization)).build();
+    }
+
     @GET
     @Produces("application/json")
     public Response findAll() {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
index 2092079..1d88ac7 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -111,6 +111,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
 
     private Action action;
     private OIDCResponseType parsedResponseType;
+    private OIDCResponseMode parsedResponseMode;
 
     private String clientId;
     private String redirectUri;
@@ -162,6 +163,11 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
             logger.oidcScopeMissing();
         }
 
+        errorResponse = checkOIDCParams(params);
+        if (errorResponse != null) {
+            return errorResponse;
+        }
+
         createClientSession();
         // So back button doesn't work
         CacheControlUtil.noBackButtonCacheControlHeader();
@@ -313,6 +319,24 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
             return redirectErrorToClient(parsedResponseMode, OAuthErrorException.UNSUPPORTED_RESPONSE_TYPE, "Client is not allowed to initiate browser login with given response_type. Implicit flow is disabled for the client.");
         }
 
+        this.parsedResponseMode = parsedResponseMode;
+
+        return null;
+    }
+
+    private Response checkOIDCParams(MultivaluedMap<String, String> params) {
+        if (params.getFirst(OIDCLoginProtocol.REQUEST_PARAM) != null) {
+            logger.unsupportedParameter(OIDCLoginProtocol.REQUEST_PARAM);
+            event.error(Errors.INVALID_REQUEST);
+            return redirectErrorToClient(parsedResponseMode, OAuthErrorException.REQUEST_NOT_SUPPORTED, null);
+        }
+
+        if (params.getFirst(OIDCLoginProtocol.REQUEST_URI_PARAM) != null) {
+            logger.unsupportedParameter(OIDCLoginProtocol.REQUEST_URI_PARAM);
+            event.error(Errors.INVALID_REQUEST);
+            return redirectErrorToClient(parsedResponseMode, OAuthErrorException.REQUEST_URI_NOT_SUPPORTED, null);
+        }
+
         return null;
     }
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java b/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java
index a7781de..6fda3f0 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java
@@ -156,7 +156,8 @@ public class KeycloakOIDCClientInstallation implements ClientInstallationProvide
             PolicyEnforcerConfig enforcerConfig = new PolicyEnforcerConfig();
 
             enforcerConfig.setEnforcementMode(null);
-            enforcerConfig.setPaths(null);
+            enforcerConfig.setCreateResources(null);
+            enforcerConfig.setOnlineIntrospection(null);
 
             rep.setEnforcerConfig(enforcerConfig);
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
index 39dc288..a68dae8 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
@@ -18,6 +18,7 @@ package org.keycloak.protocol.oidc;
 
 import org.keycloak.OAuth2Constants;
 import org.keycloak.OAuthErrorException;
+import org.keycloak.common.util.Time;
 import org.keycloak.events.Details;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
@@ -33,8 +34,10 @@ import org.keycloak.protocol.oidc.utils.OIDCResponseMode;
 import org.keycloak.protocol.oidc.utils.OIDCResponseType;
 import org.keycloak.representations.AccessTokenResponse;
 import org.keycloak.services.ServicesLogger;
+import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.managers.ResourceAdminManager;
+import org.keycloak.util.TokenUtil;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
@@ -57,9 +60,12 @@ public class OIDCLoginProtocol implements LoginProtocol {
     public static final String REDIRECT_URI_PARAM = "redirect_uri";
     public static final String CLIENT_ID_PARAM = "client_id";
     public static final String NONCE_PARAM = "nonce";
-    public static final String MAX_AGE_PARAM = "max_age";
-    public static final String PROMPT_PARAM = "prompt";
+    public static final String MAX_AGE_PARAM = OAuth2Constants.MAX_AGE;
+    public static final String PROMPT_PARAM = OAuth2Constants.PROMPT;
     public static final String LOGIN_HINT_PARAM = "login_hint";
+    public static final String REQUEST_PARAM = "request";
+    public static final String REQUEST_URI_PARAM = "request_uri";
+
     public static final String LOGOUT_REDIRECT_URI = "OIDC_LOGOUT_REDIRECT_URI";
     public static final String ISSUER = "iss";
 
@@ -242,6 +248,36 @@ public class OIDCLoginProtocol implements LoginProtocol {
         }
     }
 
+
+    @Override
+    public boolean requireReauthentication(UserSessionModel userSession, ClientSessionModel clientSession) {
+        return isPromptLogin(clientSession) || isAuthTimeExpired(userSession, clientSession);
+    }
+
+    protected boolean isPromptLogin(ClientSessionModel clientSession) {
+        String prompt = clientSession.getNote(OIDCLoginProtocol.PROMPT_PARAM);
+        return TokenUtil.hasPrompt(prompt, OIDCLoginProtocol.PROMPT_VALUE_LOGIN);
+    }
+
+    protected boolean isAuthTimeExpired(UserSessionModel userSession, ClientSessionModel clientSession) {
+        String authTime = userSession.getNote(AuthenticationManager.AUTH_TIME);
+        String maxAge = clientSession.getNote(OIDCLoginProtocol.MAX_AGE_PARAM);
+        if (maxAge == null) {
+            return false;
+        }
+
+        int authTimeInt = authTime==null ? 0 : Integer.parseInt(authTime);
+        int maxAgeInt = Integer.parseInt(maxAge);
+
+        if (authTimeInt + maxAgeInt < Time.currentTime()) {
+            logger.debugf("Authentication time is expired, needs to reauthenticate. userSession=%s, clientId=%s, maxAge=%d, authTime=%d", userSession.getId(),
+                    clientSession.getClient().getId(), maxAgeInt, authTimeInt);
+            return true;
+        }
+
+        return false;
+    }
+
     @Override
     public void close() {
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
index ddb4151..050795a 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
@@ -102,6 +102,9 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
 
         config.setScopesSupported(SCOPES_SUPPORTED);
 
+        config.setRequestParameterSupported(false);
+        config.setRequestUriParameterSupported(false);
+
         return config;
     }
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java b/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java
index 7f558b1..0421e16 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java
@@ -88,6 +88,12 @@ public class OIDCConfigurationRepresentation {
     @JsonProperty("scopes_supported")
     private List<String> scopesSupported;
 
+    @JsonProperty("request_parameter_supported")
+    private Boolean requestParameterSupported;
+
+    @JsonProperty("request_uri_parameter_supported")
+    private Boolean requestUriParameterSupported;
+
     protected Map<String, Object> otherClaims = new HashMap<String, Object>();
 
     public String getIssuer() {
@@ -242,6 +248,22 @@ public class OIDCConfigurationRepresentation {
         this.scopesSupported = scopesSupported;
     }
 
+    public Boolean getRequestParameterSupported() {
+        return requestParameterSupported;
+    }
+
+    public void setRequestParameterSupported(Boolean requestParameterSupported) {
+        this.requestParameterSupported = requestParameterSupported;
+    }
+
+    public Boolean getRequestUriParameterSupported() {
+        return requestUriParameterSupported;
+    }
+
+    public void setRequestUriParameterSupported(Boolean requestUriParameterSupported) {
+        this.requestUriParameterSupported = requestUriParameterSupported;
+    }
+
     @JsonAnyGetter
     public Map<String, Object> getOtherClaims() {
         return otherClaims;
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index 042779f..85e316f 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -629,6 +629,12 @@ public class SamlProtocol implements LoginProtocol {
         return logoutBuilder;
     }
 
+    @Override
+    public boolean requireReauthentication(UserSessionModel userSession, ClientSessionModel clientSession) {
+        // Not yet supported
+        return false;
+    }
+
     private JaxrsSAML2BindingBuilder createBindingBuilder(SamlClient samlClient) {
         JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder();
         if (samlClient.requiresRealmSignature()) {
diff --git a/services/src/main/java/org/keycloak/services/ServicesLogger.java b/services/src/main/java/org/keycloak/services/ServicesLogger.java
index 7967e34..8aa4961 100644
--- a/services/src/main/java/org/keycloak/services/ServicesLogger.java
+++ b/services/src/main/java/org/keycloak/services/ServicesLogger.java
@@ -419,6 +419,10 @@ public interface ServicesLogger extends BasicLogger {
     void invalidParameter(String paramName);
 
     @LogMessage(level = ERROR)
-    @Message(id=94, value="Client is not allowed to initiate browser login with given response_type. %s flow is disabled for the client.")
+    @Message(id=94, value="Unsupported parameter: %s")
+    void unsupportedParameter(String paramName);
+
+    @LogMessage(level = ERROR)
+    @Message(id=95, value="Client is not allowed to initiate browser login with given response_type. %s flow is disabled for the client.")
     void flowNotAllowed(String flowName);
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractPage.java
index 62510e0..5ed6afd 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractPage.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractPage.java
@@ -72,6 +72,11 @@ public abstract class AbstractPage {
         return this;
     }
 
+    public AbstractPage removeUriParameter(String name) {
+        uriParameters.remove(name);
+        return this;
+    }
+
     public Object getUriParameter(String name) {
         return uriParameters.get(name);
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java
index 3b67027..5191e55 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java
@@ -25,7 +25,9 @@ import org.junit.Ignore;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.common.Version;
+import org.keycloak.common.util.Time;
 import org.keycloak.constants.AdapterConstants;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.VersionRepresentation;
@@ -33,6 +35,7 @@ import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
 import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter;
 import org.keycloak.testsuite.adapter.page.*;
+import org.keycloak.testsuite.util.URLUtils;
 import org.keycloak.util.BasicAuthHelper;
 
 import javax.ws.rs.client.Client;
@@ -448,5 +451,32 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
         setAdapterAndServerTimeOffset(0, tokenMinTTLPage.toString());
     }
 
+    // Tests forwarding of parameters like "prompt"
+    @Test
+    public void testOIDCParamsForwarding() {
+        // test login to customer-portal which does a bearer request to customer-db
+        securePortal.navigateTo();
+        assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
+        testRealmLoginPage.form().login("bburke@redhat.com", "password");
+        assertCurrentUrlEquals(securePortal);
+        String pageSource = driver.getPageSource();
+        assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen"));
+
+        int currentTime = Time.currentTime();
+        setAdapterAndServerTimeOffset(10, securePortal.toString());
+
+        // Test I need to reauthenticate with prompt=login
+        String appUri = tokenMinTTLPage.getUriBuilder().queryParam(OIDCLoginProtocol.PROMPT_PARAM, OIDCLoginProtocol.PROMPT_VALUE_LOGIN).build().toString();
+        URLUtils.navigateToUri(driver, appUri, true);
+        assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
+        testRealmLoginPage.form().login("bburke@redhat.com", "password");
+        AccessToken token = tokenMinTTLPage.getAccessToken();
+        int authTime = token.getAuthTime();
+        Assert.assertTrue(currentTime + 10 <= authTime);
+
+        // Revert times
+        setAdapterAndServerTimeOffset(0, tokenMinTTLPage.toString());
+    }
+
 
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java
index bdc582c..db691b2 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java
@@ -289,6 +289,78 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
     }
 
 
-    // prompt=consent
+    // NONCE
+
+    @Test
+    public void nonceNotUsed() {
+        driver.navigate().to(oauth.getLoginFormUrl());
+
+        loginPage.assertCurrent();
+        loginPage.login("test-user@localhost", "password");
+        Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
+        IDToken idToken = sendTokenRequestAndGetIDToken(loginEvent);
+
+        Assert.assertNull(idToken.getNonce());
+    }
+
+    @Test
+    public void nonceMatches() {
+        driver.navigate().to(oauth.getLoginFormUrl() + "&nonce=abcdef123456");
+
+        loginPage.assertCurrent();
+        loginPage.login("test-user@localhost", "password");
+        Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
+        IDToken idToken = sendTokenRequestAndGetIDToken(loginEvent);
+
+        Assert.assertEquals("abcdef123456", idToken.getNonce());
+    }
+
+    // DISPLAY & OTHERS
+
+    @Test
+    public void nonSupportedParams() {
+        driver.navigate().to(oauth.getLoginFormUrl() + "&display=popup&foo=foobar");
+
+        loginPage.assertCurrent();
+        loginPage.login("test-user@localhost", "password");
+        Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
+        IDToken idToken = sendTokenRequestAndGetIDToken(loginEvent);
+
+        Assert.assertNotNull(idToken);
+    }
+
+    // REQUEST & REQUEST_URI
+
+    @Test
+    public void requestParam() {
+        driver.navigate().to(oauth.getLoginFormUrl() + "&request=abc");
+
+        assertFalse(loginPage.isCurrent());
+        assertTrue(appPage.isCurrent());
+
+        // Assert error response was sent because not logged in
+        OAuthClient.AuthorizationCodeResponse resp = new OAuthClient.AuthorizationCodeResponse(oauth);
+        Assert.assertNull(resp.getCode());
+        Assert.assertEquals(OAuthErrorException.REQUEST_NOT_SUPPORTED, resp.getError());
+    }
+
+    @Test
+    public void requestUriParam() {
+        driver.navigate().to(oauth.getLoginFormUrl() + "&request_uri=https%3A%2F%2Flocalhost%3A60784%2Fexport%2FqzHTG11W48.jwt");
+
+        assertFalse(loginPage.isCurrent());
+        assertTrue(appPage.isCurrent());
+
+        // Assert error response was sent because not logged in
+        OAuthClient.AuthorizationCodeResponse resp = new OAuthClient.AuthorizationCodeResponse(oauth);
+        Assert.assertNull(resp.getCode());
+        Assert.assertEquals(OAuthErrorException.REQUEST_URI_NOT_SUPPORTED, resp.getError());
+    }
 
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java
index 24188fc..ab5c230 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java
@@ -98,6 +98,10 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
 
             // Scopes supported
             Assert.assertNames(oidcConfig.getScopesSupported(), OAuth2Constants.SCOPE_OPENID, OAuth2Constants.OFFLINE_ACCESS);
+
+            // Request and Request_Uri
+            Assert.assertFalse(oidcConfig.getRequestParameterSupported());
+            Assert.assertFalse(oidcConfig.getRequestUriParameterSupported());
         } finally {
             client.close();
         }
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
index 216a5a9..680cb5b 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
@@ -107,6 +107,8 @@ module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $r
         $scope.scopes = data;
     });
 
+    var $instance = this;
+
     ResourceServer.get({
         realm : $route.current.params.realm,
         client : client.id
@@ -131,9 +133,11 @@ module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $r
             }, true);
 
             $scope.save = function() {
-                ResourceServerResource.save({realm : realm.realm, client : $scope.client.id}, $scope.resource, function(data) {
-                    $location.url("/realms/" + realm.realm + "/clients/" + $scope.client.id + "/authz/resource-server/resource/" + data._id);
-                    Notifications.success("The resource has been created.");
+                $instance.checkNameAvailability(function () {
+                    ResourceServerResource.save({realm : realm.realm, client : $scope.client.id}, $scope.resource, function(data) {
+                        $location.url("/realms/" + realm.realm + "/clients/" + $scope.client.id + "/authz/resource-server/resource/" + data._id);
+                        Notifications.success("The resource has been created.");
+                    });
                 });
             }
 
@@ -153,6 +157,10 @@ module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $r
                     $scope.resource.scopes[i] = $scope.resource.scopes[i].name;
                 }
 
+                data = angular.copy($scope.resource);
+
+                $scope.originalResource = data;
+
                 $scope.$watch('resource', function() {
                     if (!angular.equals($scope.resource, data)) {
                         $scope.changed = true;
@@ -160,9 +168,11 @@ module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $r
                 }, true);
 
                 $scope.save = function() {
-                    ResourceServerResource.update({realm : realm.realm, client : $scope.client.id, rsrid : $scope.resource._id}, $scope.resource, function() {
-                        $route.reload();
-                        Notifications.success("The resource has been updated.");
+                    $instance.checkNameAvailability(function () {
+                        ResourceServerResource.update({realm : realm.realm, client : $scope.client.id, rsrid : $scope.resource._id}, $scope.resource, function() {
+                            $route.reload();
+                            Notifications.success("The resource has been updated.");
+                        });
                     });
                 }
 
@@ -188,12 +198,30 @@ module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $r
                 }
 
                 $scope.reset = function() {
-                    $scope.resource = angular.copy(data);
-                    $scope.changed = false;
+                    $route.reload();
                 }
             });
         }
     });
+
+    $scope.checkNewNameAvailability = function () {
+        $instance.checkNameAvailability(function () {});
+    }
+
+    this.checkNameAvailability = function (onSuccess) {
+        ResourceServerResource.search({
+            realm : $route.current.params.realm,
+            client : client.id,
+            rsrid : $route.current.params.rsrid,
+            name: $scope.resource.name
+        }, function(data) {
+            if (data && data._id && data._id != $scope.resource._id) {
+                Notifications.error("Name already in use by another resource, please choose another one.");
+            } else {
+                onSuccess();
+            }
+        });
+    }
 });
 
 module.controller('ResourceServerScopeCtrl', function($scope, $http, $route, $location, realm, ResourceServer, ResourceServerScope, client) {
@@ -216,6 +244,8 @@ module.controller('ResourceServerScopeDetailCtrl', function($scope, $http, $rout
     $scope.realm = realm;
     $scope.client = client;
 
+    var $instance = this;
+
     ResourceServer.get({
         realm : $route.current.params.realm,
         client : client.id
@@ -230,7 +260,7 @@ module.controller('ResourceServerScopeDetailCtrl', function($scope, $http, $rout
 
             var scope = {};
 
-            $scope.resource = angular.copy(scope);
+            $scope.scope = angular.copy(scope);
 
             $scope.$watch('scope', function() {
                 if (!angular.equals($scope.scope, scope)) {
@@ -239,9 +269,11 @@ module.controller('ResourceServerScopeDetailCtrl', function($scope, $http, $rout
             }, true);
 
             $scope.save = function() {
-                ResourceServerScope.save({realm : realm.realm, client : $scope.client.id}, $scope.scope, function(data) {
-                    $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/scope/" + data.id);
-                    Notifications.success("The scope has been created.");
+                $instance.checkNameAvailability(function () {
+                    ResourceServerScope.save({realm : realm.realm, client : $scope.client.id}, $scope.scope, function(data) {
+                        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/scope/" + data.id);
+                        Notifications.success("The scope has been created.");
+                    });
                 });
             }
         } else {
@@ -259,10 +291,14 @@ module.controller('ResourceServerScopeDetailCtrl', function($scope, $http, $rout
                     }
                 }, true);
 
+                $scope.originalScope = angular.copy($scope.scope);
+
                 $scope.save = function() {
-                    ResourceServerScope.update({realm : realm.realm, client : $scope.client.id, id : $scope.scope.id}, $scope.scope, function() {
-                        $scope.changed = false;
-                        Notifications.success("The scope has been updated.");
+                    $instance.checkNameAvailability(function () {
+                        ResourceServerScope.update({realm : realm.realm, client : $scope.client.id, id : $scope.scope.id}, $scope.scope, function() {
+                            $scope.changed = false;
+                            Notifications.success("The scope has been updated.");
+                        });
                     });
                 }
 
@@ -288,12 +324,29 @@ module.controller('ResourceServerScopeDetailCtrl', function($scope, $http, $rout
                 }
 
                 $scope.reset = function() {
-                    $scope.scope = angular.copy(data);
-                    $scope.changed = false;
+                    $route.reload();
                 }
             });
         }
     });
+
+    $scope.checkNewNameAvailability = function () {
+        $instance.checkNameAvailability(function () {});
+    }
+
+    this.checkNameAvailability = function (onSuccess) {
+        ResourceServerScope.search({
+            realm : $route.current.params.realm,
+            client : client.id,
+            name: $scope.scope.name
+        }, function(data) {
+            if (data && data.id && data.id != $scope.scope.id) {
+                Notifications.error("Name already in use by another scope, please choose another one.");
+            } else {
+                onSuccess();
+            }
+        });
+    }
 });
 
 module.controller('ResourceServerPolicyCtrl', function($scope, $http, $route, $location, realm, ResourceServer, ResourceServerPolicy, PolicyProvider, client) {
@@ -845,6 +898,8 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
 
         delegate.onInit();
 
+        var $instance = this;
+
         ResourceServer.get({
             realm : $route.current.params.realm,
             client : client.id
@@ -876,17 +931,19 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                 }, true);
 
                 $scope.save = function() {
-                    if (delegate.onCreate) {
-                        delegate.onCreate();
-                    }
-                    ResourceServerPolicy.save({realm : realm.realm, client : client.id}, $scope.policy, function(data) {
-                        if (delegate.isPermission()) {
-                            $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/" + $scope.policy.type + "/" + data.id);
-                            Notifications.success("The permission has been created.");
-                        } else {
-                            $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/" + $scope.policy.type + "/" + data.id);
-                            Notifications.success("The policy has been created.");
+                    $instance.checkNameAvailability(function () {
+                        if (delegate.onCreate) {
+                            delegate.onCreate();
                         }
+                        ResourceServerPolicy.save({realm : realm.realm, client : client.id}, $scope.policy, function(data) {
+                            if (delegate.isPermission()) {
+                                $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/" + $scope.policy.type + "/" + data.id);
+                                Notifications.success("The permission has been created.");
+                            } else {
+                                $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/" + $scope.policy.type + "/" + data.id);
+                                Notifications.success("The policy has been created.");
+                            }
+                        });
                     });
                 }
 
@@ -903,6 +960,7 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                     client : client.id,
                     id : $route.current.params.id,
                 }, function(data) {
+                    $scope.originalPolicy = data;
                     var policy = angular.copy(data);
 
                     if (delegate.onInitUpdate) {
@@ -919,16 +977,18 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                     }, true);
 
                     $scope.save = function() {
-                        if (delegate.onUpdate) {
-                            delegate.onUpdate();
-                        }
-                        ResourceServerPolicy.update({realm : realm.realm, client : client.id, id : $scope.policy.id}, $scope.policy, function() {
-                            $route.reload();
-                            if (delegate.isPermission()) {
-                                Notifications.success("The permission has been updated.");
-                            } else {
-                                Notifications.success("The policy has been updated.");
+                        $instance.checkNameAvailability(function () {
+                            if (delegate.onUpdate) {
+                                delegate.onUpdate();
                             }
+                            ResourceServerPolicy.update({realm : realm.realm, client : client.id, id : $scope.policy.id}, $scope.policy, function() {
+                                $route.reload();
+                                if (delegate.isPermission()) {
+                                    Notifications.success("The permission has been updated.");
+                                } else {
+                                    Notifications.success("The policy has been updated.");
+                                }
+                            });
                         });
                     }
 
@@ -971,11 +1031,31 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                 }
             }
         });
+
+        $scope.checkNewNameAvailability = function () {
+            $instance.checkNameAvailability(function () {});
+        }
+
+        this.checkNameAvailability = function (onSuccess) {
+            ResourceServerPolicy.search({
+                realm: $route.current.params.realm,
+                client: client.id,
+                name: $scope.policy.name
+            }, function(data) {
+                if (data && data.id && data.id != $scope.policy.id) {
+                    Notifications.error("Name already in use by another policy or permission, please choose another one.");
+                } else {
+                    onSuccess();
+                }
+            });
+        }
     }
 
     return PolicyController;
 });
 
+
+
 module.controller('PolicyEvaluateCtrl', function($scope, $http, $route, $location, realm, clients, roles, ResourceServer, client, ResourceServerResource, ResourceServerScope, User, Notifications) {
     $scope.realm = realm;
     $scope.client = client;
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js
index e611430..795cf1d 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js
@@ -15,7 +15,8 @@ module.factory('ResourceServerResource', function($resource) {
         client: '@client',
         rsrid : '@rsrid'
     }, {
-        'update' : {method : 'PUT'}
+        'update' : {method : 'PUT'},
+        'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/resource/search', method : 'GET'}
     });
 });
 
@@ -25,7 +26,8 @@ module.factory('ResourceServerScope', function($resource) {
         client: '@client',
         id : '@id'
     }, {
-        'update' : {method : 'PUT'}
+        'update' : {method : 'PUT'},
+        'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/scope/search', method : 'GET'}
     });
 });
 
@@ -35,7 +37,8 @@ module.factory('ResourceServerPolicy', function($resource) {
         client: '@client',
         id : '@id'
     }, {
-        'update' : {method : 'PUT'}
+        'update' : {method : 'PUT'},
+        'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/search', method : 'GET'}
     });
 });
 
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
index 3d6a7bb..a8d4512 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
@@ -6,18 +6,18 @@
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server">{{:: 'authz-authorization' | translate}}</a></li>
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission">{{:: 'authz-permissions' | translate}}</a></li>
         <li data-ng-show="create">{{:: 'authz-add-resource-permission' | translate}}</li>
-        <li data-ng-hide="create">{{policy.name}}</li>
+        <li data-ng-hide="create">{{originalPolicy.name}}</li>
     </ol>
 
     <h1 data-ng-show="create">{{:: 'authz-add-resource-permission' | translate}}</h1>
-    <h1 data-ng-hide="create">{{policy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-hide="create">{{originalPolicy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-click="remove()"></i></h1>
 
     <form class="form-horizontal" name="clientForm" novalidate>
         <fieldset class="border-top">
             <div class="form-group">
                 <label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} <span class="required">*</span></label>
                 <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required>
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required data-ng-blur="checkNewNameAvailability()">
                 </div>
                 <kc-tooltip>{{:: 'authz-permission-name.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -83,13 +83,9 @@
             <input type="hidden" data-ng-model="policy.type"/>
         </fieldset>
 
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+        <div class="form-group" data-ng-show="access.manageAuthorization">
+            <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create">
-                <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html
index 969a4cc..3d1660b 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html
@@ -6,18 +6,18 @@
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server">{{:: 'authz-authorization' | translate}}</a></li>
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission">{{:: 'authz-permissions' | translate}}</a></li>
         <li data-ng-show="create">{{:: 'authz-add-scope-permission' | translate}}</li>
-        <li data-ng-hide="create">{{policy.name}}</li>
+        <li data-ng-hide="create">{{originalPolicy.name}}</li>
     </ol>
 
     <h1 data-ng-show="create">{{:: 'authz-add-scope-permission' | translate}}</h1>
-    <h1 data-ng-hide="create">{{policy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-hide="create">{{originalPolicy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-click="remove()"></i></h1>
 
     <form class="form-horizontal" name="clientForm" novalidate>
         <fieldset class="border-top">
             <div class="form-group">
                 <label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} <span class="required">*</span></label>
                 <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required>
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required data-ng-blur="checkNewNameAvailability()">
                 </div>
                 <kc-tooltip>{{:: 'authz-permission-name.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -96,13 +96,9 @@
             <input type="hidden" data-ng-model="policy.type"/>
         </fieldset>
 
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+        <div class="form-group" data-ng-show="access.manageAuthorization">
+            <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
-                <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html
index 4607adb..7888f21 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html
@@ -7,11 +7,11 @@
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy">{{:: 'authz-policies' | translate}}</a></li>
         <li data-ng-show="create">{{:: 'authz-add-aggregated-policy' | translate}}</li>
         <li data-ng-hide="create">{{:: 'authz-aggregated' | translate}}</li>
-        <li data-ng-hide="create">{{policy.name}}</li>
+        <li data-ng-hide="create">{{originalPolicy.name}}</li>
     </ol>
 
     <h1 data-ng-show="create">{{:: 'authz-add-aggregated-policy' | translate}}</h1>
-    <h1 data-ng-hide="create">{{policy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
+    <h1 data-ng-hide="create">{{originalPolicy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
                                                          data-ng-click="remove()"></i></h1>
 
     <form class="form-horizontal" name="clientForm" novalidate>
@@ -19,7 +19,7 @@
             <div class="form-group">
                 <label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} <span class="required">*</span></label>
                 <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required>
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required data-ng-blur="checkNewNameAvailability()">
                 </div>
                 <kc-tooltip>{{:: 'authz-policy-name.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -72,13 +72,9 @@
             <input type="hidden" data-ng-model="policy.type"/>
         </fieldset>
 
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+        <div class="form-group" data-ng-show="access.manageAuthorization">
+            <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
-                <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html
index 8a268f6..a121f17 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html
@@ -7,11 +7,11 @@
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy">{{:: 'authz-policies' | translate}}</a></li>
         <li data-ng-show="create">{{:: 'authz-add-drools-policy' | translate}}</li>
         <li data-ng-hide="create">Drools</li>
-        <li data-ng-hide="create">{{policy.name}}</li>
+        <li data-ng-hide="create">{{originalPolicy.name}}</li>
     </ol>
 
     <h1 data-ng-show="create">{{:: 'authz-add-drools-policy' | translate}}</h1>
-    <h1 data-ng-hide="create">{{policy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
+    <h1 data-ng-hide="create">{{originalPolicy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
                                                          data-ng-click="remove()"></i></h1>
 
     <form class="form-horizontal" name="clientForm" novalidate>
@@ -19,7 +19,7 @@
             <div class="form-group">
                 <label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} <span class="required">*</span></label>
                 <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required>
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required data-ng-blur="checkNewNameAvailability()">
                 </div>
                 <kc-tooltip>{{:: 'authz-policy-name.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -112,13 +112,9 @@
             <input type="hidden" data-ng-model="policy.type"/>
         </fieldset>
 
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+        <div class="form-group" data-ng-show="access.manageAuthorization">
+            <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create">
-                <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html
index 7966ac2..fb2fbc4 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html
@@ -10,18 +10,18 @@
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy">{{:: 'authz-policies' | translate}}</a></li>
         <li data-ng-show="create">{{:: 'authz-add-js-policy' | translate}}</li>
         <li data-ng-hide="create">JavaScript</li>
-        <li data-ng-hide="create">{{policy.name}}</li>
+        <li data-ng-hide="create">{{originalPolicy.name}}</li>
     </ol>
 
     <h1 data-ng-show="create">{{:: 'authz-add-js-policy' | translate}}</h1>
-    <h1 data-ng-hide="create">{{policy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-hide="create">{{originalPolicy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-click="remove()"></i></h1>
 
     <form class="form-horizontal" name="clientForm" novalidate>
         <fieldset class="border-top">
             <div class="form-group">
                 <label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} <span class="required">*</span></label>
                 <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required>
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required data-ng-blur="checkNewNameAvailability()">
                 </div>
                 <kc-tooltip>{{:: 'authz-policy-name.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -55,13 +55,9 @@
             <input type="hidden" data-ng-model="policy.type"/>
         </fieldset>
 
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+        <div class="form-group" data-ng-show="access.manageAuthorization">
+            <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create">
-                <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html
index 8a17870..9b0c199 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html
@@ -25,11 +25,11 @@
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy">{{:: 'authz-policies' | translate}}</a></li>
         <li data-ng-show="create">{{:: 'authz-add-role-policy' | translate}}</li>
         <li data-ng-hide="create">{{:: 'roles' | translate}}</li>
-        <li data-ng-hide="create">{{policy.name}}</li>
+        <li data-ng-hide="create">{{originalPolicy.name}}</li>
     </ol>
 
     <h1 data-ng-show="create">{{:: 'authz-add-role-policy' | translate}}</h1>
-    <h1 data-ng-hide="create">{{policy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
+    <h1 data-ng-hide="create">{{originalPolicy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
                                                          data-ng-click="remove()"></i></h1>
 
     <form class="form-horizontal" name="clientForm" novalidate>
@@ -37,7 +37,7 @@
             <div class="form-group">
                 <label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} <span class="required">*</span></label>
                 <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required>
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required data-ng-blur="checkNewNameAvailability()">
                 </div>
                 <kc-tooltip>{{:: 'authz-policy-name.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -99,13 +99,9 @@
             <input type="hidden" data-ng-model="policy.type"/>
         </fieldset>
 
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+        <div class="form-group" data-ng-show="access.manageAuthorization">
+            <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
-                <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
index 10468d5..fc4af74 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
@@ -10,19 +10,19 @@
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy">{{:: 'authz-policies' | translate}}</a></li>
         <li data-ng-show="create">{{:: 'authz-add-time-policy' | translate}}</li>
         <li data-ng-hide="create">{{:: 'time' | translate}}</li>
-        <li data-ng-hide="create">{{policy.name}}</li>
+        <li data-ng-hide="create">{{originalPolicy.name}}</li>
     </ol>
 
 
     <h1 data-ng-show="create">{{:: 'authz-add-time-policy' | translate}}</h1>
-    <h1 data-ng-hide="create">{{policy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-hide="create">{{originalPolicy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-click="remove()"></i></h1>
 
     <form class="form-horizontal" name="clientForm" novalidate>
         <fieldset class="border-top">
             <div class="form-group">
                 <label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} <span class="required">*</span></label>
                 <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required>
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required data-ng-blur="checkNewNameAvailability()">
                 </div>
                 <kc-tooltip>{{:: 'authz-policy-name.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -65,13 +65,9 @@
             <input type="hidden" data-ng-model="policy.type"/>
         </fieldset>
 
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+        <div class="form-group" data-ng-show="access.manageAuthorization">
+            <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create">
-                <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html
index 977a2ac..6b56f37 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html
@@ -7,11 +7,11 @@
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy">{{:: 'authz-policies' | translate}}</a></li>
         <li data-ng-show="create">{{:: 'authz-add-user-policy' | translate}}</li>
         <li data-ng-hide="create">{{:: 'user' | translate}}</li>
-        <li data-ng-hide="create">{{policy.name}}</li>
+        <li data-ng-hide="create">{{originalPolicy.name}}</li>
     </ol>
 
     <h1 data-ng-show="create">{{:: 'authz-add-user-policy' | translate}}</h1>
-    <h1 data-ng-hide="create">{{policy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
+    <h1 data-ng-hide="create">{{originalPolicy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
                                                          data-ng-click="remove()"></i></h1>
 
     <form class="form-horizontal" name="clientForm" novalidate>
@@ -19,7 +19,7 @@
             <div class="form-group">
                 <label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} <span class="required">*</span></label>
                 <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required>
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required data-ng-blur="checkNewNameAvailability()">
                 </div>
                 <kc-tooltip>{{:: 'authz-policy-name.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -80,13 +80,9 @@
             <input type="hidden" data-ng-model="policy.type"/>
         </fieldset>
 
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+        <div class="form-group" data-ng-show="access.manageAuthorization">
+            <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
-                <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-detail.html
index f7d1482..1110043 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-detail.html
@@ -43,13 +43,9 @@
                 </div>
                 <kc-tooltip>{{:: 'authz-remote-resource-management.tooltip' | translate}}</kc-tooltip>
             </div>
-            <div class="form-group">
-                <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+            <div class="form-group" data-ng-show="access.manageAuthorization">
+                <div class="col-md-10 col-md-offset-2">
                     <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                    <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-                </div>
-                <div class="col-md-10 col-md-offset-2" data-ng-show="!create">
-                    <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                     <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
                 </div>
             </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-detail.html
index be105f8..f61c6e9 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-detail.html
@@ -6,11 +6,11 @@
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server">{{:: 'authz-authorization' | translate}}</a></li>
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/resource">{{:: 'authz-resource' | translate}}</a></li>
         <li data-ng-show="create">{{:: 'authz-add-resource' | translate}}</li>
-        <li data-ng-hide="create">{{resource.name}}</li>
+        <li data-ng-hide="create">{{originalResource.name}}</li>
     </ol>
 
     <h1 data-ng-show="create">{{:: 'authz-add-resource' | translate}}</h1>
-    <h1 data-ng-hide="create">{{resource.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
+    <h1 data-ng-hide="create">{{originalResource.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
                                                          data-ng-click="remove()"></i></h1>
 
     <form class="form-horizontal" name="clientForm" novalidate>
@@ -18,7 +18,7 @@
             <div class="form-group">
                 <label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} <span class="required" data-ng-show="create">*</span></label>
                 <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="resource.name" autofocus required>
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="resource.name" autofocus required data-ng-blur="checkNewNameAvailability()">
                 </div>
                 <kc-tooltip>{{:: 'authz-resource-name.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -63,13 +63,9 @@
             </div>
         </fieldset>
 
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+        <div class="form-group" data-ng-show="access.manageAuthorization">
+            <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create">
-                <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-detail.html
index 2af5bf3..fac9c9c 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-detail.html
@@ -6,11 +6,11 @@
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server">{{:: 'authz-authorization' | translate}}</a></li>
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/scope">{{:: 'authz-scope' | translate}}</a></li>
         <li data-ng-show="create">{{:: 'authz-add-scope' | translate}}</li>
-        <li data-ng-hide="create">{{scope.name}}</li>
+        <li data-ng-hide="create">{{originalScope.name}}</li>
     </ol>
 
     <h1 data-ng-show="create">{{:: 'authz-add-scope' | translate}}</h1>
-    <h1 data-ng-hide="create">{{scope.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
+    <h1 data-ng-hide="create">{{originalScope.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
                                                          data-ng-hide="changed" data-ng-click="remove()"></i></h1>
 
     <form class="form-horizontal" name="clientForm" novalidate>
@@ -18,7 +18,7 @@
             <div class="form-group">
                 <label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} </label>
                 <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="scope.name" autofocus>
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="scope.name" autofocus data-ng-blur="checkNewNameAvailability()">
                 </div>
                 <kc-tooltip>{{:: 'authz-scope-name.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -31,13 +31,9 @@
             </div>
         </fieldset>
 
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+        <div class="form-group" data-ng-show="access.manageAuthorization">
+            <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
-                <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
         </div>