keycloak-aplcache

creds

9/22/2016 8:57:39 PM

Changes

distribution/src-dist/pom.xml 69(+0 -69)

pom.xml 19(+13 -6)

README.md 4(+2 -2)

Details

diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
index d7985b0..925a0db 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
@@ -17,26 +17,21 @@
 
 package org.keycloak.adapters;
 
-import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
 import org.jboss.logging.Logger;
 import org.keycloak.adapters.authentication.ClientCredentialsProvider;
+import org.keycloak.adapters.authorization.PolicyEnforcer;
+import org.keycloak.adapters.rotation.PublicKeyLocator;
 import org.keycloak.adapters.spi.HttpFacade;
 import org.keycloak.common.enums.RelativeUrlsUsed;
 import org.keycloak.common.enums.SslRequired;
 import org.keycloak.enums.TokenStore;
 import org.keycloak.representations.adapters.config.AdapterConfig;
-import org.keycloak.representations.idm.PublishedRealmRepresentation;
-import org.keycloak.util.JsonSerialization;
 import org.keycloak.common.util.KeycloakUriBuilder;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URI;
-import java.security.PublicKey;
 import java.util.Map;
 
 /**
@@ -57,7 +52,7 @@ public class AdapterDeploymentContext {
      * during the application deployment's life cycle.
      *
      * @param deployment A KeycloakConfigResolver, possibly missing the Auth
-     *                   Server URL and/or Realm Public Key
+     *                   Server URL
      */
     public AdapterDeploymentContext(KeycloakDeployment deployment) {
         this.deployment = deployment;
@@ -79,7 +74,6 @@ public class AdapterDeploymentContext {
     /**
      * For single-tenant deployments, it complements KeycloakDeployment
      * by resolving a relative Auth Server's URL based on the current request
-     * and, if needed, will lazily resolve the Realm's Public Key.
      *
      * For multi-tenant deployments, defers the resolution of KeycloakDeployment
      * to the KeycloakConfigResolver .
@@ -98,8 +92,8 @@ public class AdapterDeploymentContext {
         if (deployment.getAuthServerBaseUrl() == null) return deployment;
 
         KeycloakDeployment resolvedDeployment = resolveUrls(deployment, facade);
-        if (resolvedDeployment.getRealmKey() == null) {
-            resolveRealmKey(resolvedDeployment);
+        if (resolvedDeployment.getPublicKeyLocator() == null) {
+            throw new RuntimeException("KeycloakDeployment was never initialized through appropriate SPIs");
         }
         return resolvedDeployment;
     }
@@ -115,45 +109,6 @@ public class AdapterDeploymentContext {
         }
     }
 
-    public void resolveRealmKey(KeycloakDeployment deployment) {
-        if (deployment.getClient() == null) {
-            throw new RuntimeException("KeycloakDeployment was never initialized through appropriate SPIs");
-        }
-        HttpGet get = new HttpGet(deployment.getRealmInfoUrl());
-        try {
-            HttpResponse response = deployment.getClient().execute(get);
-            int status = response.getStatusLine().getStatusCode();
-            if (status != 200) {
-                close(response);
-                throw new RuntimeException("Unable to resolve realm public key remotely, status = " + status);
-            }
-            HttpEntity entity = response.getEntity();
-            if (entity == null) {
-                throw new RuntimeException("Unable to resolve realm public key remotely.  There was no entity.");
-            }
-            InputStream is = entity.getContent();
-            try {
-                ByteArrayOutputStream os = new ByteArrayOutputStream();
-                int c;
-                while ((c = is.read()) != -1) {
-                    os.write(c);
-                }
-                byte[] bytes = os.toByteArray();
-                String json = new String(bytes);
-                PublishedRealmRepresentation rep = JsonSerialization.readValue(json, PublishedRealmRepresentation.class);
-                deployment.setRealmKey(rep.getPublicKey());
-            } finally {
-                try {
-                    is.close();
-                } catch (IOException ignored) {
-
-                }
-            }
-        } catch (IOException e) {
-            throw new RuntimeException("Unable to resolve realm public key remotely", e);
-        }
-    }
-
     /**
      * This delegate is used to store temporary, per-request metadata like request resolved URLs.
      * Ever method is delegated except URL get methods and isConfigured()
@@ -208,6 +163,11 @@ public class AdapterDeploymentContext {
         }
 
         @Override
+        public String getJwksUrl() {
+            return (this.jwksUrl != null) ? this.jwksUrl : delegate.getJwksUrl();
+        }
+
+        @Override
         public String getResourceName() {
             return delegate.getResourceName();
         }
@@ -223,13 +183,13 @@ public class AdapterDeploymentContext {
         }
 
         @Override
-        public PublicKey getRealmKey() {
-            return delegate.getRealmKey();
+        public void setPublicKeyLocator(PublicKeyLocator publicKeyLocator) {
+            delegate.setPublicKeyLocator(publicKeyLocator);
         }
 
         @Override
-        public void setRealmKey(PublicKey realmKey) {
-            delegate.setRealmKey(realmKey);
+        public PublicKeyLocator getPublicKeyLocator() {
+            return delegate.getPublicKeyLocator();
         }
 
         @Override
@@ -466,6 +426,26 @@ public class AdapterDeploymentContext {
         public void setTokenMinimumTimeToLive(final int tokenMinimumTimeToLive) {
             delegate.setTokenMinimumTimeToLive(tokenMinimumTimeToLive);
         }
+
+        @Override
+        public PolicyEnforcer getPolicyEnforcer() {
+            return delegate.getPolicyEnforcer();
+        }
+
+        @Override
+        public void setPolicyEnforcer(PolicyEnforcer policyEnforcer) {
+            delegate.setPolicyEnforcer(policyEnforcer);
+        }
+
+        @Override
+        public void setMinTimeBetweenJwksRequests(int minTimeBetweenJwksRequests) {
+            delegate.setMinTimeBetweenJwksRequests(minTimeBetweenJwksRequests);
+        }
+
+        @Override
+        public int getMinTimeBetweenJwksRequests() {
+            return delegate.getMinTimeBetweenJwksRequests();
+        }
     }
 
     protected KeycloakUriBuilder getBaseBuilder(HttpFacade facade, String base) {
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/KeycloakAdapterPolicyEnforcer.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/KeycloakAdapterPolicyEnforcer.java
index f1be944..1c900b8 100644
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/KeycloakAdapterPolicyEnforcer.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/KeycloakAdapterPolicyEnforcer.java
@@ -21,6 +21,7 @@ import org.jboss.logging.Logger;
 import org.keycloak.RSATokenVerifier;
 import org.keycloak.adapters.KeycloakDeployment;
 import org.keycloak.adapters.OIDCHttpFacade;
+import org.keycloak.adapters.rotation.AdapterRSATokenVerifier;
 import org.keycloak.adapters.spi.HttpFacade;
 import org.keycloak.authorization.client.AuthorizationDeniedException;
 import org.keycloak.authorization.client.AuthzClient;
@@ -120,7 +121,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
                 AuthorizationResponse authzResponse = authzClient.authorization(accessToken).authorize(authzRequest);
 
                 if (authzResponse != null) {
-                    return RSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment.getRealmKey(), deployment.getRealmInfoUrl());
+                    return AdapterRSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment);
                 }
 
                 return null;
@@ -130,7 +131,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
 
                 if (token.getAuthorization() == null) {
                     EntitlementResponse authzResponse = authzClient.entitlement(accessToken).getAll(authzClient.getConfiguration().getClientId());
-                    return RSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment.getRealmKey(), deployment.getRealmInfoUrl());
+                    return AdapterRSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment);
                 } else {
                     EntitlementRequest request = new EntitlementRequest();
                     PermissionRequest permissionRequest = new PermissionRequest();
@@ -139,7 +140,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
                     permissionRequest.setScopes(new HashSet<>(pathConfig.getScopes()));
                     request.addPermission(permissionRequest);
                     EntitlementResponse authzResponse = authzClient.entitlement(accessToken).get(authzClient.getConfiguration().getClientId(), request);
-                    return RSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment.getRealmKey(), deployment.getRealmInfoUrl());
+                    return AdapterRSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment);
                 }
             }
         } catch (AuthorizationDeniedException e) {
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
index 9af6214..70b90b1 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
@@ -19,6 +19,7 @@ package org.keycloak.adapters;
 
 import org.jboss.logging.Logger;
 import org.keycloak.RSATokenVerifier;
+import org.keycloak.adapters.rotation.AdapterRSATokenVerifier;
 import org.keycloak.adapters.spi.AuthChallenge;
 import org.keycloak.adapters.spi.AuthOutcome;
 import org.keycloak.adapters.spi.HttpFacade;
@@ -84,7 +85,7 @@ public class BearerTokenRequestAuthenticator {
     
     protected AuthOutcome authenticateToken(HttpFacade exchange, String tokenString) {
         try {
-            token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
+            token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
         } catch (VerificationException e) {
             log.error("Failed to verify token", e);
             challenge = challengeResponse(exchange, OIDCAuthenticationError.Reason.INVALID_TOKEN, "invalid_token", e.getMessage());
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java
index 7f66dbf..2093645 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import org.jboss.logging.Logger;
 import org.keycloak.KeycloakPrincipal;
 import org.keycloak.RSATokenVerifier;
+import org.keycloak.adapters.rotation.AdapterRSATokenVerifier;
 import org.keycloak.adapters.spi.HttpFacade;
 import org.keycloak.common.VerificationException;
 import org.keycloak.constants.AdapterConstants;
@@ -73,7 +74,7 @@ public class CookieTokenStore {
 
         try {
             // Skip check if token is active now. It's supposed to be done later by the caller
-            AccessToken accessToken = RSATokenVerifier.verifyToken(accessTokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl(), false, true);
+            AccessToken accessToken = AdapterRSATokenVerifier.verifyToken(accessTokenString, deployment, false, true);
             IDToken idToken;
             if (idTokenString != null && idTokenString.length() > 0) {
                 try {
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/HttpAdapterUtils.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/HttpAdapterUtils.java
new file mode 100644
index 0000000..e01f7dc
--- /dev/null
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/HttpAdapterUtils.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.keycloak.util.JsonSerialization;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class HttpAdapterUtils {
+
+
+    public static <T> T sendJsonHttpRequest(KeycloakDeployment deployment, HttpRequestBase httpRequest, Class<T> clazz) throws HttpClientAdapterException {
+        try {
+            HttpResponse response = deployment.getClient().execute(httpRequest);
+            int status = response.getStatusLine().getStatusCode();
+            if (status != 200) {
+                close(response);
+                throw new HttpClientAdapterException("Unexpected status = " + status);
+            }
+            HttpEntity entity = response.getEntity();
+            if (entity == null) {
+                throw new HttpClientAdapterException("There was no entity.");
+            }
+            InputStream is = entity.getContent();
+            try {
+                ByteArrayOutputStream os = new ByteArrayOutputStream();
+                int c;
+                while ((c = is.read()) != -1) {
+                    os.write(c);
+                }
+                byte[] bytes = os.toByteArray();
+                String json = new String(bytes);
+                return JsonSerialization.readValue(json, clazz);
+            } finally {
+                try {
+                    is.close();
+                } catch (IOException ignored) {
+
+                }
+            }
+        } catch (IOException e) {
+            throw new HttpClientAdapterException("IO error", e);
+        }
+    }
+
+
+    private static void close(HttpResponse response) {
+        if (response.getEntity() != null) {
+            try {
+                response.getEntity().getContent().close();
+            } catch (IOException e) {
+
+            }
+        }
+    }
+}
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/HttpClientAdapterException.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/HttpClientAdapterException.java
new file mode 100644
index 0000000..7d303e2
--- /dev/null
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/HttpClientAdapterException.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class HttpClientAdapterException extends Exception {
+
+    public HttpClientAdapterException(String message) {
+        super(message);
+    }
+
+    public HttpClientAdapterException(String message, Throwable t) {
+        super(message, t);
+    }
+}
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/jaas/AbstractKeycloakLoginModule.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/jaas/AbstractKeycloakLoginModule.java
index 51be551..75086e7 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/jaas/AbstractKeycloakLoginModule.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/jaas/AbstractKeycloakLoginModule.java
@@ -43,6 +43,7 @@ import org.keycloak.adapters.AdapterUtils;
 import org.keycloak.adapters.KeycloakDeployment;
 import org.keycloak.adapters.KeycloakDeploymentBuilder;
 import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.rotation.AdapterRSATokenVerifier;
 import org.keycloak.common.VerificationException;
 import org.keycloak.common.util.FindFile;
 import org.keycloak.representations.AccessToken;
@@ -88,9 +89,6 @@ public abstract class AbstractKeycloakLoginModule implements LoginModule {
         try {
             InputStream is = FindFile.findFile(keycloakConfigFile);
             KeycloakDeployment kd = KeycloakDeploymentBuilder.build(is);
-            if (kd.getRealmKey() == null) {
-                new AdapterDeploymentContext().resolveRealmKey(kd);
-            }
             return kd;
         } catch (RuntimeException e) {
             getLogger().debug("Unable to find or parse file " + keycloakConfigFile + " due to " + e.getMessage(), e);
@@ -190,7 +188,7 @@ public abstract class AbstractKeycloakLoginModule implements LoginModule {
 
 
     protected Auth bearerAuth(String tokenString) throws VerificationException {
-        AccessToken token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
+        AccessToken token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
 
         boolean verifyCaller;
         if (deployment.isUseResourceRoleMappings()) {
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
index 901b3ea..30c40c3 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
@@ -21,6 +21,7 @@ import org.apache.http.client.HttpClient;
 import org.jboss.logging.Logger;
 import org.keycloak.adapters.authentication.ClientCredentialsProvider;
 import org.keycloak.adapters.authorization.PolicyEnforcer;
+import org.keycloak.adapters.rotation.PublicKeyLocator;
 import org.keycloak.constants.ServiceUrlConstants;
 import org.keycloak.common.enums.RelativeUrlsUsed;
 import org.keycloak.common.enums.SslRequired;
@@ -29,7 +30,6 @@ import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.common.util.KeycloakUriBuilder;
 
 import java.net.URI;
-import java.security.PublicKey;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -43,7 +43,7 @@ public class KeycloakDeployment {
 
     protected RelativeUrlsUsed relativeUrls;
     protected String realm;
-    protected volatile PublicKey realmKey;
+    protected PublicKeyLocator publicKeyLocator;
     protected String authServerBaseUrl;
     protected String realmInfoUrl;
     protected KeycloakUriBuilder authUrl;
@@ -52,6 +52,7 @@ public class KeycloakDeployment {
     protected String accountUrl;
     protected String registerNodeUrl;
     protected String unregisterNodeUrl;
+    protected String jwksUrl;
     protected String principalAttribute = "sub";
 
     protected String resourceName;
@@ -79,13 +80,14 @@ public class KeycloakDeployment {
 
     protected volatile int notBefore;
     protected int tokenMinimumTimeToLive;
+    protected int minTimeBetweenJwksRequests;
     private PolicyEnforcer policyEnforcer;
 
     public KeycloakDeployment() {
     }
 
     public boolean isConfigured() {
-        return getRealm() != null && getRealmKey() != null && (isBearerOnly() || getAuthServerBaseUrl() != null);
+        return getRealm() != null && getPublicKeyLocator() != null && (isBearerOnly() || getAuthServerBaseUrl() != null);
     }
 
     public String getResourceName() {
@@ -100,12 +102,12 @@ public class KeycloakDeployment {
         this.realm = realm;
     }
 
-    public PublicKey getRealmKey() {
-        return realmKey;
+    public PublicKeyLocator getPublicKeyLocator() {
+        return publicKeyLocator;
     }
 
-    public void setRealmKey(PublicKey realmKey) {
-        this.realmKey = realmKey;
+    public void setPublicKeyLocator(PublicKeyLocator publicKeyLocator) {
+        this.publicKeyLocator = publicKeyLocator;
     }
 
     public String getAuthServerBaseUrl() {
@@ -147,6 +149,7 @@ public class KeycloakDeployment {
         accountUrl = authUrlBuilder.clone().path(ServiceUrlConstants.ACCOUNT_SERVICE_PATH).build(getRealm()).toString();
         registerNodeUrl = authUrlBuilder.clone().path(ServiceUrlConstants.CLIENTS_MANAGEMENT_REGISTER_NODE_PATH).build(getRealm()).toString();
         unregisterNodeUrl = authUrlBuilder.clone().path(ServiceUrlConstants.CLIENTS_MANAGEMENT_UNREGISTER_NODE_PATH).build(getRealm()).toString();
+        jwksUrl = authUrlBuilder.clone().path(ServiceUrlConstants.JWKS_URL).build(getRealm()).toString();
     }
 
     public RelativeUrlsUsed getRelativeUrls() {
@@ -181,6 +184,10 @@ public class KeycloakDeployment {
         return unregisterNodeUrl;
     }
 
+    public String getJwksUrl() {
+        return jwksUrl;
+    }
+
     public void setResourceName(String resourceName) {
         this.resourceName = resourceName;
     }
@@ -369,6 +376,14 @@ public class KeycloakDeployment {
         this.tokenMinimumTimeToLive = tokenMinimumTimeToLive;
     }
 
+    public int getMinTimeBetweenJwksRequests() {
+        return minTimeBetweenJwksRequests;
+    }
+
+    public void setMinTimeBetweenJwksRequests(int minTimeBetweenJwksRequests) {
+        this.minTimeBetweenJwksRequests = minTimeBetweenJwksRequests;
+    }
+
     public void setPolicyEnforcer(PolicyEnforcer policyEnforcer) {
         this.policyEnforcer = policyEnforcer;
     }
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
index 5d54df9..04e16f8 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
@@ -22,6 +22,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import org.jboss.logging.Logger;
 import org.keycloak.adapters.authentication.ClientCredentialsProviderUtils;
 import org.keycloak.adapters.authorization.PolicyEnforcer;
+import org.keycloak.adapters.rotation.HardcodedPublicKeyLocator;
+import org.keycloak.adapters.rotation.JWKPublicKeyLocator;
 import org.keycloak.common.enums.SslRequired;
 import org.keycloak.common.util.PemUtils;
 import org.keycloak.enums.TokenStore;
@@ -59,11 +61,16 @@ public class KeycloakDeploymentBuilder {
             PublicKey realmKey;
             try {
                 realmKey = PemUtils.decodePublicKey(realmKeyPem);
+                HardcodedPublicKeyLocator pkLocator = new HardcodedPublicKeyLocator(realmKey);
+                deployment.setPublicKeyLocator(pkLocator);
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
-            deployment.setRealmKey(realmKey);
+        } else {
+            JWKPublicKeyLocator pkLocator = new JWKPublicKeyLocator();
+            deployment.setPublicKeyLocator(pkLocator);
         }
+
         if (adapterConfig.getSslRequired() != null) {
             deployment.setSslRequired(SslRequired.valueOf(adapterConfig.getSslRequired().toUpperCase()));
         } else {
@@ -97,6 +104,7 @@ public class KeycloakDeploymentBuilder {
         deployment.setRegisterNodeAtStartup(adapterConfig.isRegisterNodeAtStartup());
         deployment.setRegisterNodePeriod(adapterConfig.getRegisterNodePeriod());
         deployment.setTokenMinimumTimeToLive(adapterConfig.getTokenMinimumTimeToLive());
+        deployment.setMinTimeBetweenJwksRequests(adapterConfig.getMinTimeBetweenJwksRequests());
 
         if (realmKeyPem == null && adapterConfig.isBearerOnly() && adapterConfig.getAuthServerUrl() == null) {
             throw new IllegalArgumentException("For bearer auth, you must set the realm-public-key or auth-server-url");
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 73aa0f5..02637c0 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
@@ -20,6 +20,7 @@ package org.keycloak.adapters;
 import org.jboss.logging.Logger;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.RSATokenVerifier;
+import org.keycloak.adapters.rotation.AdapterRSATokenVerifier;
 import org.keycloak.adapters.spi.AdapterSessionStore;
 import org.keycloak.adapters.spi.AuthChallenge;
 import org.keycloak.adapters.spi.AuthOutcome;
@@ -342,7 +343,7 @@ public class OAuthRequestAuthenticator {
         refreshToken = tokenResponse.getRefreshToken();
         idTokenString = tokenResponse.getIdToken();
         try {
-            token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
+            token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
             if (idTokenString != null) {
                 try {
                     JWSInput input = new JWSInput(idTokenString);
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java
index 1a8c735..5a1df8c 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java
@@ -17,7 +17,10 @@
 
 package org.keycloak.adapters;
 
+import java.security.PublicKey;
+
 import org.jboss.logging.Logger;
+import org.keycloak.adapters.rotation.AdapterRSATokenVerifier;
 import org.keycloak.adapters.spi.HttpFacade;
 import org.keycloak.adapters.spi.UserSessionManagement;
 import org.keycloak.jose.jws.JWSInputException;
@@ -198,7 +201,8 @@ public class PreAuthActionsHandler {
 
         try {
             JWSInput input = new JWSInput(token);
-            if (RSAProvider.verify(input, deployment.getRealmKey())) {
+            PublicKey publicKey = AdapterRSATokenVerifier.getPublicKey(input, deployment);
+            if (RSAProvider.verify(input, publicKey)) {
                 return input;
             }
         } catch (JWSInputException ignore) {
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java
index 7cfc7a6..75f0cb8 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java
@@ -21,6 +21,7 @@ import org.jboss.logging.Logger;
 import org.keycloak.AuthorizationContext;
 import org.keycloak.KeycloakSecurityContext;
 import org.keycloak.RSATokenVerifier;
+import org.keycloak.adapters.rotation.AdapterRSATokenVerifier;
 import org.keycloak.common.VerificationException;
 import org.keycloak.common.util.Time;
 import org.keycloak.representations.AccessToken;
@@ -130,7 +131,7 @@ public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext 
         String tokenString = response.getToken();
         AccessToken token = null;
         try {
-            token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
+            token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
             log.debug("Token Verification succeeded!");
         } catch (VerificationException e) {
             log.error("failed verification of token");
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/AdapterRSATokenVerifier.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/AdapterRSATokenVerifier.java
new file mode 100644
index 0000000..c69ee38
--- /dev/null
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/AdapterRSATokenVerifier.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.rotation;
+
+import java.security.PublicKey;
+
+import org.jboss.logging.Logger;
+import org.keycloak.RSATokenVerifier;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.common.VerificationException;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.representations.AccessToken;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class AdapterRSATokenVerifier {
+
+    private static final Logger log = Logger.getLogger(AdapterRSATokenVerifier.class);
+
+    public static AccessToken verifyToken(String tokenString, KeycloakDeployment deployment) throws VerificationException {
+        return verifyToken(tokenString, deployment, true, true);
+    }
+
+
+    public static PublicKey getPublicKey(JWSInput input, KeycloakDeployment deployment) throws VerificationException {
+        PublicKeyLocator pkLocator = deployment.getPublicKeyLocator();
+
+        PublicKey publicKey = pkLocator.getPublicKey(input, deployment);
+        if (publicKey == null) {
+            log.errorf("Didn't find publicKey for kid: %s", input.getHeader().getKeyId());
+            throw new VerificationException("Didn't find publicKey for specified kid");
+        }
+
+        return publicKey;
+    }
+
+    public static AccessToken verifyToken(String tokenString, KeycloakDeployment deployment, boolean checkActive, boolean checkTokenType) throws VerificationException {
+        JWSInput input;
+        try {
+            input = new JWSInput(tokenString);
+        } catch (Exception e) {
+            throw new VerificationException("Couldn't parse token", e);
+        }
+
+        PublicKey publicKey = getPublicKey(input, deployment);
+        return RSATokenVerifier.verifyToken(input, publicKey, deployment.getRealmInfoUrl(), checkActive, checkTokenType);
+    }
+}
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/HardcodedPublicKeyLocator.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/HardcodedPublicKeyLocator.java
new file mode 100644
index 0000000..40fb71a
--- /dev/null
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/HardcodedPublicKeyLocator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.rotation;
+
+import java.security.PublicKey;
+
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.jose.jws.JWSInput;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class HardcodedPublicKeyLocator implements PublicKeyLocator {
+
+    private PublicKey publicKey;
+
+    public HardcodedPublicKeyLocator(PublicKey publicKey) {
+        this.publicKey = publicKey;
+    }
+
+    @Override
+    public PublicKey getPublicKey(JWSInput input, KeycloakDeployment deployment) {
+        return publicKey;
+    }
+}
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/JWKPublicKeyLocator.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/JWKPublicKeyLocator.java
new file mode 100644
index 0000000..5003923
--- /dev/null
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/JWKPublicKeyLocator.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.rotation;
+
+import java.security.PublicKey;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.http.client.methods.HttpGet;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.HttpAdapterUtils;
+import org.keycloak.adapters.HttpClientAdapterException;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.common.util.Time;
+import org.keycloak.jose.jwk.JSONWebKeySet;
+import org.keycloak.jose.jwk.JWK;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.util.JWKSUtils;
+
+/**
+ * When needed, publicKeys are downloaded by sending request to realm's jwks_url
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class JWKPublicKeyLocator implements PublicKeyLocator {
+
+    private static final Logger log = Logger.getLogger(JWKPublicKeyLocator.class);
+
+    private Map<String, PublicKey> currentKeys = new ConcurrentHashMap<>();
+
+    private volatile int lastRequestTime = 0;
+
+    @Override
+    public PublicKey getPublicKey(JWSInput input, KeycloakDeployment deployment) {
+        String kid = input.getHeader().getKeyId();
+        return getPublicKey(kid, deployment);
+    }
+
+
+    private PublicKey getPublicKey(String kid, KeycloakDeployment deployment) {
+        int minTimeBetweenRequests = deployment.getMinTimeBetweenJwksRequests();
+
+        // Check if key is in cache.
+        PublicKey publicKey = currentKeys.get(kid);
+        if (publicKey != null) {
+            return publicKey;
+        }
+
+        int currentTime = Time.currentTime();
+
+        // Check if we are allowed to send request
+        if (currentTime > lastRequestTime + minTimeBetweenRequests) {
+            synchronized (this) {
+                currentTime = Time.currentTime();
+                if (currentTime > lastRequestTime + minTimeBetweenRequests) {
+                    sendRequest(deployment);
+                    lastRequestTime = currentTime;
+                } else {
+                    // TODO: debug
+                    log.infof("Won't send request to realm jwks url. Last request time was %d", lastRequestTime);
+                }
+            }
+        }
+
+        return currentKeys.get(kid);
+
+    }
+
+
+    private void sendRequest(KeycloakDeployment deployment) {
+        // Send the request
+        // TODO: trace or remove?
+        log.infof("Going to send request to retrieve new set of realm public keys for client %s", deployment.getResourceName());
+
+        HttpGet getMethod = new HttpGet(deployment.getJwksUrl());
+        try {
+            JSONWebKeySet jwks = HttpAdapterUtils.sendJsonHttpRequest(deployment, getMethod, JSONWebKeySet.class);
+
+            Map<String, PublicKey> publicKeys = JWKSUtils.getKeysForUse(jwks, JWK.Use.SIG);
+
+            // TODO: Debug with condition
+            log.infof("Realm public keys successfully retrieved for client %s. New kids: %s", deployment.getResourceName(), publicKeys.keySet().toString());
+
+            // Update current keys
+            currentKeys.clear();
+            currentKeys.putAll(publicKeys);
+
+        } catch (HttpClientAdapterException e) {
+            log.error("Error when sending request to retrieve realm keys", e);
+        }
+    }
+}
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/PublicKeyLocator.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/PublicKeyLocator.java
new file mode 100644
index 0000000..bda80dc
--- /dev/null
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/PublicKeyLocator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.rotation;
+
+import java.security.PublicKey;
+
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.jose.jws.JWSInput;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface PublicKeyLocator {
+
+    /**
+     * @param input
+     * @param deployment
+     * @return publicKey, which should be used for verify signature on given "input"
+     */
+    PublicKey getPublicKey(JWSInput input, KeycloakDeployment deployment);
+
+}
diff --git a/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java b/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java
index 4be5110..d1ce748 100644
--- a/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java
+++ b/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java
@@ -21,6 +21,8 @@ import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
 import org.junit.Test;
 import org.keycloak.adapters.authentication.ClientIdAndSecretCredentialsProvider;
 import org.keycloak.adapters.authentication.JWTClientCredentialsProvider;
+import org.keycloak.adapters.rotation.HardcodedPublicKeyLocator;
+import org.keycloak.adapters.rotation.JWKPublicKeyLocator;
 import org.keycloak.common.enums.RelativeUrlsUsed;
 import org.keycloak.common.enums.SslRequired;
 import org.keycloak.enums.TokenStore;
@@ -39,7 +41,11 @@ public class KeycloakDeploymentBuilderTest {
         KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(getClass().getResourceAsStream("/keycloak.json"));
         assertEquals("demo", deployment.getRealm());
         assertEquals("customer-portal", deployment.getResourceName());
-        assertEquals(PemUtils.decodePublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"), deployment.getRealmKey());
+
+        assertTrue(deployment.getPublicKeyLocator() instanceof HardcodedPublicKeyLocator);
+        assertEquals(PemUtils.decodePublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"),
+                deployment.getPublicKeyLocator().getPublicKey(null, deployment));
+
         assertEquals("https://localhost:8443/auth/realms/demo/protocol/openid-connect/auth", deployment.getAuthUrl().build().toString());
         assertEquals(SslRequired.EXTERNAL, deployment.getSslRequired());
         assertTrue(deployment.isUseResourceRoleMappings());
@@ -62,12 +68,16 @@ public class KeycloakDeploymentBuilderTest {
         assertEquals(TokenStore.COOKIE, deployment.getTokenStore());
         assertEquals("email", deployment.getPrincipalAttribute());
         assertEquals(10, deployment.getTokenMinimumTimeToLive());
+        assertEquals(20, deployment.getMinTimeBetweenJwksRequests());
     }
 
     @Test
     public void loadNoClientCredentials() throws Exception {
         KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(getClass().getResourceAsStream("/keycloak-no-credentials.json"));
         assertEquals(ClientIdAndSecretCredentialsProvider.PROVIDER_ID, deployment.getClientAuthenticator().getId());
+
+        assertTrue(deployment.getPublicKeyLocator() instanceof JWKPublicKeyLocator);
+        assertEquals(10, deployment.getMinTimeBetweenJwksRequests());
     }
 
     @Test
diff --git a/adapters/oidc/adapter-core/src/test/resources/keycloak.json b/adapters/oidc/adapter-core/src/test/resources/keycloak.json
index 7bf269f..a8afd22 100644
--- a/adapters/oidc/adapter-core/src/test/resources/keycloak.json
+++ b/adapters/oidc/adapter-core/src/test/resources/keycloak.json
@@ -29,5 +29,6 @@
     "register-node-period": 1000,
     "token-store": "cookie",
     "principal-attribute": "email",
-    "token-minimum-time-to-live": 10
+    "token-minimum-time-to-live": 10,
+    "min-time-between-jwks-requests": 20
 }
\ No newline at end of file
diff --git a/adapters/oidc/adapter-core/src/test/resources/keycloak-no-credentials.json b/adapters/oidc/adapter-core/src/test/resources/keycloak-no-credentials.json
index 5f223ac..a3c4026 100644
--- a/adapters/oidc/adapter-core/src/test/resources/keycloak-no-credentials.json
+++ b/adapters/oidc/adapter-core/src/test/resources/keycloak-no-credentials.json
@@ -1,7 +1,6 @@
 {
     "realm": "demo",
     "resource": "customer-portal",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
     "auth-server-url": "https://localhost:8443/auth",
     "public-client": true,
     "expose-token": true
diff --git a/adapters/oidc/installed/src/main/java/org/keycloak/adapters/installed/KeycloakInstalled.java b/adapters/oidc/installed/src/main/java/org/keycloak/adapters/installed/KeycloakInstalled.java
index fc0e47f..c52a44a 100644
--- a/adapters/oidc/installed/src/main/java/org/keycloak/adapters/installed/KeycloakInstalled.java
+++ b/adapters/oidc/installed/src/main/java/org/keycloak/adapters/installed/KeycloakInstalled.java
@@ -20,6 +20,7 @@ package org.keycloak.adapters.installed;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.OAuthErrorException;
 import org.keycloak.RSATokenVerifier;
+import org.keycloak.adapters.rotation.AdapterRSATokenVerifier;
 import org.keycloak.common.VerificationException;
 import org.keycloak.adapters.KeycloakDeployment;
 import org.keycloak.adapters.KeycloakDeploymentBuilder;
@@ -213,7 +214,7 @@ public class KeycloakInstalled {
         refreshToken = tokenResponse.getRefreshToken();
         idTokenString = tokenResponse.getIdToken();
 
-        token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
+        token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
         if (idTokenString != null) {
             try {
                 JWSInput input = new JWSInput(idTokenString);
diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js
index 44a7e75..2d8f421 100755
--- a/adapters/oidc/js/src/main/resources/keycloak.js
+++ b/adapters/oidc/js/src/main/resources/keycloak.js
@@ -155,7 +155,6 @@
                 } else if (initOptions) {
                     if (initOptions.token || initOptions.refreshToken) {
                         setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken);
-                        kc.timeSkew = initOptions.timeSkew || 0;
 
                         if (loginIframe.enable) {
                             setupCheckLoginIframe().success(function() {
@@ -166,6 +165,8 @@
                                     kc.onAuthError && kc.onAuthError();
                                     if (initOptions.onLoad) {
                                         onLoad();
+                                    } else {
+                                        initPromise.setError();
                                     }
                                 });
                             });
@@ -177,6 +178,8 @@
                                 kc.onAuthError && kc.onAuthError();
                                 if (initOptions.onLoad) {
                                     onLoad();
+                                } else {
+                                    initPromise.setError();
                                 }
                             });
                         }
@@ -359,11 +362,10 @@
                 throw 'Not authenticated';
             }
 
-            var expiresIn = kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew;
+            var expiresIn = kc.tokenParsed['exp'] - Math.ceil(new Date().getTime() / 1000) + kc.timeSkew;
             if (minValidity) {
                 expiresIn -= minValidity;
             }
-
             return expiresIn < 0;
         }
 
@@ -378,7 +380,20 @@
             minValidity = minValidity || 5;
 
             var exec = function() {
-                if (minValidity >= 0 && !kc.isTokenExpired(minValidity)) {
+                var refreshToken = false;
+                if (kc.timeSkew == -1) {
+                    console.info('Skew ' + kc.timeSkew);
+                    refreshToken = true;
+                    console.info('[KEYCLOAK] Refreshing token: time skew not set');
+                } else if (minValidity == -1) {
+                    refreshToken = true;
+                    console.info('[KEYCLOAK] Refreshing token: forced refresh');
+                } else if (kc.isTokenExpired(minValidity)) {
+                    refreshToken = true;
+                    console.info('[KEYCLOAK] Refreshing token: token expired');
+                }
+
+                if (!refreshToken) {
                     promise.setSuccess(false);
                 } else {
                     var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken;
@@ -403,18 +418,21 @@
                         req.onreadystatechange = function () {
                             if (req.readyState == 4) {
                                 if (req.status == 200) {
+                                    console.info('[KEYCLOAK] Token refreshed');
+
                                     timeLocal = (timeLocal + new Date().getTime()) / 2;
 
                                     var tokenResponse = JSON.parse(req.responseText);
-                                    kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
 
-                                    setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token']);
+                                    setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], timeLocal);
 
                                     kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();
                                     for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
                                         p.setSuccess(true);
                                     }
                                 } else {
+                                    console.warn('[KEYCLOAK] Failed to refresh token');
+
                                     kc.onAuthRefreshError && kc.onAuthRefreshError();
                                     for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
                                         p.setError(true);
@@ -525,18 +543,16 @@
             function authSuccess(accessToken, refreshToken, idToken, fulfillPromise) {
                 timeLocal = (timeLocal + new Date().getTime()) / 2;
 
-                setToken(accessToken, refreshToken, idToken);
+                setToken(accessToken, refreshToken, idToken, timeLocal);
 
                 if ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) ||
                     (kc.refreshTokenParsed && kc.refreshTokenParsed.nonce != oauth.storedNonce) ||
                     (kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce)) {
 
-                    console.log('invalid nonce!');
+                    console.info('[KEYCLOAK] Invalid nonce, clearing token');
                     kc.clearToken();
                     promise && promise.setError();
                 } else {
-                    kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
-
                     if (fulfillPromise) {
                         kc.onAuthSuccess && kc.onAuthSuccess();
                         promise && promise.setSuccess();
@@ -609,7 +625,7 @@
             return promise.promise;
         }
 
-        function setToken(token, refreshToken, idToken) {
+        function setToken(token, refreshToken, idToken, timeLocal) {
             if (kc.tokenTimeoutHandle) {
                 clearTimeout(kc.tokenTimeoutHandle);
                 kc.tokenTimeoutHandle = null;
@@ -628,12 +644,23 @@
                 kc.realmAccess = kc.tokenParsed.realm_access;
                 kc.resourceAccess = kc.tokenParsed.resource_access;
 
+                if (timeLocal) {
+                    kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
+                    console.info('[KEYCLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds');
+                } else {
+                    kc.timeSkew = -1;
+                }
+
                 if (kc.onTokenExpired) {
-                    var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000;
-                    if (expiresIn <= 0) {
+                    if (kc.timeSkew == -1) {
                         kc.onTokenExpired();
                     } else {
-                        kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
+                        var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000;
+                        if (expiresIn <= 0) {
+                            kc.onTokenExpired();
+                        } else {
+                            kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
+                        }
                     }
                 }
 
diff --git a/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/management/HttpSessionManager.java b/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/management/HttpSessionManager.java
index 7472d79..cb8a764 100644
--- a/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/management/HttpSessionManager.java
+++ b/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/management/HttpSessionManager.java
@@ -69,6 +69,5 @@ public class HttpSessionManager implements HttpSessionListener, UserSessionManag
                 session.invalidate();
             }
         }
-        sessions.clear();
     }
 }
diff --git a/common/src/main/java/org/keycloak/common/Profile.java b/common/src/main/java/org/keycloak/common/Profile.java
new file mode 100755
index 0000000..ac16874
--- /dev/null
+++ b/common/src/main/java/org/keycloak/common/Profile.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.common;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class Profile {
+
+    private enum ProfileValue {
+        PRODUCT, PREVIEW, COMMUNITY
+    }
+
+    private static ProfileValue value = load();
+
+    static ProfileValue load() {
+        String profile = null;
+        try {
+            profile = System.getProperty("keycloak.profile");
+            if (profile == null) {
+                String jbossServerConfigDir = System.getProperty("jboss.server.config.dir");
+                if (jbossServerConfigDir != null) {
+                    File file = new File(jbossServerConfigDir, "profile.properties");
+                    if (file.isFile()) {
+                        Properties props = new Properties();
+                        props.load(new FileInputStream(file));
+                        profile = props.getProperty("profile");
+                    }
+                }
+            }
+        } catch (Exception e) {
+        }
+
+        if (profile == null) {
+            return ProfileValue.valueOf(Version.DEFAULT_PROFILE.toUpperCase());
+        } else {
+            return ProfileValue.valueOf(profile.toUpperCase());
+        }
+    }
+
+    public static String getName() {
+        return value.name().toLowerCase();
+    }
+
+    public static boolean isPreviewEnabled() {
+        return value.ordinal() >= ProfileValue.PREVIEW.ordinal();
+    }
+
+}
diff --git a/common/src/main/java/org/keycloak/common/Version.java b/common/src/main/java/org/keycloak/common/Version.java
index 42ba52a..862ccd2 100755
--- a/common/src/main/java/org/keycloak/common/Version.java
+++ b/common/src/main/java/org/keycloak/common/Version.java
@@ -32,6 +32,7 @@ public class Version {
     public static String VERSION;
     public static String RESOURCES_VERSION;
     public static String BUILD_TIME;
+    public static String DEFAULT_PROFILE;
 
     static {
         Properties props = new Properties();
@@ -40,6 +41,7 @@ public class Version {
             props.load(is);
             Version.NAME = props.getProperty("name");
             Version.NAME_HTML = props.getProperty("name-html");
+            Version.DEFAULT_PROFILE = props.getProperty("default-profile");
             Version.VERSION = props.getProperty("version");
             Version.BUILD_TIME = props.getProperty("build-time");
             Version.RESOURCES_VERSION = Version.VERSION.toLowerCase();
diff --git a/common/src/main/resources/keycloak-version.properties b/common/src/main/resources/keycloak-version.properties
index 643b6de..f66e436 100755
--- a/common/src/main/resources/keycloak-version.properties
+++ b/common/src/main/resources/keycloak-version.properties
@@ -18,4 +18,5 @@
 name=${product.name}
 name-html=${product.name-html}
 version=${product.version}
-build-time=${product.build-time}
\ No newline at end of file
+build-time=${product.build-time}
+default-profile=${product.default-profile}
\ No newline at end of file
diff --git a/core/src/main/java/org/keycloak/constants/ServiceUrlConstants.java b/core/src/main/java/org/keycloak/constants/ServiceUrlConstants.java
index a21f262..36b4f1d 100755
--- a/core/src/main/java/org/keycloak/constants/ServiceUrlConstants.java
+++ b/core/src/main/java/org/keycloak/constants/ServiceUrlConstants.java
@@ -30,5 +30,6 @@ public interface ServiceUrlConstants {
     public static final String REALM_INFO_PATH = "/realms/{realm-name}";
     public static final String CLIENTS_MANAGEMENT_REGISTER_NODE_PATH = "/realms/{realm-name}/clients-managements/register-node";
     public static final String CLIENTS_MANAGEMENT_UNREGISTER_NODE_PATH = "/realms/{realm-name}/clients-managements/unregister-node";
+    public static final String JWKS_URL = "/realms/{realm-name}/protocol/openid-connect/certs";
 
 }
diff --git a/core/src/main/java/org/keycloak/jose/jwk/JWKParser.java b/core/src/main/java/org/keycloak/jose/jwk/JWKParser.java
index 7a31f72..a20d253 100755
--- a/core/src/main/java/org/keycloak/jose/jwk/JWKParser.java
+++ b/core/src/main/java/org/keycloak/jose/jwk/JWKParser.java
@@ -21,7 +21,6 @@ import com.fasterxml.jackson.core.type.TypeReference;
 import org.keycloak.common.util.Base64Url;
 import org.keycloak.util.JsonSerialization;
 
-import java.io.InputStream;
 import java.math.BigInteger;
 import java.security.KeyFactory;
 import java.security.PublicKey;
@@ -66,8 +65,8 @@ public class JWKParser {
     }
 
     public PublicKey toPublicKey() {
-        String algorithm = jwk.getKeyType();
-        if (isAlgorithmSupported(algorithm)) {
+        String keyType = jwk.getKeyType();
+        if (isKeyTypeSupported(keyType)) {
             BigInteger modulus = new BigInteger(1, Base64Url.decode(jwk.getOtherClaims().get(RSAPublicJWK.MODULUS).toString()));
             BigInteger publicExponent = new BigInteger(1, Base64Url.decode(jwk.getOtherClaims().get(RSAPublicJWK.PUBLIC_EXPONENT).toString()));
 
@@ -77,12 +76,12 @@ public class JWKParser {
                 throw new RuntimeException(e);
             }
         } else {
-            throw new RuntimeException("Unsupported algorithm " + algorithm);
+            throw new RuntimeException("Unsupported keyType " + keyType);
         }
     }
 
-    public boolean isAlgorithmSupported(String algorithm) {
-        return RSAPublicJWK.RSA.equals(algorithm);
+    public boolean isKeyTypeSupported(String keyType) {
+        return RSAPublicJWK.RSA.equals(keyType);
     }
 
 }
diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
index 91fb5f0..c4818b4 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
@@ -36,7 +36,7 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
         "client-keystore", "client-keystore-password", "client-key-password",
         "always-refresh-token",
         "register-node-at-startup", "register-node-period", "token-store", "principal-attribute",
-        "proxy-url", "turn-off-change-session-id-on-login", "token-minimum-time-to-live",
+        "proxy-url", "turn-off-change-session-id-on-login", "token-minimum-time-to-live", "min-time-between-jwks-requests",
         "policy-enforcer"
 })
 public class AdapterConfig extends BaseAdapterConfig {
@@ -71,6 +71,8 @@ public class AdapterConfig extends BaseAdapterConfig {
     protected Boolean turnOffChangeSessionIdOnLogin;
     @JsonProperty("token-minimum-time-to-live")
     protected int tokenMinimumTimeToLive = 0;
+    @JsonProperty("min-time-between-jwks-requests")
+    protected int minTimeBetweenJwksRequests = 10;
     @JsonProperty("policy-enforcer")
     protected PolicyEnforcerConfig policyEnforcerConfig;
 
@@ -216,4 +218,11 @@ public class AdapterConfig extends BaseAdapterConfig {
         this.tokenMinimumTimeToLive = tokenMinimumTimeToLive;
     }
 
+    public int getMinTimeBetweenJwksRequests() {
+        return minTimeBetweenJwksRequests;
+    }
+
+    public void setMinTimeBetweenJwksRequests(int minTimeBetweenJwksRequests) {
+        this.minTimeBetweenJwksRequests = minTimeBetweenJwksRequests;
+    }
 }
diff --git a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
index 524cbb3..2466f12 100755
--- a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
@@ -123,10 +123,15 @@ public class IdentityProviderRepresentation {
         this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
     }
 
+    /**
+     * @deprecated Replaced by configuration option in identity provider authenticator
+     */
+    @Deprecated
     public boolean isAuthenticateByDefault() {
         return authenticateByDefault;
     }
 
+    @Deprecated
     public void setAuthenticateByDefault(boolean authenticateByDefault) {
         this.authenticateByDefault = authenticateByDefault;
     }
diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
index 67c1678..89e0c01 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -123,6 +123,8 @@ public class RealmRepresentation {
     protected String resetCredentialsFlow;
     protected String clientAuthenticationFlow;
 
+    protected Map<String, String> attributes;
+
     protected String keycloakVersion;
 
     @Deprecated
@@ -864,4 +866,12 @@ public class RealmRepresentation {
         return identityProviders != null && !identityProviders.isEmpty();
     }
 
+    public void setAttributes(Map<String, String> attributes) {
+        this.attributes = attributes;
+    }
+
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
 }
diff --git a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
index e6e7ddd..b715bf5 100755
--- a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
@@ -123,10 +123,12 @@ public class UserRepresentation {
         this.enabled = enabled;
     }
 
+    @Deprecated
     public Boolean isTotp() {
         return totp;
     }
 
+    @Deprecated
     public void setTotp(Boolean totp) {
         this.totp = totp;
     }
diff --git a/core/src/main/java/org/keycloak/representations/info/ProfileInfoRepresentation.java b/core/src/main/java/org/keycloak/representations/info/ProfileInfoRepresentation.java
new file mode 100644
index 0000000..3c474d0
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/info/ProfileInfoRepresentation.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.representations.info;
+
+import org.keycloak.common.Profile;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ProfileInfoRepresentation {
+
+    private String name;
+    private boolean previewEnabled;
+
+    public static ProfileInfoRepresentation create() {
+        ProfileInfoRepresentation info = new ProfileInfoRepresentation();
+        info.setName(Profile.getName());
+        info.setPreviewEnabled(Profile.isPreviewEnabled());
+        return info;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isPreviewEnabled() {
+        return previewEnabled;
+    }
+
+    public void setPreviewEnabled(boolean previewEnabled) {
+        this.previewEnabled = previewEnabled;
+    }
+
+}
diff --git a/core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java b/core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java
index 59d400e..8c98ce3 100755
--- a/core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java
@@ -32,6 +32,7 @@ public class ServerInfoRepresentation {
 
     private SystemInfoRepresentation systemInfo;
     private MemoryInfoRepresentation memoryInfo;
+    private ProfileInfoRepresentation profileInfo;
 
     private Map<String, List<ThemeInfoRepresentation>> themes;
 
@@ -66,6 +67,14 @@ public class ServerInfoRepresentation {
         this.memoryInfo = memoryInfo;
     }
 
+    public ProfileInfoRepresentation getProfileInfo() {
+        return profileInfo;
+    }
+
+    public void setProfileInfo(ProfileInfoRepresentation profileInfo) {
+        this.profileInfo = profileInfo;
+    }
+
     public Map<String, List<ThemeInfoRepresentation>> getThemes() {
         return themes;
     }
diff --git a/core/src/main/java/org/keycloak/RSATokenVerifier.java b/core/src/main/java/org/keycloak/RSATokenVerifier.java
index 27a4301..562261d 100755
--- a/core/src/main/java/org/keycloak/RSATokenVerifier.java
+++ b/core/src/main/java/org/keycloak/RSATokenVerifier.java
@@ -38,6 +38,12 @@ public class RSATokenVerifier {
     public static AccessToken verifyToken(String tokenString, PublicKey realmKey, String realmUrl, boolean checkActive, boolean checkTokenType) throws VerificationException {
         AccessToken token = toAccessToken(tokenString, realmKey);
 
+        tokenVerifications(token, realmUrl, checkActive, checkTokenType);
+
+        return token;
+    }
+
+    private static void tokenVerifications(AccessToken token, String realmUrl, boolean checkActive, boolean checkTokenType) throws VerificationException {
         String user = token.getSubject();
         if (user == null) {
             throw new VerificationException("Token user was null.");
@@ -60,9 +66,9 @@ public class RSATokenVerifier {
             throw new VerificationException("Token is not active.");
         }
 
-        return token;
     }
 
+
     public static AccessToken toAccessToken(String tokenString, PublicKey realmKey) throws VerificationException {
         JWSInput input;
         try {
@@ -81,6 +87,23 @@ public class RSATokenVerifier {
         return token;
     }
 
+
+    public static AccessToken verifyToken(JWSInput input, PublicKey realmKey, String realmUrl, boolean checkActive, boolean checkTokenType) throws VerificationException {
+        if (!isPublicKeyValid(input, realmKey)) throw new VerificationException("Invalid token signature.");
+
+        AccessToken token;
+        try {
+            token = input.readJsonContent(AccessToken.class);
+        } catch (JWSInputException e) {
+            throw new VerificationException("Couldn't parse token signature", e);
+        }
+
+        tokenVerifications(token, realmUrl, checkActive, checkTokenType);
+
+        return token;
+    }
+
+
     private static boolean isPublicKeyValid(JWSInput input, PublicKey realmKey) throws VerificationException {
         try {
             return RSAProvider.verify(input, realmKey);
diff --git a/core/src/main/java/org/keycloak/util/JWKSUtils.java b/core/src/main/java/org/keycloak/util/JWKSUtils.java
new file mode 100644
index 0000000..72ffe91
--- /dev/null
+++ b/core/src/main/java/org/keycloak/util/JWKSUtils.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.util;
+
+import java.security.PublicKey;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.keycloak.jose.jwk.JSONWebKeySet;
+import org.keycloak.jose.jwk.JWK;
+import org.keycloak.jose.jwk.JWKParser;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class JWKSUtils {
+
+    public static Map<String, PublicKey> getKeysForUse(JSONWebKeySet keySet, JWK.Use requestedUse) {
+        Map<String, PublicKey> result = new HashMap<>();
+
+        for (JWK jwk : keySet.getKeys()) {
+            JWKParser parser = JWKParser.create(jwk);
+            if (jwk.getPublicKeyUse().equals(requestedUse.asString()) && parser.isKeyTypeSupported(jwk.getKeyType())) {
+                result.put(jwk.getKeyId(), parser.toPublicKey());
+            }
+        }
+
+        return result;
+    }
+}
diff --git a/core/src/test/java/org/keycloak/JsonParserTest.java b/core/src/test/java/org/keycloak/JsonParserTest.java
index e346fe6..965a13c 100755
--- a/core/src/test/java/org/keycloak/JsonParserTest.java
+++ b/core/src/test/java/org/keycloak/JsonParserTest.java
@@ -17,17 +17,6 @@
 
 package org.keycloak;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import com.fasterxml.jackson.annotation.JsonAnyGetter;
-import com.fasterxml.jackson.annotation.JsonAnySetter;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonUnwrapped;
 import org.junit.Assert;
 import org.junit.Test;
 import org.keycloak.representations.IDToken;
@@ -36,6 +25,13 @@ import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.representations.oidc.OIDCClientRepresentation;
 import org.keycloak.util.JsonSerialization;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
@@ -139,6 +135,18 @@ public class JsonParserTest {
     }
 
     @Test
+    public void testReadOIDCClientRepWithPairwise() throws IOException {
+        String stringRep = "{\"subject_type\": \"pairwise\", \"jwks_uri\": \"https://op.certification.openid.net:60720/export/jwk_60720.json\", \"contacts\": [\"roland.hedberg@umu.se\"], \"application_type\": \"web\", \"grant_types\": [\"authorization_code\"], \"post_logout_redirect_uris\": [\"https://op.certification.openid.net:60720/logout\"], \"redirect_uris\": [\"https://op.certification.openid.net:60720/authz_cb\"], \"response_types\": [\"code\"], \"require_auth_time\": true, \"default_max_age\": 3600}";
+        OIDCClientRepresentation clientRep = JsonSerialization.readValue(stringRep, OIDCClientRepresentation.class);
+        Assert.assertEquals("pairwise", clientRep.getSubjectType());
+        Assert.assertTrue(clientRep.getRequireAuthTime());
+        Assert.assertEquals(3600, clientRep.getDefaultMaxAge().intValue());
+        Assert.assertEquals(1, clientRep.getRedirectUris().size());
+        Assert.assertEquals("https://op.certification.openid.net:60720/authz_cb", clientRep.getRedirectUris().get(0));
+        Assert.assertNull(clientRep.getJwks());
+    }
+
+    @Test
     public void testReadOIDCClientRepWithJWKS() throws IOException {
         String stringRep = "{\"token_endpoint_auth_method\": \"private_key_jwt\", \"subject_type\": \"public\", \"jwks_uri\": null, \"jwks\": {\"keys\": [{\"use\": \"enc\", \"e\": \"AQAB\", \"d\": \"lZQv0_81euRLeUYU84Aodh0ar7ymDlzWP5NMra4Jklkb-lTBWkI-u4RMsPqGYyW3KHRoL_pgzZXSzQx8RLQfER6timRWb--NxMMKllZubByU3RqH2ooNuocJurspYiXkznPW1Mg9DaNXL0C2hwWPQHTeUVISpjgi5TCOV1ccWVyksFruya_VNL1CIByB-L0GL1rqbKv32cDwi2A3_jJa61cpzfLSIBe-lvCO6tuiDsR4qgJnUwnndQFwEI_4mLmD3iNWXrc8N-poleV8mBfMqBB5fWwy_ZTFCpmQ5AywGmctaik_wNhMoWuA4tUfY6_1LdKld-5Cjq55eLtuJjtvuQ\", \"n\": \"tx3Hjdbc19lkTiohbJrNj4jf2_90MEE122CRrwtFu6saDywKcG7Bi7w2FMAK2oTkuWfqhWRb5BEGmnSXdiCEPO5d-ytqP3nwlZXHaCDYscpP8bB4YLhvCn7R8Efw6gwQle24QPRP3lYoFeuUbDUq7GKA5SfaZUvWoeWjqyLIaBspKQsC26_Umx1E4IXLrMSL6nkRnrYcVZBAXrYCeTP1XtsV38_lZVJfHSaJaUy4PKaj3yvgm93EV2CXybPti7CCMXZ34VqqWiF64pQjZsPu3ZTr7ha_TTQq499-zYRQNDvIVsBDLQQIgrbctuGqj6lrXb31Jj3JIEYqH_4h5X9d0Q\", \"q\": \"1q-r-bmMFbIzrLK2U3elksZq8CqUqZxlSfkGMZuVkxgYMS-e4FPzEp2iirG-eO11aa0cpMMoBdTnVdGJ_ZUR93w0lGf9XnQAJqxP7eOsrUoiW4VWlWH4WfOiLgpO-pFtyTz_JksYYaotc_Z3Zy-Szw6a39IDbuYGy1qL-15oQuc\", \"p\": \"2lrYPppRbcQWu4LtWN6tOVUrtCOPv1eLTKTc7q8vCMcem1Ox5QFB7KnUtNZ5Ni7wnZUeVDfimNebtjNsGvDSrpgIlo9dEnFBQsQIkzZ2SkoYfgmF8hNdi6P-BfRjdgYouy4c6xAnGDgSMTip1YnPRyvbMaoYT9E_tEcBW5wOeoc\", \"kid\": \"a0\", \"kty\": \"RSA\"}, {\"use\": \"sig\", \"e\": \"AQAB\", \"d\": \"DodXDEtkovWWGsMEXYy_nEEMCWyROMOebCnCv0ey3i4M4bh2dmwqgz0e-IKQAFlGiMkidGL1lNbq0uFS04FbuRAR06dYw1cbrNbDdhrWFxKTd1L5D9p-x-gW-YDWhpI8rUGRa76JXkOSxZUbg09_QyUd99CXAHh-FXi_ZkIKD8hK6FrAs68qhLf8MNkUv63DTduw7QgeFfQivdopePxyGuMk5n8veqwsUZsklQkhNlTYQqeM1xb2698ZQcNYkl0OssEsSJKRjXt-LRPowKrdvTuTo2p--HMI0pIEeFs7H_u5OW3jihjvoFClGPynHQhgWmQzlQRvWRXh6FhDVqFeGQ\", \"n\": \"zfZzttF7HmnTYwSMPdxKs5AoczbNS2mOPz-tN1g4ljqI_F1DG8cgQDcN_VDufxoFGRERo2FK6WEN41LhbGEyP6uL6wW6Cy29qE9QZcvY5mXrncndRSOkNcMizvuEJes_fMYrmP_lPiC6kWiqItTk9QBWqJfiYKhCx9cSDXsBmJXn3KWQCVHvj1ANFWW0CWLMKlWN-_NMNLIWJN_pEAocTZMzxSFBK1b5_5J8ZS7hfWRF6MQmjsJcz2jzA21SQZNpre3kwnTGRSwo05sAS-TyeadDqQPWgbqX69UzcGq5irhzN8cpZ_JaTk3Y_uV6owanTZLVvCgdjaAnMYeZhb0KFw\", \"q\": \"5E5XKK5njT-zzRqqTeY2tgP9PJBACeaH_xQRHZ_1ydE7tVd7HdgdaEHfQ1jvKIHFkknWWOBAY1mlBc4YDirLShB_voShD8C-Hx3nF5sne5fleVfU-sZy6Za4B2U75PcE62oZgCPauOTAEm9Xuvrt5aMMovyzR8ecJZhm9bw7naU\", \"p\": \"5vJHCSM3H3q4RltYzENC9RyZZV8EUmpkv9moyguT5t-BUGA-T4W_FGIxzOPXRWOckIplKkoDKhavUeNmTZMCUcue0nkICSJpvNE4Nb2p5PZk_QqSdQNvCasQtdojEG0AmfVD85SU551CYxJdLdDFOqyK2entpMr8lhokem189As\", \"kid\": \"a1\", \"kty\": \"RSA\"}, {\"d\": \"S4_OufhLBgXFMgIDMI1zlVe2uCExpcEAQ80J_lXfS8I\", \"use\": \"sig\", \"crv\": \"P-256\", \"kty\": \"EC\", \"y\": \"DBdNyq30mXmUs_BIvKMqaTTNO7HDhCi0YiC8GciwNYk\", \"x\": \"cYwzBoyjRjxj334bRTqanONf7DUYK-6TgiuN0DixJAk\", \"kid\": \"a2\"}, {\"d\": \"33TnYgdJtWAiVosKqUnz0zSmvWTbsx5-6pceynW6Xck\", \"use\": \"enc\", \"crv\": \"P-256\", \"kty\": \"EC\", \"y\": \"Cula95Eix1Ia77St3OULe6-UKWs5I06nmdfUzhXUQTs\", \"x\": \"wk8HBVxNNzj1gJBxPmmx9XYW1L61ObBGzxpRa6_OqWU\", \"kid\": \"a3\"}]}, \"application_type\": \"web\", \"contacts\": [\"roland.hedberg@umu.se\"], \"post_logout_redirect_uris\": [\"https://op.certification.openid.net:60784/logout\"], \"redirect_uris\": [\"https://op.certification.openid.net:60784/authz_cb\"], \"response_types\": [\"code\"], \"require_auth_time\": true, \"grant_types\": [\"authorization_code\"], \"default_max_age\": 3600}";
         OIDCClientRepresentation clientRep = JsonSerialization.readValue(stringRep, OIDCClientRepresentation.class);
diff --git a/distribution/downloads/pom.xml b/distribution/downloads/pom.xml
index 71b27d9..e186545 100755
--- a/distribution/downloads/pom.xml
+++ b/distribution/downloads/pom.xml
@@ -112,12 +112,6 @@
                                     <type>zip</type>
                                     <destFileName>keycloak-examples-${project.version}.zip</destFileName>
                                 </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.keycloak</groupId>
-                                    <artifactId>keycloak-src-dist</artifactId>
-                                    <type>zip</type>
-                                    <destFileName>keycloak-src-${project.version}.zip</destFileName>
-                                </artifactItem>
                             </artifactItems>
                             <outputDirectory>target/${project.version}</outputDirectory>
                         </configuration>
diff --git a/distribution/pom.xml b/distribution/pom.xml
index 74e0e40..746d5ae 100755
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -40,7 +40,6 @@
         <module>proxy-dist</module>
         <module>server-dist</module>
         <module>server-overlay</module>
-        <module>src-dist</module>
         <module>feature-packs</module>
     </modules>
 
diff --git a/examples/authz/hello-world/src/main/java/org/keycloak/authz/helloworld/AuthorizationClientExample.java b/examples/authz/hello-world/src/main/java/org/keycloak/authz/helloworld/AuthorizationClientExample.java
index 887a461..493637a 100644
--- a/examples/authz/hello-world/src/main/java/org/keycloak/authz/helloworld/AuthorizationClientExample.java
+++ b/examples/authz/hello-world/src/main/java/org/keycloak/authz/helloworld/AuthorizationClientExample.java
@@ -43,7 +43,7 @@ public class AuthorizationClientExample {
     }
 
     private static void introspectRequestingPartyToken() {
-        // create a new instance based on the configuration define at keycloak-authz.json
+        // create a new instance based on the configuration defined in keycloak-authz.json
         AuthzClient authzClient = AuthzClient.create();
 
         // query the server for a resource with a given name
@@ -51,8 +51,9 @@ public class AuthorizationClientExample {
                 .resource()
                 .findByFilter("name=Default Resource");
 
-        // obtian a Entitlement API Token in order to get access to the Entitlement API.
-        // this token is just an access token issued to a client on behalf of an user with a scope kc_entitlement
+        // obtain an Entitlement API Token in order to get access to the Entitlement API.
+        // this token is just an access token issued to a client on behalf of an user
+        // with a scope = kc_entitlement
         String eat = getEntitlementAPIToken(authzClient);
 
         // create an entitlement request
@@ -63,7 +64,8 @@ public class AuthorizationClientExample {
 
         request.addPermission(permission);
 
-        // send the entitlement request to the server in order to obtain a RPT with all permissions granted to the user
+        // send the entitlement request to the server in order to
+        // obtain an RPT with all permissions granted to the user
         EntitlementResponse response = authzClient.entitlement(eat).get("hello-world-authz-service", request);
         String rpt = response.getRpt();
 
@@ -79,7 +81,7 @@ public class AuthorizationClientExample {
     }
 
     private static void createResource() {
-        // create a new instance based on the configuration define at keycloak-authz.json
+        // create a new instance based on the configuration defined in keycloak-authz.json
         AuthzClient authzClient = AuthzClient.create();
 
         // create a new resource representation with the information we want
@@ -111,8 +113,9 @@ public class AuthorizationClientExample {
         // create a new instance based on the configuration define at keycloak-authz.json
         AuthzClient authzClient = AuthzClient.create();
 
-        // obtian a Entitlement API Token in order to get access to the Entitlement API.
-        // this token is just an access token issued to a client on behalf of an user with a scope kc_entitlement
+        // obtain an Entitlement API Token in order to get access to the Entitlement API.
+        // this token is just an access token issued to a client on behalf of an user
+        // with a scope = kc_entitlement
         String eat = getEntitlementAPIToken(authzClient);
 
         // create an entitlement request
@@ -123,7 +126,8 @@ public class AuthorizationClientExample {
 
         request.addPermission(permission);
 
-        // send the entitlement request to the server in order to obtain a RPT with all permissions granted to the user
+        // send the entitlement request to the server in order to obtain a RPT
+        // with all permissions granted to the user
         EntitlementResponse response = authzClient.entitlement(eat).get("hello-world-authz-service", request);
         String rpt = response.getRpt();
 
@@ -133,7 +137,7 @@ public class AuthorizationClientExample {
     }
 
     private static void obtainAllEntitlements() {
-        // create a new instance based on the configuration define at keycloak-authz.json
+        // create a new instance based on the configuration defined in keycloak-authz.json
         AuthzClient authzClient = AuthzClient.create();
 
         // obtian a Entitlement API Token in order to get access to the Entitlement API.
diff --git a/examples/authz/hello-world-authz-service/src/main/webapp/WEB-INF/keycloak.json b/examples/authz/hello-world-authz-service/src/main/webapp/WEB-INF/keycloak.json
index a492837..b5a1bbf 100644
--- a/examples/authz/hello-world-authz-service/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/authz/hello-world-authz-service/src/main/webapp/WEB-INF/keycloak.json
@@ -1,6 +1,5 @@
 {
   "realm": "hello-world-authz",
-  "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "http://localhost:8080/auth",
   "ssl-required": "external",
   "resource": "hello-world-authz-service",
diff --git a/examples/authz/photoz/photoz-html5-client/src/main/webapp/keycloak.json b/examples/authz/photoz/photoz-html5-client/src/main/webapp/keycloak.json
index c1dee24..affafdd 100644
--- a/examples/authz/photoz/photoz-html5-client/src/main/webapp/keycloak.json
+++ b/examples/authz/photoz/photoz-html5-client/src/main/webapp/keycloak.json
@@ -1,6 +1,5 @@
 {
   "realm": "photoz",
-  "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "http://localhost:8080/auth",
   "ssl-required" : "external",
   "resource" : "photoz-html5-client",
diff --git a/examples/authz/photoz/photoz-restful-api/src/main/webapp/WEB-INF/keycloak.json b/examples/authz/photoz/photoz-restful-api/src/main/webapp/WEB-INF/keycloak.json
index 6849d07..9e06730 100644
--- a/examples/authz/photoz/photoz-restful-api/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/authz/photoz/photoz-restful-api/src/main/webapp/WEB-INF/keycloak.json
@@ -1,6 +1,5 @@
 {
   "realm": "photoz",
-  "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "http://localhost:8080/auth",
   "ssl-required": "external",
   "resource": "photoz-restful-api",
diff --git a/examples/authz/servlet-authz/src/main/webapp/WEB-INF/keycloak.json b/examples/authz/servlet-authz/src/main/webapp/WEB-INF/keycloak.json
index eaffea8..f6b9c90 100644
--- a/examples/authz/servlet-authz/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/authz/servlet-authz/src/main/webapp/WEB-INF/keycloak.json
@@ -1,6 +1,5 @@
 {
   "realm": "servlet-authz",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "http://localhost:8080/auth",
   "ssl-required" : "external",
   "resource" : "servlet-authz-app",
diff --git a/examples/basic-auth/src/main/webapp/WEB-INF/keycloak.json b/examples/basic-auth/src/main/webapp/WEB-INF/keycloak.json
index 4502199..9da7ed4 100644
--- a/examples/basic-auth/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/basic-auth/src/main/webapp/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "basic-auth",
   "resource" : "basic-auth-service",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "/auth",
   "ssl-required" : "external",
   "enable-basic-auth" : "true",
diff --git a/examples/broker/facebook-authentication/src/main/webapp/keycloak.json b/examples/broker/facebook-authentication/src/main/webapp/keycloak.json
index 55446af..17743f6 100644
--- a/examples/broker/facebook-authentication/src/main/webapp/keycloak.json
+++ b/examples/broker/facebook-authentication/src/main/webapp/keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "facebook-identity-provider-realm",
   "resource" : "facebook-authentication",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "/auth",
   "ssl-required" : "external",
   "public-client" : true
diff --git a/examples/broker/google-authentication/src/main/webapp/keycloak.json b/examples/broker/google-authentication/src/main/webapp/keycloak.json
index 93c25b4..f05da2f 100644
--- a/examples/broker/google-authentication/src/main/webapp/keycloak.json
+++ b/examples/broker/google-authentication/src/main/webapp/keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "google-identity-provider-realm",
   "resource" : "google-authentication",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "/auth",
   "ssl-required" : "external",
   "public-client" : true
diff --git a/examples/broker/twitter-authentication/src/main/webapp/keycloak.json b/examples/broker/twitter-authentication/src/main/webapp/keycloak.json
index 7243636..2f74514 100644
--- a/examples/broker/twitter-authentication/src/main/webapp/keycloak.json
+++ b/examples/broker/twitter-authentication/src/main/webapp/keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "twitter-identity-provider-realm",
   "resource" : "twitter-authentication",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "/auth",
   "ssl-required" : "external",
   "public-client" : true
diff --git a/examples/cors/angular-product-app/src/main/webapp/keycloak.json b/examples/cors/angular-product-app/src/main/webapp/keycloak.json
index 40b35a1..d685459 100755
--- a/examples/cors/angular-product-app/src/main/webapp/keycloak.json
+++ b/examples/cors/angular-product-app/src/main/webapp/keycloak.json
@@ -1,6 +1,5 @@
 {
   "realm" : "cors",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "http://localhost-auth:8080/auth",
   "ssl-required" : "external",
   "resource" : "angular-cors-product",
diff --git a/examples/cors/database-service/src/main/webapp/WEB-INF/keycloak.json b/examples/cors/database-service/src/main/webapp/WEB-INF/keycloak.json
index 265049f..61da408 100755
--- a/examples/cors/database-service/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/cors/database-service/src/main/webapp/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "cors",
   "resource" : "cors-database-service",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "http://localhost-auth:8080/auth",
   "bearer-only" : true,
   "ssl-required": "external",
diff --git a/examples/demo-template/angular2-product-app/pom.xml b/examples/demo-template/angular2-product-app/pom.xml
index 7eecc42..d461196 100644
--- a/examples/demo-template/angular2-product-app/pom.xml
+++ b/examples/demo-template/angular2-product-app/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>keycloak-examples-demo-parent</artifactId>
         <groupId>org.keycloak</groupId>
-        <version></version>
+        <version>2.2.0-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/.gitignore b/examples/demo-template/angular2-product-app/src/main/webapp/.gitignore
new file mode 100644
index 0000000..1c790fa
--- /dev/null
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/.gitignore
@@ -0,0 +1,4 @@
+app/*.js
+app/*.js.map
+node_modules
+typings
diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/app/app.module.ts b/examples/demo-template/angular2-product-app/src/main/webapp/app/app.module.ts
new file mode 100644
index 0000000..f345fa3
--- /dev/null
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/app/app.module.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { HttpModule } from '@angular/http';
+import { KeycloakService } from './keycloak.service';
+import { AppComponent } from './app.component';
+
+@NgModule({
+  imports: [
+    BrowserModule,
+    HttpModule
+  ],
+  declarations: [
+    AppComponent
+  ],
+  providers: [
+    KeycloakService,
+  ],
+  bootstrap: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/app/main.ts b/examples/demo-template/angular2-product-app/src/main/webapp/app/main.ts
index 73613b2..6bf99bf 100644
--- a/examples/demo-template/angular2-product-app/src/main/webapp/app/main.ts
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/app/main.ts
@@ -1,14 +1,11 @@
-import 'rxjs/Rx';
-import {bootstrap}    from 'angular2/platform/browser';
-import {HTTP_BINDINGS} from 'angular2/http';
-import {KeycloakService} from './keycloak';
-import {AppComponent} from './app';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app.module';
 
-KeycloakService.init().then(
-    o=>{
-        bootstrap(AppComponent,[HTTP_BINDINGS, KeycloakService]);
-    },
-    x=>{
-        window.location.reload();
-    }
-);
\ No newline at end of file
+import {KeycloakService} from './keycloak.service';
+
+KeycloakService.init()
+  .then(() => {
+    const platform = platformBrowserDynamic();
+    platform.bootstrapModule(AppModule);
+  })
+  .catch(() => window.location.reload());
diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/index.html b/examples/demo-template/angular2-product-app/src/main/webapp/index.html
index 2da600c..1edeb56 100644
--- a/examples/demo-template/angular2-product-app/src/main/webapp/index.html
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/index.html
@@ -2,48 +2,23 @@
 <html>
   <head>
     <title>Angular 2 QuickStart</title>
+    <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
-
-
-
-
-
-
-  </head>
-
-  <!-- 3. Display the application -->
-  <body>
-    <my-app>Loading...</my-app>
-
-
-
     <!-- 1. Load libraries -->
-    <!-- IE required polyfills, in this exact order -->
-    <script src="node_modules/es6-shim/es6-shim.min.js"></script>
-    <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
-
-    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
+    <!-- Polyfill(s) for older browsers -->
+    <script src="node_modules/core-js/client/shim.min.js"></script>
+    <script src="node_modules/zone.js/dist/zone.js"></script>
+    <script src="node_modules/reflect-metadata/Reflect.js"></script>
     <script src="node_modules/systemjs/dist/system.src.js"></script>
-    <script src="node_modules/rxjs/bundles/Rx.js"></script>
-    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
-    <script src="node_modules/angular2/bundles/http.js"></script>
-
-
     <script src="/auth/js/keycloak.js"></script>
-
     <!-- 2. Configure SystemJS -->
+    <script src="systemjs.config.js"></script>
     <script>
-      System.config({
-        packages: {
-          app: {
-            format: 'register',
-            defaultExtension: 'js'
-          }
-        }
-      });
-      System.import('app/main')
-            .then(null, console.error.bind(console));
+      System.import('app').catch(function(err){ console.error(err); });
     </script>
+  </head>
+  <!-- 3. Display the application -->
+  <body>
+    <my-app>Loading...</my-app>
   </body>
-
 </html>
diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/keycloak.json b/examples/demo-template/angular2-product-app/src/main/webapp/keycloak.json
index ddd1f2e..87a2ad6 100644
--- a/examples/demo-template/angular2-product-app/src/main/webapp/keycloak.json
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/keycloak.json
@@ -1,6 +1,5 @@
 {
   "realm": "demo",
-  "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "/auth",
   "ssl-required": "external",
   "resource": "angular2-product",
diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/package.json b/examples/demo-template/angular2-product-app/src/main/webapp/package.json
index f66b44c..5bd783b 100644
--- a/examples/demo-template/angular2-product-app/src/main/webapp/package.json
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/package.json
@@ -2,24 +2,36 @@
   "name": "angular2-product-app",
   "version": "1.0.0",
   "scripts": {
+    "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
+    "lite": "lite-server",
+    "postinstall": "typings install",
     "tsc": "tsc",
     "tsc:w": "tsc -w",
-    "lite": "lite-server",
-    "start": "concurrent \"npm run tsc:w\" \"npm run lite\" "
+    "typings": "typings"
   },
   "license": "ISC",
   "dependencies": {
-    "angular2": "2.0.0-beta.3",
-    "systemjs": "0.19.6",
-    "es6-promise": "^3.0.2",
-    "es6-shim": "^0.33.3",
-    "reflect-metadata": "0.1.2",
-    "rxjs": "5.0.0-beta.0",
-    "zone.js": "0.5.11"
+    "@angular/common": "2.0.0",
+    "@angular/compiler": "2.0.0",
+    "@angular/core": "2.0.0",
+    "@angular/forms": "2.0.0",
+    "@angular/http": "2.0.0",
+    "@angular/platform-browser": "2.0.0",
+    "@angular/platform-browser-dynamic": "2.0.0",
+    "@angular/router": "3.0.0",
+    "@angular/upgrade": "2.0.0",
+    "angular2-in-memory-web-api": "0.0.20",
+    "bootstrap": "^3.3.6",
+    "core-js": "^2.4.1",
+    "reflect-metadata": "^0.1.3",
+    "rxjs": "5.0.0-beta.12",
+    "systemjs": "0.19.27",
+    "zone.js": "^0.6.21"
   },
   "devDependencies": {
-    "concurrently": "^1.0.0",
-    "lite-server": "^2.0.1",
-    "typescript": "^1.7.5"
+    "concurrently": "^2.2.0",
+    "lite-server": "^2.2.2",
+    "typescript": "^2.0.2",
+    "typings": "^1.3.2"
   }
 }
diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/systemjs.config.js b/examples/demo-template/angular2-product-app/src/main/webapp/systemjs.config.js
new file mode 100644
index 0000000..de199e6
--- /dev/null
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/systemjs.config.js
@@ -0,0 +1,43 @@
+/**
+ * System configuration for Angular 2 samples
+ * Adjust as necessary for your application needs.
+ */
+(function (global) {
+  System.config({
+    paths: {
+      // paths serve as alias
+      'npm:': 'node_modules/'
+    },
+    // map tells the System loader where to look for things
+    map: {
+      // our app is within the app folder
+      app: 'app',
+      // angular bundles
+      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
+      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
+      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
+      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
+      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
+      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
+      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
+      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
+      // other libraries
+      'rxjs':                       'npm:rxjs',
+      'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api',
+    },
+    // packages tells the System loader how to load when no filename and/or no extension
+    packages: {
+      app: {
+        main: './main.js',
+        defaultExtension: 'js'
+      },
+      rxjs: {
+        defaultExtension: 'js'
+      },
+      'angular2-in-memory-web-api': {
+        main: './index.js',
+        defaultExtension: 'js'
+      }
+    }
+  });
+})(this);
diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/tsconfig.json b/examples/demo-template/angular2-product-app/src/main/webapp/tsconfig.json
index 52c77a5..e6a6eac 100644
--- a/examples/demo-template/angular2-product-app/src/main/webapp/tsconfig.json
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/tsconfig.json
@@ -1,15 +1,12 @@
 {
   "compilerOptions": {
     "target": "es5",
-    "module": "system",
+    "module": "commonjs",
     "moduleResolution": "node",
-    "sourceMap": false,
+    "sourceMap": true,
     "emitDecoratorMetadata": true,
     "experimentalDecorators": true,
     "removeComments": false,
     "noImplicitAny": false
-  },
-  "exclude": [
-    "node_modules"
-  ]
-}
\ No newline at end of file
+  }
+}
diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/typings.json b/examples/demo-template/angular2-product-app/src/main/webapp/typings.json
new file mode 100644
index 0000000..7da31ca
--- /dev/null
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/typings.json
@@ -0,0 +1,7 @@
+{
+  "globalDependencies": {
+    "core-js": "registry:dt/core-js#0.0.0+20160725163759",
+    "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
+    "node": "registry:dt/node#6.0.0+20160909174046"
+  }
+}
diff --git a/examples/demo-template/angular-product-app/src/main/webapp/keycloak.json b/examples/demo-template/angular-product-app/src/main/webapp/keycloak.json
index 72ecb5b..174053e 100755
--- a/examples/demo-template/angular-product-app/src/main/webapp/keycloak.json
+++ b/examples/demo-template/angular-product-app/src/main/webapp/keycloak.json
@@ -1,6 +1,5 @@
 {
   "realm" : "demo",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "/auth",
   "ssl-required" : "external",
   "resource" : "angular-product",
diff --git a/examples/demo-template/customer-app/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/customer-app/src/main/webapp/WEB-INF/keycloak.json
index c2241b3..2061909 100755
--- a/examples/demo-template/customer-app/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/demo-template/customer-app/src/main/webapp/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
     "realm": "demo",
     "resource": "customer-portal",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
     "auth-server-url": "/auth",
     "ssl-required" : "external",
     "expose-token": true,
diff --git a/examples/demo-template/customer-app-cli/src/main/resources/META-INF/keycloak.json b/examples/demo-template/customer-app-cli/src/main/resources/META-INF/keycloak.json
index 51c8775..1c61433 100644
--- a/examples/demo-template/customer-app-cli/src/main/resources/META-INF/keycloak.json
+++ b/examples/demo-template/customer-app-cli/src/main/resources/META-INF/keycloak.json
@@ -1,6 +1,5 @@
 {
   "realm" : "demo",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "http://localhost:8080/auth",
   "ssl-required" : "external",
   "resource" : "customer-portal-cli",
diff --git a/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/keycloak.json
index 14e56f5..3766330 100755
--- a/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
     "realm": "demo",
     "resource": "customer-portal-filter",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
     "auth-server-url": "/auth",
     "ssl-required" : "external",
     "expose-token": true,
diff --git a/examples/demo-template/customer-app-js/src/main/webapp/keycloak.json b/examples/demo-template/customer-app-js/src/main/webapp/keycloak.json
index 224c70b..4a60ffa 100644
--- a/examples/demo-template/customer-app-js/src/main/webapp/keycloak.json
+++ b/examples/demo-template/customer-app-js/src/main/webapp/keycloak.json
@@ -1,6 +1,5 @@
 {
   "realm" : "demo",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "/auth",
   "ssl-required" : "external",
   "resource" : "customer-portal-js",
diff --git a/examples/demo-template/database-service/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/database-service/src/main/webapp/WEB-INF/keycloak.json
index cb93854..72e4903 100755
--- a/examples/demo-template/database-service/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/demo-template/database-service/src/main/webapp/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "demo",
   "resource" : "database-service",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "/auth",
   "bearer-only" : true,
   "ssl-required" : "external"
diff --git a/examples/demo-template/offline-access-app/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/offline-access-app/src/main/webapp/WEB-INF/keycloak.json
index dff976c..600dcfa 100644
--- a/examples/demo-template/offline-access-app/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/demo-template/offline-access-app/src/main/webapp/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm": "demo",
   "resource": "offline-access-portal",
-  "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "/auth",
   "ssl-required" : "external",
   "credentials": {
diff --git a/examples/demo-template/pom.xml b/examples/demo-template/pom.xml
index b7fc027..dbc0218 100755
--- a/examples/demo-template/pom.xml
+++ b/examples/demo-template/pom.xml
@@ -51,6 +51,7 @@
         <module>example-ear</module>
         <module>admin-access-app</module>
         <module>angular-product-app</module>
+        <module>angular2-product-app</module>
         <module>database-service</module>
         <module>third-party</module>
         <module>third-party-cdi</module>
diff --git a/examples/demo-template/product-app/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/product-app/src/main/webapp/WEB-INF/keycloak.json
index 0a86c04..1092701 100755
--- a/examples/demo-template/product-app/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/demo-template/product-app/src/main/webapp/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "demo",
   "resource" : "product-portal",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "/auth",
   "ssl-required" : "external",
   "credentials" : {
diff --git a/examples/demo-template/service-account/src/main/java/org/keycloak/example/ProductServiceAccountServlet.java b/examples/demo-template/service-account/src/main/java/org/keycloak/example/ProductServiceAccountServlet.java
index e4d6a40..72ffd49 100644
--- a/examples/demo-template/service-account/src/main/java/org/keycloak/example/ProductServiceAccountServlet.java
+++ b/examples/demo-template/service-account/src/main/java/org/keycloak/example/ProductServiceAccountServlet.java
@@ -41,6 +41,7 @@ import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.message.BasicNameValuePair;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.RSATokenVerifier;
+import org.keycloak.adapters.rotation.AdapterRSATokenVerifier;
 import org.keycloak.common.VerificationException;
 import org.keycloak.adapters.KeycloakDeployment;
 import org.keycloak.adapters.KeycloakDeploymentBuilder;
@@ -163,7 +164,7 @@ public abstract class ProductServiceAccountServlet extends HttpServlet {
     private void setTokens(HttpServletRequest req, KeycloakDeployment deployment, AccessTokenResponse tokenResponse) throws IOException, VerificationException {
         String token = tokenResponse.getToken();
         String refreshToken = tokenResponse.getRefreshToken();
-        AccessToken tokenParsed = RSATokenVerifier.verifyToken(token, deployment.getRealmKey(), deployment.getRealmInfoUrl());
+        AccessToken tokenParsed = AdapterRSATokenVerifier.verifyToken(token, deployment);
         req.getSession().setAttribute(TOKEN, token);
         req.getSession().setAttribute(REFRESH_TOKEN, refreshToken);
         req.getSession().setAttribute(TOKEN_PARSED, tokenParsed);
diff --git a/examples/demo-template/service-account/src/main/webapp/WEB-INF/keycloak-client-secret.json b/examples/demo-template/service-account/src/main/webapp/WEB-INF/keycloak-client-secret.json
index 7eec22a..1a9322d 100644
--- a/examples/demo-template/service-account/src/main/webapp/WEB-INF/keycloak-client-secret.json
+++ b/examples/demo-template/service-account/src/main/webapp/WEB-INF/keycloak-client-secret.json
@@ -1,6 +1,5 @@
 {
   "realm" : "demo",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "http://localhost:8080/auth",
   "ssl-required" : "external",
   "resource" : "product-sa-client",
diff --git a/examples/demo-template/service-account/src/main/webapp/WEB-INF/keycloak-client-signed-jwt.json b/examples/demo-template/service-account/src/main/webapp/WEB-INF/keycloak-client-signed-jwt.json
index 3e90c34..3c99da7 100644
--- a/examples/demo-template/service-account/src/main/webapp/WEB-INF/keycloak-client-signed-jwt.json
+++ b/examples/demo-template/service-account/src/main/webapp/WEB-INF/keycloak-client-signed-jwt.json
@@ -1,6 +1,5 @@
 {
   "realm" : "demo",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "http://localhost:8080/auth",
   "ssl-required" : "external",
   "resource" : "product-sa-client-jwt-auth",
diff --git a/examples/fuse/camel/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/examples/fuse/camel/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index a4796cc..56550d6 100644
--- a/examples/fuse/camel/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/examples/fuse/camel/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -26,7 +26,6 @@
     <bean id="kcAdapterConfig" class="org.keycloak.representations.adapters.config.AdapterConfig">
         <property name="realm" value="demo"/>
         <property name="resource" value="admin-camel-endpoint"/>
-        <property name="realmKey" value="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"/>
         <property name="bearerOnly" value="true"/>
         <property name="authServerUrl" value="http://localhost:8080/auth" />
         <property name="sslRequired" value="EXTERNAL"/>
diff --git a/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/keycloak.json b/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/keycloak.json
index b5d6b30..c7f61f6 100755
--- a/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
     "realm": "demo",
     "resource": "customer-portal",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
     "auth-server-url": "http://localhost:8080/auth",
     "ssl-required" : "external",
     "credentials": {
diff --git a/examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/keycloak.json b/examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/keycloak.json
index f5d7e1a..a8c4b75 100644
--- a/examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/keycloak.json
+++ b/examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
     "realm": "demo",
     "resource": "builtin-cxf-app",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
     "auth-server-url": "http://localhost:8080/auth",
     "ssl-required" : "external",
     "credentials": {
diff --git a/examples/fuse/cxf-jaxws/src/main/resources/META-INF/spring/beans.xml b/examples/fuse/cxf-jaxws/src/main/resources/META-INF/spring/beans.xml
index 2d15ae0..8a808c6 100644
--- a/examples/fuse/cxf-jaxws/src/main/resources/META-INF/spring/beans.xml
+++ b/examples/fuse/cxf-jaxws/src/main/resources/META-INF/spring/beans.xml
@@ -32,7 +32,6 @@
     <bean id="kcAdapterConfig" class="org.keycloak.representations.adapters.config.AdapterConfig">
         <property name="realm" value="demo"/>
         <property name="resource" value="custom-cxf-endpoint"/>
-        <property name="realmKey" value="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"/>
         <property name="bearerOnly" value="true"/>
         <property name="authServerUrl" value="http://localhost:8080/auth" />
         <property name="sslRequired" value="EXTERNAL"/>
diff --git a/examples/fuse/external-config/external-config-keycloak.json b/examples/fuse/external-config/external-config-keycloak.json
index 920e99a..469da82 100644
--- a/examples/fuse/external-config/external-config-keycloak.json
+++ b/examples/fuse/external-config/external-config-keycloak.json
@@ -1,7 +1,6 @@
 {
     "realm": "demo",
     "resource": "external-config",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
     "auth-server-url": "http://localhost:8080/auth",
     "ssl-required" : "external",
     "credentials": {
diff --git a/examples/fuse/fuse-admin/keycloak-direct-access.json b/examples/fuse/fuse-admin/keycloak-direct-access.json
index 8e5ac0f..2441134 100644
--- a/examples/fuse/fuse-admin/keycloak-direct-access.json
+++ b/examples/fuse/fuse-admin/keycloak-direct-access.json
@@ -1,7 +1,6 @@
 {
     "realm": "demo",
     "resource": "ssh-jmx-admin-client",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
     "ssl-required" : "external",
     "auth-server-url" : "http://localhost:8080/auth",
     "credentials": {
diff --git a/examples/fuse/product-app-fuse/src/main/resources/WEB-INF/keycloak.json b/examples/fuse/product-app-fuse/src/main/resources/WEB-INF/keycloak.json
index 2a52d24..e90433a 100644
--- a/examples/fuse/product-app-fuse/src/main/resources/WEB-INF/keycloak.json
+++ b/examples/fuse/product-app-fuse/src/main/resources/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
     "realm": "demo",
     "resource": "product-portal",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
     "auth-server-url": "http://localhost:8080/auth",
     "ssl-required" : "external",
     "credentials": {
diff --git a/examples/js-console/src/main/webapp/keycloak.json b/examples/js-console/src/main/webapp/keycloak.json
index c0c04d5..cc4bab3 100644
--- a/examples/js-console/src/main/webapp/keycloak.json
+++ b/examples/js-console/src/main/webapp/keycloak.json
@@ -1,6 +1,5 @@
 {
   "realm" : "example",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "/auth",
   "ssl-required" : "external",
   "resource" : "js-console",
diff --git a/examples/kerberos/src/main/webapp/WEB-INF/keycloak.json b/examples/kerberos/src/main/webapp/WEB-INF/keycloak.json
index db1223c..7e9d91a 100644
--- a/examples/kerberos/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/kerberos/src/main/webapp/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "kerberos-demo",
   "resource" : "kerberos-app",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "/auth",
   "ssl-required" : "external",
   "credentials": {
diff --git a/examples/ldap/src/main/webapp/WEB-INF/keycloak.json b/examples/ldap/src/main/webapp/WEB-INF/keycloak.json
index 84e1129..f43107b 100644
--- a/examples/ldap/src/main/webapp/WEB-INF/keycloak.json
+++ b/examples/ldap/src/main/webapp/WEB-INF/keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "ldap-demo",
   "resource" : "ldap-app",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "/auth",
   "ssl-required" : "external",
   "credentials": {
diff --git a/examples/multi-tenant/src/main/resources/tenant1-keycloak.json b/examples/multi-tenant/src/main/resources/tenant1-keycloak.json
index 57be277..34c1773 100644
--- a/examples/multi-tenant/src/main/resources/tenant1-keycloak.json
+++ b/examples/multi-tenant/src/main/resources/tenant1-keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "tenant1",
   "resource" : "multi-tenant",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "http://localhost:8080/auth",
   "ssl-required" : "external",
   "credentials" : {
diff --git a/examples/multi-tenant/src/main/resources/tenant2-keycloak.json b/examples/multi-tenant/src/main/resources/tenant2-keycloak.json
index 4f221dc..5877082 100644
--- a/examples/multi-tenant/src/main/resources/tenant2-keycloak.json
+++ b/examples/multi-tenant/src/main/resources/tenant2-keycloak.json
@@ -1,7 +1,6 @@
 {
   "realm" : "tenant2",
   "resource" : "multi-tenant",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA0oJjgPQJhnVhOo51KauQGfLLreMFu64OJdKXRnfvAQJQTuKNwc5JrR63l/byyW1B6FgclABF818TtLvMCAkn4EuFwQZCZhg3x3+lFGiB/IzC6UAt4Bi0JQrTbdh83/U97GIPegvaDqiqEiQESEkbCZWxM6sh/34hQaAhCaFpMwIDAQAB",
   "auth-server-url" : "http://localhost:8080/auth",
   "ssl-required" : "external",
   "credentials" : {
diff --git a/examples/providers/authenticator/README.md b/examples/providers/authenticator/README.md
index 1edf0ed..54dc752 100755
--- a/examples/providers/authenticator/README.md
+++ b/examples/providers/authenticator/README.md
@@ -6,13 +6,12 @@ of Keycloak.   To deploy, build this directory then take the jar and copy it to 
 
     KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.secret-question --resources=target/authenticator-required-action-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-services,org.jboss.resteasy.resteasy-jaxrs,javax.ws.rs.api"
 
-Then registering the provider by editing keycloak-server.json and adding the module to the providers field:
-
-    "providers": [
-        ....
-        "module:org.keycloak.examples.secret-question"
-    ],
+Then registering the provider by editing `standalone/configuration/standalone.xml` and adding the module to the providers element:
 
+    <providers>
+        ...
+        <provider>module:org.keycloak.examples.secret-question</provider>
+    </providers>
 
 You then have to copy the secret-question.ftl and secret-question-config.ftl files to the themes/base/login directory.
 
diff --git a/examples/providers/authenticator/src/main/java/org/keycloak/examples/authenticator/SecretQuestionCredentialProvider.java b/examples/providers/authenticator/src/main/java/org/keycloak/examples/authenticator/SecretQuestionCredentialProvider.java
index 61e07a8..693c0eb 100644
--- a/examples/providers/authenticator/src/main/java/org/keycloak/examples/authenticator/SecretQuestionCredentialProvider.java
+++ b/examples/providers/authenticator/src/main/java/org/keycloak/examples/authenticator/SecretQuestionCredentialProvider.java
@@ -70,7 +70,7 @@ public class SecretQuestionCredentialProvider implements CredentialProvider, Cre
             CredentialModel secret = new CredentialModel();
             secret.setType(SECRET_QUESTION);
             secret.setValue(credInput.getValue());
-            secret.setCreatedDate(Time.toMillis(Time.currentTime()));
+            secret.setCreatedDate(Time.currentTimeMillis());
             session.userCredentialManager().createCredential(realm ,user, secret);
         } else {
             creds.get(0).setValue(credInput.getValue());
diff --git a/examples/providers/domain-extension/README.md b/examples/providers/domain-extension/README.md
index e1aa2cd..51e2b3c 100644
--- a/examples/providers/domain-extension/README.md
+++ b/examples/providers/domain-extension/README.md
@@ -6,12 +6,12 @@ To run, deploy as a module by running:
     $KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.domain-extension-example --resources=target/domain-extension-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-services,org.keycloak.keycloak-model-jpa,org.keycloak.keycloak-server-spi,javax.ws.rs.api,javax.persistence.api,org.hibernate,org.javassist"
 
 
-Then registering the provider by editing keycloak-server.json and adding the module to the providers field:
+Then registering the provider by editing `standalone/configuration/standalone.xml` and adding the module to the providers element:
 
-    "providers": [
-        ....
-        "module:org.keycloak.examples.domain-extension-example"
-    ],
+    <providers>
+        ...
+        <provider>module:org.keycloak.examples.domain-extension-example</provider>
+    </providers>
 
 Then start (or restart) the server.
 
diff --git a/examples/providers/event-listener-sysout/README.md b/examples/providers/event-listener-sysout/README.md
index 57519f3..8e1a085 100644
--- a/examples/providers/event-listener-sysout/README.md
+++ b/examples/providers/event-listener-sysout/README.md
@@ -5,23 +5,25 @@ To deploy copy target/event-listener-sysout-example.jar to providers directory. 
 
     KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.event-sysout --resources=target/event-listener-sysout-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-server-spi"
 
-Then registering the provider by editing keycloak-server.json and adding the module to the providers field:
+Then registering the provider by editing `standalone/configuration/standalone.xml` and adding the module to the providers element:
 
-    "providers": [
-        ....
-        "module:org.keycloak.examples.event-sysout"
-    ],
+    <providers>
+        ...
+        <provider>module:org.keycloak.examples.event-sysout</provider>
+    </providers>
 
 Then start (or restart) the server. Once started open the admin console, select your realm, then click on Events, 
 followed by config. Click on Listeners select box, then pick sysout from the dropdown. After this try to logout and 
 login again to see events printed to System.out.
 
 The example event listener can be configured to exclude certain events, for example to exclude REFRESH_TOKEN and
-CODE_TO_TOKEN events add the following to keycloak-server.json:
+CODE_TO_TOKEN events add the following to `standalone.xml`:
 
     ...
-    "eventsListener": {
-        "sysout": {
-            "exclude": [ "REFRESH_TOKEN", "CODE_TO_TOKEN" ]
-        }
-    }
+    <spi name="eventsListener">
+        <provider name="sysout">
+            <properties>
+                <property name="exclude-events" value="[&quot;REFRESH_TOKEN&quot;, &quot;CODE_TO_TOKEN&quot;]"/>
+            </properties>
+        </provider
+    </spi>
diff --git a/examples/providers/event-store-mem/README.md b/examples/providers/event-store-mem/README.md
index d533fda..682ff42 100644
--- a/examples/providers/event-store-mem/README.md
+++ b/examples/providers/event-store-mem/README.md
@@ -5,24 +5,24 @@ To deploy copy target/event-store-mem-example.jar to providers directory. Altern
 
     KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.event-inmem --resources=target/event-store-mem-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-server-spi"
 
-Then registering the provider by editing keycloak-server.json and adding the module to the providers field:
+Then registering the provider by editing `standalone/configuration/standalone.xml` and adding the module to the providers element:
 
-    "providers": [
-        ....
-        "module:org.keycloak.examples.event-inmem"
-    ],
+    <providers>
+        ...
+        <provider>module:org.keycloak.examples.event-inmem</provider>
+    </providers>
 
-Then edit standalone/configuration/keycloak-server.json, change:
+Then edit `standalone/configuration/standalone.xml`, change:
 
-   "eventsStore": {
-     "provider": "jpa"
-   }
+    <spi name="eventsStore">
+        <default-provider>jpa</default-provider>
+    </spi>
 
 to:
 
-   "eventsStore": {
-     "provider": "in-mem"
-   }
+    <spi name="eventsStore">
+        <default-provider>in-mem</default-provider>
+    </spi>
 
 Then start (or restart)the server. Once started open the admin console, select your realm, then click on Events, 
 followed by config. Set the toggle for Enabled to ON. After this try to logout and login again then open the Events tab 
diff --git a/examples/providers/federation-provider/README.md b/examples/providers/federation-provider/README.md
index c8b4430..c90e791 100755
--- a/examples/providers/federation-provider/README.md
+++ b/examples/providers/federation-provider/README.md
@@ -6,13 +6,12 @@ key pairs.  To deploy, build this directory then take the jar and copy it to pro
 
     KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.userprops --resources=target/federation-properties-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-server-spi"
 
-Then registering the provider by editing keycloak-server.json and adding the module to the providers field:
-
-    "providers": [
-        ....
-        "module:org.keycloak.examples.userprops"
-    ],
+Then registering the provider by editing `standalone/configuration/standalone.xml` and adding the module to the providers element:
 
+    <providers>
+        ...
+        <provider>module:org.keycloak.examples.userprops</provider>
+    </providers>
   
 You will then have to restart the authentication server.
 
diff --git a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationFactory.java b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationFactory.java
index 2d5abc3..e9ec451 100755
--- a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationFactory.java
+++ b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationFactory.java
@@ -96,7 +96,7 @@ public abstract class BasePropertiesFederationFactory implements UserFederationP
     }
 
     /**
-     * You can import additional plugin configuration from keycloak-server.json here.
+     * You can import additional plugin configuration from standalone.xml here.
      *
      * @param config
      */
diff --git a/examples/providers/rest/README.md b/examples/providers/rest/README.md
index 5124f88..5ee9327 100644
--- a/examples/providers/rest/README.md
+++ b/examples/providers/rest/README.md
@@ -5,12 +5,12 @@ To deploy copy target/hello-rest-example.jar to providers directory. Alternative
 
     $KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.hello-rest-example --resources=target/hello-rest-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-server-spi,javax.ws.rs.api"
 
-Then registering the provider by editing keycloak-server.json and adding the module to the providers field:
+Then registering the provider by editing `standalone/configuration/standalone.xml` and adding the module to the providers element:
 
-    "providers": [
-        ....
-        "module:org.keycloak.examples.hello-rest-example"
-    ],
+    <providers>
+        ...
+        <provider>module:org.keycloak.examples.hello-rest-example</provider>
+    </providers>
 
 Then start (or restart) the server. Once started open http://localhost:8080/realms/master/hello and you should see the message _Hello master_.
 You can also invoke the endpoint for other realms by replacing `master` with the realm name in the above url.
\ No newline at end of file
diff --git a/examples/themes/README.md b/examples/themes/README.md
index ea160bc..5089ca1 100644
--- a/examples/themes/README.md
+++ b/examples/themes/README.md
@@ -17,14 +17,14 @@ Alternatively you can deploy as modules. This can be done by first running:
     mvn clean install
     $KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.example.themes --resources=target/keycloak-example-themes.jar"
 
-Then open $KEYCLOAK_HOME/standalone/configuration/keycloak-server.json and register the theme module by adding:
-    
-    "theme": {
-        "module": {
-            "modules": [ "org.keycloak.example.themes" ]
-        }
-    }
+Then open `standalone/configuration/standalone.xml` and register the theme module by adding:
 
+    <theme>
+        ...
+        <modules>
+            <module>org.keycloak.example.themes</module>
+        </modules>
+    </theme>
 
 Address Theme
 -------------------
@@ -45,11 +45,11 @@ Change Logo Theme
 
 To enable the theme open the admin console, select your realm, click on `Theme`. In the dropdowns for `Login Theme`, `Account Theme` and `Admin Console Theme` select `logo-example`. Click `Save` and login to the realm to see the new theme in action.
 
-To change the theme for the welcome pages open `standalone/configuration/keycloak-server.json` find the config for `theme` and add 'welcomeTheme':
+To change the theme for the welcome pages open `standalone/configuration/standalone.xml` find the config for `theme` and add 'welcomeTheme':
 
-    "theme": {
+    <theme>
         ...
-        "welcomeTheme": "logo-example"
-    },
+        <welcomeTheme>logo-example</welcomeTheme>
+    </theme>
 
 One thing to note is that to change the admin console for the master admin console (`/auth/admin`) you need to change the theme for the master realm. Changing the admin console theme for any other realms will only change the admin console for that specific realm (for example `/auth/admin/myrealm/console`).
diff --git a/federation/sssd/pom.xml b/federation/sssd/pom.xml
index 7d109e8..d3e3afb 100644
--- a/federation/sssd/pom.xml
+++ b/federation/sssd/pom.xml
@@ -23,6 +23,20 @@
                     <target>${maven.compiler.target}</target>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>2.3</version>
+                <executions>
+                    <!-- Run shade goal on package phase -->
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 
diff --git a/federation/sssd/src/main/java/cx/ath/matthew/LibraryLoader.java b/federation/sssd/src/main/java/cx/ath/matthew/LibraryLoader.java
index ffdf02d..4088d46 100644
--- a/federation/sssd/src/main/java/cx/ath/matthew/LibraryLoader.java
+++ b/federation/sssd/src/main/java/cx/ath/matthew/LibraryLoader.java
@@ -16,22 +16,17 @@
  */
 package cx.ath.matthew;
 
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
 /**
  * @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>.
  */
 public class LibraryLoader {
 
-    private static final Logger LOGGER = Logger.getLogger(LibraryLoader.class.getSimpleName());
-
     private static final String[] PATHS = {"/usr/lib/", "/usr/lib64/", "/usr/local/lib/", "/opt/local/lib/"};
     private static final String LIBRARY_NAME = "libunix_dbus_java";
     private static final String VERSION = "0.0.8";
     private static boolean loadSucceeded;
 
-    public static void load() {
+    public static LibraryLoader load() {
         for (String path : PATHS) {
             try {
                 System.load(String.format("%s/%s.so.%s", path, LIBRARY_NAME, VERSION));
@@ -40,10 +35,12 @@ public class LibraryLoader {
             } catch (UnsatisfiedLinkError e) {
                 loadSucceeded = false;
             }
-
         }
 
-        if (!loadSucceeded) LOGGER.log(Level.WARNING, "libunix_dbus_java not found\n" +
-                "Please, make sure you have the package libunix-dbus-java installed.");
+        return new LibraryLoader();
+    }
+
+    public boolean succeed() {
+        return loadSucceeded;
     }
 }
diff --git a/federation/sssd/src/main/java/org/freedesktop/DBus.java b/federation/sssd/src/main/java/org/freedesktop/DBus.java
index 1aa180a..b7a1687 100644
--- a/federation/sssd/src/main/java/org/freedesktop/DBus.java
+++ b/federation/sssd/src/main/java/org/freedesktop/DBus.java
@@ -30,18 +30,22 @@ import java.util.List;
 import java.util.Map;
 
 public interface DBus extends DBusInterface {
-    public static final int DBUS_NAME_FLAG_ALLOW_REPLACEMENT = 0x01;
-    public static final int DBUS_NAME_FLAG_REPLACE_EXISTING = 0x02;
-    public static final int DBUS_NAME_FLAG_DO_NOT_QUEUE = 0x04;
-    public static final int DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER = 1;
-    public static final int DBUS_REQUEST_NAME_REPLY_IN_QUEUE = 2;
-    public static final int DBUS_REQUEST_NAME_REPLY_EXISTS = 3;
-    public static final int DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER = 4;
-    public static final int DBUS_RELEASE_NAME_REPLY_RELEASED = 1;
-    public static final int DBUS_RELEASE_NAME_REPLY_NON_EXISTANT = 2;
-    public static final int DBUS_RELEASE_NAME_REPLY_NOT_OWNER = 3;
-    public static final int DBUS_START_REPLY_SUCCESS = 1;
-    public static final int DBUS_START_REPLY_ALREADY_RUNNING = 2;
+
+    String BUSNAME = "org.freedesktop.DBus";
+    String OBJECTPATH = "/org/freedesktop/DBus";
+
+    int DBUS_NAME_FLAG_ALLOW_REPLACEMENT = 0x01;
+    int DBUS_NAME_FLAG_REPLACE_EXISTING = 0x02;
+    int DBUS_NAME_FLAG_DO_NOT_QUEUE = 0x04;
+    int DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER = 1;
+    int DBUS_REQUEST_NAME_REPLY_IN_QUEUE = 2;
+    int DBUS_REQUEST_NAME_REPLY_EXISTS = 3;
+    int DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER = 4;
+    int DBUS_RELEASEME_REPLY_RELEASED = 1;
+    int DBUS_RELEASE_NAME_REPLY_NON_EXISTANT = 2;
+    int DBUS_RELEASE_NAME_REPLY_NOT_OWNER = 3;
+    int DBUS_START_REPLY_SUCCESS = 1;
+    int DBUS_START_REPLY_ALREADY_RUNNING = 2;
 
     /**
      * All DBus Applications should respond to the Ping method on this interface
@@ -527,4 +531,4 @@ public interface DBus extends DBusInterface {
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/federation/sssd/src/main/java/org/freedesktop/sssd/infopipe/InfoPipe.java b/federation/sssd/src/main/java/org/freedesktop/sssd/infopipe/InfoPipe.java
index 8791170..6152d26 100644
--- a/federation/sssd/src/main/java/org/freedesktop/sssd/infopipe/InfoPipe.java
+++ b/federation/sssd/src/main/java/org/freedesktop/sssd/infopipe/InfoPipe.java
@@ -32,6 +32,8 @@ import java.util.Map;
 public interface InfoPipe extends DBusInterface {
 
     String OBJECTPATH = "/org/freedesktop/sssd/infopipe";
+    String BUSNAME = "org.freedesktop.sssd.infopipe";
+
 
     @DBusMemberName("GetUserAttr")
     Map<String, Variant> getUserAttributes(String user, List<String> attr);
@@ -39,4 +41,4 @@ public interface InfoPipe extends DBusInterface {
     @DBusMemberName("GetUserGroups")
     List<String> getUserGroups(String user);
 
-}
+}
\ No newline at end of file
diff --git a/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java b/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java
index a5bb57a..065eb98 100644
--- a/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java
+++ b/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.federation.sssd.api;
 
+import cx.ath.matthew.LibraryLoader;
+import org.freedesktop.DBus;
 import org.freedesktop.dbus.DBusConnection;
 import org.freedesktop.dbus.Variant;
 import org.freedesktop.dbus.exceptions.DBusException;
@@ -35,8 +37,6 @@ import java.util.Vector;
  */
 public class Sssd {
 
-    public static final String BUSNAME = "org.freedesktop.sssd.infopipe";
-
     public static User user() {
         return SingletonHolder.USER_OBJECT;
     }
@@ -45,6 +45,7 @@ public class Sssd {
         return SingletonHolder.INFOPIPE_OBJECT;
     }
 
+
     public static void disconnect() {
         SingletonHolder.DBUS_CONNECTION.disconnect();
     }
@@ -67,10 +68,10 @@ public class Sssd {
         static {
             try {
                 DBUS_CONNECTION = DBusConnection.getConnection(DBusConnection.SYSTEM);
-                INFOPIPE_OBJECT = DBUS_CONNECTION.getRemoteObject(BUSNAME, InfoPipe.OBJECTPATH, InfoPipe.class);
-                USER_OBJECT = DBUS_CONNECTION.getRemoteObject(BUSNAME, User.OBJECTPATH, User.class);
+                INFOPIPE_OBJECT = DBUS_CONNECTION.getRemoteObject(InfoPipe.BUSNAME, InfoPipe.OBJECTPATH, InfoPipe.class);
+                USER_OBJECT = DBUS_CONNECTION.getRemoteObject(InfoPipe.BUSNAME, User.OBJECTPATH, User.class);
             } catch (DBusException e) {
-                e.printStackTrace();
+                logger.error("Failed to obtain D-Bus connection", e);
             }
         }
     }
@@ -108,4 +109,26 @@ public class Sssd {
         }
         return userGroups;
     }
+
+    public static boolean isAvailable(){
+        boolean sssdAvailable = false;
+        try {
+            if (LibraryLoader.load().succeed()) {
+                DBusConnection connection = DBusConnection.getConnection(DBusConnection.SYSTEM);
+                DBus dbus = connection.getRemoteObject(DBus.BUSNAME, DBus.OBJECTPATH, DBus.class);
+                sssdAvailable = Arrays.asList(dbus.ListNames()).contains(InfoPipe.BUSNAME);
+                if (!sssdAvailable) {
+                    logger.debugv("SSSD is not available in your system. Federation provider will be disabled.");
+                } else {
+                    sssdAvailable = true;
+                }
+                connection.disconnect();
+            } else {
+                logger.debugv("libunix_dbus_java not found. Federation provider will be disabled.");
+            }
+        } catch (DBusException e) {
+            logger.error("Failed to check the status of SSSD", e);
+        }
+        return sssdAvailable;
+    }
 }
diff --git a/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java b/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java
index 6a287a7..3140e9e 100755
--- a/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java
+++ b/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java
@@ -19,6 +19,7 @@ package org.keycloak.federation.sssd;
 
 import org.jboss.logging.Logger;
 import org.keycloak.Config;
+import org.keycloak.federation.sssd.api.Sssd;
 import org.keycloak.federation.sssd.impl.PAMAuthenticator;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
@@ -26,6 +27,7 @@ import org.keycloak.models.UserFederationProvider;
 import org.keycloak.models.UserFederationProviderFactory;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.UserFederationSyncResult;
+import org.keycloak.provider.EnvironmentDependentProviderFactory;
 
 import java.util.Date;
 import java.util.HashSet;
@@ -35,7 +37,7 @@ import java.util.Set;
  * @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
  * @version $Revision: 1 $
  */
-public class SSSDFederationProviderFactory implements UserFederationProviderFactory {
+public class SSSDFederationProviderFactory implements UserFederationProviderFactory, EnvironmentDependentProviderFactory {
 
     private static final String PROVIDER_NAME = "sssd";
     private static final Logger logger = Logger.getLogger(SSSDFederationProvider.class);
@@ -99,4 +101,8 @@ public class SSSDFederationProviderFactory implements UserFederationProviderFact
         return new PAMAuthenticator(username, factors);
     }
 
-}
+    @Override
+    public boolean isSupported() {
+        return Sssd.isAvailable();
+    }
+}
\ No newline at end of file
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcesResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcesResource.java
index 1aaaa23..07438d0 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcesResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcesResource.java
@@ -25,6 +25,7 @@ import javax.ws.rs.POST;
 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.MediaType;
 import javax.ws.rs.core.Response;
 import java.util.List;
@@ -45,5 +46,16 @@ public interface ResourcesResource {
     @GET
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
+    List<ResourceRepresentation> find(@QueryParam("name") String name,
+                  @QueryParam("uri") String uri,
+                  @QueryParam("owner") String owner,
+                  @QueryParam("type") String type,
+                  @QueryParam("scope") String scope,
+                  @QueryParam("first") Integer firstResult,
+                  @QueryParam("max") Integer maxResult);
+
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
     List<ResourceRepresentation> resources();
 }
diff --git a/misc/HackingOnKeycloak.md b/misc/HackingOnKeycloak.md
index 590a301..902d1ed 100644
--- a/misc/HackingOnKeycloak.md
+++ b/misc/HackingOnKeycloak.md
@@ -59,5 +59,6 @@ Here's a quick check list for a good pull request (PR):
 * A JIRA associated with your PR (include the JIRA issue number in commit comment)
 * All tests in testsuite pass
 * Do a rebase on upstream master
+* We only accept contributions to the master branch. The exception to this is if the fix is for the latest CR release and Final has not yet been released, in which case you can send the PR to both the corresponding branch and the master branch.
 
-Once you're happy with your changes go to GitHub and create a PR.
+Once you're happy with your changes go to GitHub and create a PR to the master branch.
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java
index 7eab0eb..e85078e 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java
@@ -152,6 +152,8 @@ public class CachedRealm extends AbstractRevisioned {
     protected MultivaluedHashMap<String, IdentityProviderMapperModel> identityProviderMappers = new MultivaluedHashMap<>();
     protected Set<IdentityProviderMapperModel> identityProviderMapperSet;
 
+    protected Map<String, String> attributes;
+
     public CachedRealm(Long revision, RealmModel model) {
         super(revision, model.getId());
         name = model.getName();
@@ -231,10 +233,10 @@ public class CachedRealm extends AbstractRevisioned {
         eventsExpiration = model.getEventsExpiration();
         eventsListeners = model.getEventsListeners();
         enabledEventTypes = model.getEnabledEventTypes();
-        
+
         adminEventsEnabled = model.isAdminEventsEnabled();
         adminEventsDetailsEnabled = model.isAdminEventsDetailsEnabled();
-        
+
         defaultRoles = model.getDefaultRoles();
         ClientModel masterAdminClient = model.getMasterAdminClient();
         this.masterAdminClient = (masterAdminClient != null) ? masterAdminClient.getId() : null;
@@ -285,6 +287,11 @@ public class CachedRealm extends AbstractRevisioned {
             components.put(component.getId(), component);
         }
 
+        try {
+            attributes = model.getAttributes();
+        } catch (UnsupportedOperationException ex) {
+        }
+
     }
 
     protected void cacheClientTemplates(RealmModel model) {
@@ -475,7 +482,7 @@ public class CachedRealm extends AbstractRevisioned {
     public Set<String> getEventsListeners() {
         return eventsListeners;
     }
-    
+
     public Set<String> getEnabledEventTypes() {
         return enabledEventTypes;
     }
@@ -619,4 +626,28 @@ public class CachedRealm extends AbstractRevisioned {
     public Map<String, ComponentModel> getComponents() {
         return components;
     }
+
+    public String getAttribute(String name) {
+        return attributes != null ? attributes.get(name) : null;
+    }
+
+    public Integer getAttribute(String name, Integer defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Integer.parseInt(v) : defaultValue;
+    }
+
+    public Long getAttribute(String name, Long defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Long.parseLong(v) : defaultValue;
+    }
+
+    public Boolean getAttribute(String name, Boolean defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Boolean.parseBoolean(v) : defaultValue;
+    }
+
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUser.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUser.java
index 2eec04a..bc92c48 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUser.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUser.java
@@ -45,7 +45,6 @@ public class CachedUser extends AbstractExtendableRevisioned implements InRealm 
     private String email;
     private boolean emailVerified;
     private boolean enabled;
-    private boolean totp;
     private String federationLink;
     private String serviceAccountClientLink;
     private MultivaluedHashMap<String, String> attributes = new MultivaluedHashMap<>();
@@ -66,7 +65,6 @@ public class CachedUser extends AbstractExtendableRevisioned implements InRealm 
         this.email = user.getEmail();
         this.emailVerified = user.isEmailVerified();
         this.enabled = user.isEnabled();
-        this.totp = user.isOtpEnabled();
         this.federationLink = user.getFederationLink();
         this.serviceAccountClientLink = user.getServiceAccountClientLink();
         this.requiredActions.addAll(user.getRequiredActions());
@@ -113,10 +111,6 @@ public class CachedUser extends AbstractExtendableRevisioned implements InRealm 
         return enabled;
     }
 
-    public boolean isTotp() {
-        return totp;
-    }
-
     public MultivaluedHashMap<String, String> getAttributes() {
         return attributes;
     }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
index 8256aa2..6950ed8 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
@@ -1465,4 +1465,64 @@ public class RealmAdapter implements RealmModel {
         if (isUpdated()) return updated.getComponent(id);
         return cached.getComponents().get(id);
     }
+
+    public void setAttribute(String name, String value) {
+        getDelegateForUpdate();
+        updated.setAttribute(name, value);
+    }
+
+    @Override
+    public void setAttribute(String name, Boolean value) {
+        getDelegateForUpdate();
+        updated.setAttribute(name, value);
+    }
+
+    @Override
+    public void setAttribute(String name, Integer value) {
+        getDelegateForUpdate();
+        updated.setAttribute(name, value);
+    }
+
+    @Override
+    public void setAttribute(String name, Long value) {
+        getDelegateForUpdate();
+        updated.setAttribute(name, value);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        getDelegateForUpdate();
+        updated.removeAttribute(name);
+    }
+
+    @Override
+    public String getAttribute(String name) {
+        if (isUpdated()) return updated.getAttribute(name);
+        return cached.getAttribute(name);
+    }
+
+    @Override
+    public Integer getAttribute(String name, Integer defaultValue) {
+        if (isUpdated()) return updated.getAttribute(name, defaultValue);
+        return cached.getAttribute(name, defaultValue);
+    }
+
+    @Override
+    public Long getAttribute(String name, Long defaultValue) {
+        if (isUpdated()) return updated.getAttribute(name, defaultValue);
+        return cached.getAttribute(name, defaultValue);
+    }
+
+    @Override
+    public Boolean getAttribute(String name, Boolean defaultValue) {
+        if (isUpdated()) return updated.getAttribute(name, defaultValue);
+        return cached.getAttribute(name, defaultValue);
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        if (isUpdated()) return updated.getAttributes();
+        return cached.getAttributes();
+    }
+
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserAdapter.java
index 0ef7689..6483f2a 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserAdapter.java
@@ -120,12 +120,6 @@ public class UserAdapter implements CachedUserModel {
     }
 
     @Override
-    public boolean isOtpEnabled() {
-        if (updated != null) return updated.isOtpEnabled();
-        return cached.isTotp();
-    }
-
-    @Override
     public void setEnabled(boolean enabled) {
         getDelegateForUpdate();
         updated.setEnabled(enabled);
@@ -248,12 +242,6 @@ public class UserAdapter implements CachedUserModel {
     }
 
     @Override
-    public void setOtpEnabled(boolean totp) {
-        getDelegateForUpdate();
-        updated.setOtpEnabled(totp);
-    }
-
-    @Override
     public String getFederationLink() {
         if (updated != null) return updated.getFederationLink();
         return cached.getFederationLink();
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
index d110a17..2af7673 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
@@ -76,8 +76,6 @@ public class UserEntity {
     protected String email;
     @Column(name = "ENABLED")
     protected boolean enabled;
-    @Column(name = "TOTP")
-    protected boolean totp;
     @Column(name = "EMAIL_VERIFIED")
     protected boolean emailVerified;
 
@@ -168,14 +166,6 @@ public class UserEntity {
         this.emailConstraint = emailConstraint;
     }
 
-    public boolean isTotp() {
-        return totp;
-    }
-
-    public void setTotp(boolean totp) {
-        this.totp = totp;
-    }
-
     public boolean isEmailVerified() {
         return emailVerified;
     }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 46df41a..a5747c6 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -182,6 +182,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
         em.flush();
     }
 
+    @Override
     public void setAttribute(String name, String value) {
         for (RealmAttributeEntity attr : realm.getAttributes()) {
             if (attr.getName().equals(name)) {
@@ -197,18 +198,22 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
         realm.getAttributes().add(attr);
     }
 
+    @Override
     public void setAttribute(String name, Boolean value) {
         setAttribute(name, value.toString());
     }
 
+    @Override
     public void setAttribute(String name, Integer value) {
         setAttribute(name, value.toString());
     }
 
+    @Override
     public void setAttribute(String name, Long value) {
         setAttribute(name, value.toString());
     }
 
+    @Override
     public void removeAttribute(String name) {
         Iterator<RealmAttributeEntity> it = realm.getAttributes().iterator();
         while (it.hasNext()) {
@@ -220,6 +225,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
         }
     }
 
+    @Override
     public String getAttribute(String name) {
         for (RealmAttributeEntity attr : realm.getAttributes()) {
             if (attr.getName().equals(name)) {
@@ -229,24 +235,28 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
         return null;
     }
 
+    @Override
     public Integer getAttribute(String name, Integer defaultValue) {
         String v = getAttribute(name);
         return v != null ? Integer.parseInt(v) : defaultValue;
 
     }
 
+    @Override
     public Long getAttribute(String name, Long defaultValue) {
         String v = getAttribute(name);
         return v != null ? Long.parseLong(v) : defaultValue;
 
     }
 
+    @Override
     public Boolean getAttribute(String name, Boolean defaultValue) {
         String v = getAttribute(name);
         return v != null ? Boolean.parseBoolean(v) : defaultValue;
 
     }
 
+    @Override
     public Map<String, String> getAttributes() {
         // should always return a copy
         Map<String, String> result = new HashMap<String, String>();
@@ -255,6 +265,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
         }
         return result;
     }
+
     @Override
     public boolean isBruteForceProtected() {
         return getAttribute("bruteForceProtected", false);
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
index 5d4bc91..7e01746 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
@@ -114,11 +114,6 @@ public class UserAdapter implements UserModel, JpaModel<UserEntity> {
     }
 
     @Override
-    public boolean isOtpEnabled() {
-        return user.isTotp();
-    }
-
-    @Override
     public void setEnabled(boolean enabled) {
         user.setEnabled(enabled);
     }
@@ -311,11 +306,6 @@ public class UserAdapter implements UserModel, JpaModel<UserEntity> {
     }
 
     @Override
-    public void setOtpEnabled(boolean totp) {
-        user.setTotp(totp);
-    }
-
-    @Override
     public Set<GroupModel> getGroups() {
         // we query ids only as the group  might be cached and following the @ManyToOne will result in a load
         // even if we're getting just the id.
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.2.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.2.0.xml
index a9b6078..adc49fb 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.2.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.2.0.xml
@@ -18,13 +18,12 @@
 
 <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
 
-    <changeSet author="thomas.darimont@gmail.com" id="2.2.0">
+    <changeSet author="bburke@redhat.com" id="2.2.0">
+
         <addColumn tableName="ADMIN_EVENT_ENTITY">
             <column name="RESOURCE_TYPE" type="VARCHAR(64)"></column>
         </addColumn>
-    </changeSet>
 
-    <changeSet author="bburke@redhat.com" id="2.2.0">
         <createTable tableName="CREDENTIAL_ATTRIBUTE">
             <column name="ID" type="VARCHAR(36)">
                 <constraints nullable="false"/>
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml
index d6041e0..6a3f9fe 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml
@@ -31,9 +31,11 @@
         </createTable>
          <addPrimaryKey columnNames="ID" constraintName="CONSTR_FEDERATED_USER" tableName="FEDERATED_USER"/>
 
+         <dropColumn tableName="USER_ENTITY" columnName="TOTP" />
 
 
-    </changeSet>
+
+     </changeSet>
 
 
 </databaseChangeLog>
\ No newline at end of file
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index e7dc5f6..86a9001 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -1230,7 +1230,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
         }
         updateRealm();
     }
-    
+
     @Override
     public boolean isAdminEventsEnabled() {
         return realm.isAdminEventsEnabled();
@@ -1240,7 +1240,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     public void setAdminEventsEnabled(boolean enabled) {
         realm.setAdminEventsEnabled(enabled);
         updateRealm();
-        
+
     }
 
     @Override
@@ -1253,7 +1253,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
         realm.setAdminEventsDetailsEnabled(enabled);
         updateRealm();
     }
-    
+
     @Override
     public ClientModel getMasterAdminClient() {
         MongoClientEntity appData = getMongoStore().loadEntity(MongoClientEntity.class, realm.getMasterAdminClient(), invocationContext);
@@ -2181,4 +2181,62 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
         }
         return null;
     }
+
+    @Override
+    public void setAttribute(String name, String value) {
+        realm.getAttributes().put(name, value);
+        updateRealm();
+    }
+
+    @Override
+    public void setAttribute(String name, Boolean value) {
+        setAttribute(name, value.toString());
+    }
+
+    @Override
+    public void setAttribute(String name, Integer value) {
+        setAttribute(name, value.toString());
+    }
+
+    @Override
+    public void setAttribute(String name, Long value) {
+        setAttribute(name, value.toString());
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        realm.getAttributes().remove(name);
+        updateRealm();
+    }
+
+    @Override
+    public String getAttribute(String name) {
+        return realm.getAttributes().get(name);
+    }
+
+    @Override
+    public Integer getAttribute(String name, Integer defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Integer.parseInt(v) : defaultValue;
+    }
+
+    @Override
+    public Long getAttribute(String name, Long defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Long.parseLong(v) : defaultValue;
+    }
+
+    @Override
+    public Boolean getAttribute(String name, Boolean defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Boolean.parseBoolean(v) : defaultValue;
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        Map<String, String> attributes = new HashMap<>();
+        attributes.putAll(realm.getAttributes());
+        return attributes;
+    }
+
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
index caa1f71..f642ef1 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
@@ -243,17 +243,6 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
         getMongoStore().pullItemFromList(user, "requiredActions", actionName, invocationContext);
     }
 
-    @Override
-    public boolean isOtpEnabled() {
-        return user.isTotp();
-    }
-
-    @Override
-    public void setOtpEnabled(boolean totp) {
-        user.setTotp(totp);
-        updateUser();
-    }
-
     protected void updateUser() {
         super.updateMongoEntity();
     }

pom.xml 19(+13 -6)

diff --git a/pom.xml b/pom.xml
index a2de58f..da7a2ea 100755
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,7 @@
         <product.name-html>\u003Cdiv class="kc-logo-text"\u003E\u003Cspan\u003EKeycloak\u003C\u002Fspan\u003E\u003C\u002Fdiv\u003E</product.name-html>
         <product.version>${project.version}</product.version>
         <product.build-time>${timestamp}</product.build-time>
+        <product.default-profile>community</product.default-profile>
 
         <!-- WildFly -->
         <eap.version>7.0.0.Beta</eap.version>
@@ -1075,6 +1076,18 @@
             </dependency>
             <dependency>
                 <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-fuse-adapter-dist</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-fuse-adapter-dist</artifactId>
+                <version>${project.version}</version>
+                <type>tar.gz</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
                 <artifactId>keycloak-wildfly-adapter-dist</artifactId>
                 <version>${project.version}</version>
                 <type>zip</type>
@@ -1116,12 +1129,6 @@
             </dependency>
             <dependency>
                 <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-src-dist</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
                 <artifactId>keycloak-proxy-dist</artifactId>
                 <version>${project.version}</version>
                 <type>zip</type>

README.md 4(+2 -2)

diff --git a/README.md b/README.md
index 14addf7..570576c 100755
--- a/README.md
+++ b/README.md
@@ -52,7 +52,7 @@ To stop the server press `Ctrl + C`.
 
 Help and Documentation
 ----------------------
-* [Documentation](http://keycloak.jboss.org/docs) - User Guide, Admin REST API and Javadocs
+* [Documentation](http://www.keycloak.org/documentation.html) - User Guide, Admin REST API and Javadocs
 * [User Mailing List](https://lists.jboss.org/mailman/listinfo/keycloak-user) - Mailing list to ask for help and general questions about Keycloak
 * [JIRA](https://issues.jboss.org/projects/KEYCLOAK) - Issue tracker for bugs and feature requests
 
@@ -72,4 +72,4 @@ Contributing
 License
 -------
 
-* [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
\ No newline at end of file
+* [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
diff --git a/server-spi/src/main/java/org/keycloak/migration/MigrationModel.java b/server-spi/src/main/java/org/keycloak/migration/MigrationModel.java
index 59fcee8..a59508b 100755
--- a/server-spi/src/main/java/org/keycloak/migration/MigrationModel.java
+++ b/server-spi/src/main/java/org/keycloak/migration/MigrationModel.java
@@ -23,11 +23,6 @@ package org.keycloak.migration;
  * @version $Revision: 1 $
  */
 public interface MigrationModel {
-    /**
-     * Must have the form of major.minor.micro as the version is parsed and numbers are compared
-     */
-    String LATEST_VERSION = "2.3.0";
-
     String getStoredVersion();
     void setStoredVersion(String version);
 }
diff --git a/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java b/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java
index 6a2f448..e2b55e1 100755
--- a/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java
+++ b/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java
@@ -18,6 +18,7 @@
 package org.keycloak.migration;
 
 import org.jboss.logging.Logger;
+import org.keycloak.migration.migrators.MigrateTo1_2_0;
 import org.keycloak.migration.migrators.MigrateTo1_3_0;
 import org.keycloak.migration.migrators.MigrateTo1_4_0;
 import org.keycloak.migration.migrators.MigrateTo1_5_0;
@@ -28,7 +29,8 @@ import org.keycloak.migration.migrators.MigrateTo1_9_0;
 import org.keycloak.migration.migrators.MigrateTo1_9_2;
 import org.keycloak.migration.migrators.MigrateTo2_0_0;
 import org.keycloak.migration.migrators.MigrateTo2_1_0;
-import org.keycloak.migration.migrators.MigrationTo1_2_0_CR1;
+import org.keycloak.migration.migrators.MigrateTo2_2_0;
+import org.keycloak.migration.migrators.Migration;
 import org.keycloak.models.KeycloakSession;
 
 /**
@@ -38,82 +40,41 @@ import org.keycloak.models.KeycloakSession;
 public class MigrationModelManager {
     private static Logger logger = Logger.getLogger(MigrationModelManager.class);
 
+    private static final Migration[] migrations = {
+        new MigrateTo1_2_0(),
+        new MigrateTo1_3_0(),
+        new MigrateTo1_4_0(),
+        new MigrateTo1_5_0(),
+        new MigrateTo1_6_0(),
+        new MigrateTo1_7_0(),
+        new MigrateTo1_8_0(),
+        new MigrateTo1_9_0(),
+        new MigrateTo1_9_2(),
+        new MigrateTo2_0_0(),
+        new MigrateTo2_1_0(),
+        new MigrateTo2_2_0(),
+    };
+
     public static void migrate(KeycloakSession session) {
+        ModelVersion latest = migrations[migrations.length-1].getVersion();
         MigrationModel model = session.realms().getMigrationModel();
-        String storedVersion = model.getStoredVersion();
-        if (MigrationModel.LATEST_VERSION.equals(storedVersion)) return;
         ModelVersion stored = null;
-        if (storedVersion != null) {
-            stored = new ModelVersion(storedVersion);
-        }
-
-        if (stored == null || stored.lessThan(MigrationTo1_2_0_CR1.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.2.0.CR1 updates");
-            }
-            new MigrationTo1_2_0_CR1().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo1_3_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.3.0 updates");
-            }
-            new MigrateTo1_3_0().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo1_4_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.4.0 updates");
-            }
-            new MigrateTo1_4_0().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo1_5_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.5.0 updates");
-            }
-            new MigrateTo1_5_0().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo1_6_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.6.0 updates");
+        if (model.getStoredVersion() != null) {
+            stored = new ModelVersion(model.getStoredVersion());
+            if (latest.equals(stored)) {
+                return;
             }
-            new MigrateTo1_6_0().migrate(session);
         }
-        if (stored == null || stored.lessThan(MigrateTo1_7_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.7.0 updates");
-            }
-            new MigrateTo1_7_0().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo1_8_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.8.0 updates");
-            }
-            new MigrateTo1_8_0().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo1_9_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.9.0 updates");
-            }
-            new MigrateTo1_9_0().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo1_9_2.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.9.2 updates");
-            }
-            new MigrateTo1_9_2().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo2_0_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 2.0.0 updates");
-            }
-            new MigrateTo2_0_0().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo2_1_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 2.1.0 updates");
+
+        for (Migration m : migrations) {
+            if (stored == null || stored.lessThan(m.getVersion())) {
+                if (stored != null) {
+                    logger.debugf("Migrating older model to %s", m.getVersion());
+                }
+                m.migrate(session);
             }
-            new MigrateTo2_1_0().migrate(session);
         }
 
-        model.setStoredVersion(MigrationModel.LATEST_VERSION);
+        model.setStoredVersion(latest.toString());
     }
 }
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java
index 8d573c7..ee33714 100755
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java
@@ -37,9 +37,13 @@ import javax.naming.directory.SearchControls;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class MigrateTo1_3_0 {
+public class MigrateTo1_3_0 implements Migration {
+
     public static final ModelVersion VERSION = new ModelVersion("1.3.0");
 
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
 
     public void migrate(KeycloakSession session) {
         List<RealmModel> realms = session.realms().getRealms();
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
index 5fbab26..9f28f91 100755
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
@@ -34,9 +34,13 @@ import java.util.List;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class MigrateTo1_4_0 {
+public class MigrateTo1_4_0 implements Migration {
     public static final ModelVersion VERSION = new ModelVersion("1.4.0");
 
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+
     public void migrate(KeycloakSession session) {
         List<RealmModel> realms = session.realms().getRealms();
         for (RealmModel realm : realms) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java
index 1a7f83e..6969d5c 100755
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java
@@ -32,9 +32,13 @@ import java.util.List;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class MigrateTo1_5_0 {
+public class MigrateTo1_5_0 implements Migration {
     public static final ModelVersion VERSION = new ModelVersion("1.5.0");
 
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+
     public void migrate(KeycloakSession session) {
         List<RealmModel> realms = session.realms().getRealms();
         for (RealmModel realm : realms) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
index 17ddf1b..c3d9222 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
@@ -27,10 +27,14 @@ import org.keycloak.models.utils.KeycloakModelUtils;
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
-public class MigrateTo1_6_0 {
+public class MigrateTo1_6_0 implements Migration {
 
     public static final ModelVersion VERSION = new ModelVersion("1.6.0");
 
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+
     public void migrate(KeycloakSession session) {
         MigrationProvider provider = session.getProvider(MigrationProvider.class);
 
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java
index 47abe62..3d4a5d5 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java
@@ -31,10 +31,14 @@ import org.keycloak.models.utils.DefaultAuthenticationFlows;
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
-public class MigrateTo1_7_0 {
+public class MigrateTo1_7_0 implements Migration {
 
     public static final ModelVersion VERSION = new ModelVersion("1.7.0");
 
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+
     public void migrate(KeycloakSession session) {
         List<RealmModel> realms = session.realms().getRealms();
         for (RealmModel realm : realms) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java
index 94e0243..549cde9 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java
@@ -30,10 +30,14 @@ import org.keycloak.models.utils.KeycloakModelUtils;
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
-public class MigrateTo1_8_0 {
+public class MigrateTo1_8_0 implements Migration {
 
     public static final ModelVersion VERSION = new ModelVersion("1.8.0");
 
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+
     public void migrate(KeycloakSession session) {
         List<RealmModel> realms = session.realms().getRealms();
         for (RealmModel realm : realms) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_0.java
index fb24598..e91f126 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_0.java
@@ -33,10 +33,14 @@ import java.util.Map;
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
-public class MigrateTo1_9_0 {
+public class MigrateTo1_9_0 implements Migration {
 
     public static final ModelVersion VERSION = new ModelVersion("1.9.0");
 
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+
     public void migrate(KeycloakSession session) {
         RealmModel realm = session.realms().getRealm(Config.getAdminRealm());
         if (realm != null && realm.getDisplayNameHtml() != null && realm.getDisplayNameHtml().equals("<strong>Keycloak</strong>")) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
index 2473937..3a41058 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
@@ -25,10 +25,14 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
-public class MigrateTo1_9_2 {
+public class MigrateTo1_9_2 implements Migration {
 
     public static final ModelVersion VERSION = new ModelVersion("1.9.2");
 
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+
     public void migrate(KeycloakSession session) {
         for (RealmModel realm : session.realms().getRealms()) {
             if (realm.getBrowserSecurityHeaders() != null) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java
index 23368f3..d36a858 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java
@@ -23,10 +23,14 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
 
-public class MigrateTo2_0_0 {
+public class MigrateTo2_0_0 implements Migration {
 
     public static final ModelVersion VERSION = new ModelVersion("2.0.0");
 
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+
     public void migrate(KeycloakSession session) {
         for (RealmModel realm : session.realms().getRealms()) {
             migrateAuthorizationServices(realm);
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
index 9e7b931..995dafb 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
@@ -38,9 +38,13 @@ import java.util.stream.Collectors;
  *
  * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
  */
-public class MigrateTo2_1_0 {
+public class MigrateTo2_1_0 implements Migration {
     public static final ModelVersion VERSION = new ModelVersion("2.1.0");
 
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+
     public void migrate(KeycloakSession session) {
         for (RealmModel realm : session.realms().getRealms()) {
             migrateDefaultRequiredAction(realm);
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java
new file mode 100644
index 0000000..1dbcba4
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.migration.migrators;
+
+import org.jboss.logging.Logger;
+import org.keycloak.migration.ModelVersion;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.DefaultAuthenticationFlows;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MigrateTo2_2_0 implements Migration {
+    public static final ModelVersion VERSION = new ModelVersion("2.2.0");
+
+    private static final Logger LOG = Logger.getLogger(MigrateTo2_2_0.class);
+
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+
+    public void migrate(KeycloakSession session) {
+        for (RealmModel realm : session.realms().getRealms()) {
+            addIdentityProviderAuthenticator(realm);
+        }
+    }
+
+    private void addIdentityProviderAuthenticator(RealmModel realm) {
+        String defaultProvider = null;
+        for (IdentityProviderModel provider : realm.getIdentityProviders()) {
+            if (provider.isEnabled() && provider.isAuthenticateByDefault()) {
+                defaultProvider = provider.getAlias();
+                break;
+            }
+        }
+
+        DefaultAuthenticationFlows.addIdentityProviderAuthenticator(realm, defaultProvider);
+    }
+
+}
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/Migration.java b/server-spi/src/main/java/org/keycloak/migration/migrators/Migration.java
new file mode 100644
index 0000000..e37dad2
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/Migration.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.migration.migrators;
+
+import org.keycloak.migration.ModelVersion;
+import org.keycloak.models.KeycloakSession;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface Migration {
+
+    void migrate(KeycloakSession session);
+
+    ModelVersion getVersion();
+
+}
diff --git a/server-spi/src/main/java/org/keycloak/migration/ModelVersion.java b/server-spi/src/main/java/org/keycloak/migration/ModelVersion.java
index 383edd5..8845879 100755
--- a/server-spi/src/main/java/org/keycloak/migration/ModelVersion.java
+++ b/server-spi/src/main/java/org/keycloak/migration/ModelVersion.java
@@ -98,4 +98,19 @@ public class ModelVersion {
         if (comp < 0) return true;
         return false;
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ModelVersion)) {
+            return false;
+        }
+
+        ModelVersion v = (ModelVersion) obj;
+        return v.getMajor() == major && v.getMinor() == minor && v.getMicro() != micro;
+    }
+
+    @Override
+    public String toString() {
+        return major + "." + minor + "." + micro;
+    }
 }
diff --git a/server-spi/src/main/java/org/keycloak/models/Constants.java b/server-spi/src/main/java/org/keycloak/models/Constants.java
index 42982f6..edc9567 100755
--- a/server-spi/src/main/java/org/keycloak/models/Constants.java
+++ b/server-spi/src/main/java/org/keycloak/models/Constants.java
@@ -51,4 +51,7 @@ public interface Constants {
 
     // Prefix for user attributes used in various "context"data maps
     String USER_ATTRIBUTES_PREFIX = "user.attributes.";
+
+    // Indication to admin-rest-endpoint that realm keys should be re-generated
+    String GENERATE = "GENERATE";
 }
diff --git a/server-spi/src/main/java/org/keycloak/models/entities/RealmEntity.java b/server-spi/src/main/java/org/keycloak/models/entities/RealmEntity.java
index c5a6ecf..cccdacd 100755
--- a/server-spi/src/main/java/org/keycloak/models/entities/RealmEntity.java
+++ b/server-spi/src/main/java/org/keycloak/models/entities/RealmEntity.java
@@ -94,6 +94,8 @@ public class RealmEntity extends AbstractIdentifiableEntity {
     private Map<String, String> smtpConfig = new HashMap<String, String>();
     private Map<String, String> socialConfig = new HashMap<String, String>();
 
+    private Map<String, String> attributes = new HashMap<>();
+
     private boolean eventsEnabled;
     private long eventsExpiration;
     private List<String> eventsListeners = new ArrayList<String>();
@@ -692,6 +694,13 @@ public class RealmEntity extends AbstractIdentifiableEntity {
     public void setComponentEntities(List<ComponentEntity> componentEntities) {
         this.componentEntities = componentEntities;
     }
-}
 
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(Map<String, String> attributes) {
+        this.attributes = attributes;
+    }
 
+}
diff --git a/server-spi/src/main/java/org/keycloak/models/entities/UserEntity.java b/server-spi/src/main/java/org/keycloak/models/entities/UserEntity.java
index 0475715..95bdc0d 100755
--- a/server-spi/src/main/java/org/keycloak/models/entities/UserEntity.java
+++ b/server-spi/src/main/java/org/keycloak/models/entities/UserEntity.java
@@ -32,7 +32,6 @@ public class UserEntity extends AbstractIdentifiableEntity {
     private String lastName;
     private String email;
     private boolean emailVerified;
-    private boolean totp;
     private boolean enabled;
 
     private String realmId;
@@ -96,14 +95,6 @@ public class UserEntity extends AbstractIdentifiableEntity {
         this.emailVerified = emailVerified;
     }
 
-    public boolean isTotp() {
-        return totp;
-    }
-
-    public void setTotp(boolean totp) {
-        this.totp = totp;
-    }
-
     public boolean isEnabled() {
         return enabled;
     }
diff --git a/server-spi/src/main/java/org/keycloak/models/IdentityProviderModel.java b/server-spi/src/main/java/org/keycloak/models/IdentityProviderModel.java
index 82e373f..2425c7d 100755
--- a/server-spi/src/main/java/org/keycloak/models/IdentityProviderModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/IdentityProviderModel.java
@@ -120,10 +120,12 @@ public class IdentityProviderModel implements Serializable {
         this.storeToken = storeToken;
     }
 
+    @Deprecated
     public boolean isAuthenticateByDefault() {
         return authenticateByDefault;
     }
 
+    @Deprecated
     public void setAuthenticateByDefault(boolean authenticateByDefault) {
         this.authenticateByDefault = authenticateByDefault;
     }
diff --git a/server-spi/src/main/java/org/keycloak/models/RealmModel.java b/server-spi/src/main/java/org/keycloak/models/RealmModel.java
index 61dc9c1..7ff7813 100755
--- a/server-spi/src/main/java/org/keycloak/models/RealmModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/RealmModel.java
@@ -110,6 +110,17 @@ public interface RealmModel extends RoleContainerModel {
 
     void setEditUsernameAllowed(boolean editUsernameAllowed);
 
+    void setAttribute(String name, String value);
+    void setAttribute(String name, Boolean value);
+    void setAttribute(String name, Integer value);
+    void setAttribute(String name, Long value);
+    void removeAttribute(String name);
+    String getAttribute(String name);
+    Integer getAttribute(String name, Integer defaultValue);
+    Long getAttribute(String name, Long defaultValue);
+    Boolean getAttribute(String name, Boolean defaultValue);
+    Map<String, String> getAttributes();
+
     //--- brute force settings
     boolean isBruteForceProtected();
     void setBruteForceProtected(boolean value);
diff --git a/server-spi/src/main/java/org/keycloak/models/UserModel.java b/server-spi/src/main/java/org/keycloak/models/UserModel.java
index c756330..6bc80c3 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserModel.java
@@ -54,8 +54,6 @@ public interface UserModel extends RoleMapperModel {
 
     boolean isEnabled();
 
-    boolean isOtpEnabled();
-
     void setEnabled(boolean enabled);
 
     /**
@@ -110,8 +108,6 @@ public interface UserModel extends RoleMapperModel {
 
     void setEmailVerified(boolean verified);
 
-    void setOtpEnabled(boolean totp);
-
     Set<GroupModel> getGroups();
     void joinGroup(GroupModel group);
     void leaveGroup(GroupModel group);
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java b/server-spi/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
index 7b2c61b..a738d05 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
@@ -276,6 +276,7 @@ public class DefaultAuthenticationFlows {
         execution.setAuthenticatorFlow(false);
         realm.addAuthenticatorExecution(execution);
 
+        addIdentityProviderAuthenticator(realm, null);
 
         AuthenticationFlowModel forms = new AuthenticationFlowModel();
         forms.setTopLevel(false);
@@ -317,6 +318,45 @@ public class DefaultAuthenticationFlows {
         realm.addAuthenticatorExecution(execution);
     }
 
+    public static void addIdentityProviderAuthenticator(RealmModel realm, String defaultProvider) {
+        String browserFlowId = null;
+        for (AuthenticationFlowModel f : realm.getAuthenticationFlows()) {
+            if (f.getAlias().equals(DefaultAuthenticationFlows.BROWSER_FLOW)) {
+                browserFlowId = f.getId();
+                break;
+            }
+        }
+
+        if (browserFlowId != null) {
+            for (AuthenticationExecutionModel e : realm.getAuthenticationExecutions(browserFlowId)) {
+                if ("identity-provider-redirector".equals(e.getAuthenticator())) {
+                    return;
+                }
+            }
+
+            AuthenticationExecutionModel execution;
+            execution = new AuthenticationExecutionModel();
+            execution.setParentFlow(browserFlowId);
+            execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
+            execution.setAuthenticator("identity-provider-redirector");
+            execution.setPriority(25);
+            execution.setAuthenticatorFlow(false);
+
+            if (defaultProvider != null) {
+                AuthenticatorConfigModel configModel = new AuthenticatorConfigModel();
+
+                Map<String, String> config = new HashMap<>();
+                config.put("defaultProvider", defaultProvider);
+                configModel.setConfig(config);
+                configModel = realm.addAuthenticatorConfig(configModel);
+
+                execution.setAuthenticatorConfig(configModel.getId());
+            }
+
+            realm.addAuthenticatorExecution(execution);
+        }
+    }
+
     public static void clientAuthFlow(RealmModel realm) {
         AuthenticationFlowModel clients = new AuthenticationFlowModel();
         clients.setAlias(CLIENT_AUTHENTICATION_FLOW);
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index e2d4799..659c116 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -26,6 +26,7 @@ import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.authorization.store.ResourceStore;
 import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.component.ComponentModel;
+import org.keycloak.credential.CredentialModel;
 import org.keycloak.events.Event;
 import org.keycloak.events.admin.AdminEvent;
 import org.keycloak.events.admin.AuthDetails;
@@ -174,7 +175,7 @@ public class ModelToRepresentation {
     }
 
 
-    public static UserRepresentation toRepresentation(UserModel user) {
+    public static UserRepresentation toRepresentation(KeycloakSession session, RealmModel realm, UserModel user) {
         UserRepresentation rep = new UserRepresentation();
         rep.setId(user.getId());
         rep.setUsername(user.getUsername());
@@ -184,7 +185,7 @@ public class ModelToRepresentation {
         rep.setEmail(user.getEmail());
         rep.setEnabled(user.isEnabled());
         rep.setEmailVerified(user.isEmailVerified());
-        rep.setTotp(user.isOtpEnabled());
+        rep.setTotp(session.userCredentialManager().isConfiguredFor(realm, user, CredentialModel.OTP));
         rep.setFederationLink(user.getFederationLink());
 
         List<String> reqActions = new ArrayList<String>();
@@ -390,6 +391,10 @@ public class ModelToRepresentation {
             exportRequiredActions(realm, rep);
             exportGroups(realm, rep);
         }
+
+        Map<String, String> attributes = realm.getAttributes();
+        rep.setAttributes(attributes);
+
         return rep;
     }
 
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index f78f1cf..f228bc7 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -374,6 +374,15 @@ public class RepresentationToModel {
         if(rep.getDefaultLocale() != null){
             newRealm.setDefaultLocale(rep.getDefaultLocale());
         }
+        
+        // import attributes
+
+        if (rep.getAttributes() != null) {
+            for (Map.Entry<String, String> attr : rep.getAttributes().entrySet()) {
+                newRealm.setAttribute(attr.getKey(), attr.getValue());
+            }
+        }
+
     }
 
     protected static void importComponents(RealmModel newRealm, MultivaluedHashMap<String, ComponentExportRepresentation> components, String parentId) {
@@ -557,6 +566,19 @@ public class RepresentationToModel {
         if (newRealm.getFlowByAlias(DefaultAuthenticationFlows.FIRST_BROKER_LOGIN_FLOW) == null) {
             DefaultAuthenticationFlows.firstBrokerLoginFlow(newRealm, true);
         }
+
+        // Added in 2.2
+        String defaultProvider = null;
+        if (rep.getIdentityProviders() != null) {
+            for (IdentityProviderRepresentation i : rep.getIdentityProviders()) {
+                if (i.isEnabled() && i.isAuthenticateByDefault()) {
+                    defaultProvider = i.getProviderId();
+                    break;
+                }
+            }
+        }
+
+        DefaultAuthenticationFlows.addIdentityProviderAuthenticator(newRealm, defaultProvider);
     }
 
     private static void convertDeprecatedSocialProviders(RealmRepresentation rep) {
@@ -720,6 +742,21 @@ public class RepresentationToModel {
         if (rep.getRealm() != null) {
             renameRealm(realm, rep.getRealm());
         }
+
+        // Import attributes first, so the stuff saved directly on representation (displayName, bruteForce etc) has bigger priority
+        if (rep.getAttributes() != null) {
+            Set<String> attrsToRemove = new HashSet<>(realm.getAttributes().keySet());
+            attrsToRemove.removeAll(rep.getAttributes().keySet());
+
+            for (Map.Entry<String, String> entry : rep.getAttributes().entrySet()) {
+                realm.setAttribute(entry.getKey(), entry.getValue());
+            }
+
+            for (String attr : attrsToRemove) {
+                realm.removeAttribute(attr);
+            }
+        }
+
         if (rep.getDisplayName() != null) realm.setDisplayName(rep.getDisplayName());
         if (rep.getDisplayNameHtml() != null) realm.setDisplayNameHtml(rep.getDisplayNameHtml());
         if (rep.isEnabled() != null) realm.setEnabled(rep.isEnabled());
@@ -784,7 +821,7 @@ public class RepresentationToModel {
             realm.setUserFederationProviders(providerModels);
         }
 
-        if ("GENERATE".equals(rep.getPublicKey())) {
+        if (Constants.GENERATE.equals(rep.getPublicKey())) {
             KeycloakModelUtils.generateRealmKeys(realm);
         } else {
             if (rep.getPrivateKey() != null && rep.getPublicKey() != null) {
@@ -1005,6 +1042,8 @@ public class RepresentationToModel {
             client.updateDefaultRoles(resourceRep.getDefaultRoles());
         }
 
+
+
         if (resourceRep.getProtocolMappers() != null) {
             // first, remove all default/built in mappers
             Set<ProtocolMapperModel> mappers = client.getProtocolMappers();
@@ -1013,6 +1052,9 @@ public class RepresentationToModel {
             for (ProtocolMapperRepresentation mapper : resourceRep.getProtocolMappers()) {
                 client.addProtocolMapper(toModel(mapper));
             }
+
+
+
         }
 
         if (resourceRep.getClientTemplate() != null) {
@@ -1307,7 +1349,6 @@ public class RepresentationToModel {
         user.setFirstName(userRep.getFirstName());
         user.setLastName(userRep.getLastName());
         user.setFederationLink(userRep.getFederationLink());
-        if (userRep.isTotp() != null) user.setOtpEnabled(userRep.isTotp());
         if (userRep.getAttributes() != null) {
             for (Map.Entry<String, Object> entry : userRep.getAttributes().entrySet()) {
                 Object value = entry.getValue();
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/UserModelDelegate.java b/server-spi/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
index 4596ff4..9efdfad 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
@@ -61,11 +61,6 @@ public class UserModelDelegate implements UserModel {
     }
 
     @Override
-    public boolean isOtpEnabled() {
-        return delegate.isOtpEnabled();
-    }
-
-    @Override
     public void setEnabled(boolean enabled) {
         delegate.setEnabled(enabled);
     }
@@ -166,11 +161,6 @@ public class UserModelDelegate implements UserModel {
     }
 
     @Override
-    public void setOtpEnabled(boolean totp) {
-        delegate.setOtpEnabled(totp);
-    }
-
-    @Override
     public Set<RoleModel> getRealmRoleMappings() {
         return delegate.getRealmRoleMappings();
     }
diff --git a/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapperConfigException.java b/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapperConfigException.java
index f50a73d..3f1f676 100644
--- a/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapperConfigException.java
+++ b/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapperConfigException.java
@@ -22,21 +22,42 @@ package org.keycloak.protocol;
  */
 public class ProtocolMapperConfigException extends Exception {
 
+    private String messageKey;
     private Object[] parameters;
 
     public ProtocolMapperConfigException(String message) {
         super(message);
     }
 
+    public ProtocolMapperConfigException(String message, String messageKey) {
+        super(message);
+        this.messageKey = messageKey;
+    }
+
     public ProtocolMapperConfigException(String message, Throwable cause) {
         super(message, cause);
     }
 
+    public ProtocolMapperConfigException(String message, String messageKey, Throwable cause) {
+        super(message, cause);
+        this.messageKey = messageKey;
+    }
+
     public ProtocolMapperConfigException(String message, Object ... parameters) {
         super(message);
         this.parameters = parameters;
     }
 
+    public ProtocolMapperConfigException(String messageKey, String message, Object ... parameters) {
+        super(message);
+        this.messageKey = messageKey;
+        this.parameters = parameters;
+    }
+
+    public String getMessageKey() {
+        return messageKey;
+    }
+
     public Object[] getParameters() {
         return parameters;
     }
diff --git a/server-spi/src/main/java/org/keycloak/provider/EnvironmentDependentProviderFactory.java b/server-spi/src/main/java/org/keycloak/provider/EnvironmentDependentProviderFactory.java
new file mode 100644
index 0000000..b4e993a
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/provider/EnvironmentDependentProviderFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.provider;
+
+/**
+ * Providers that are only supported in some environments can implement this interface to be able to determine if they
+ * should be available or not.
+ *
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface EnvironmentDependentProviderFactory {
+
+    /**
+     * @return <code>true</code> if the provider is supported and should be available, <code>false</code> otherwise
+     */
+    boolean isSupported();
+
+}
diff --git a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java
index fdf1893..157f9dd 100644
--- a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java
+++ b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java
@@ -223,17 +223,6 @@ public abstract class AbstractUserAdapter implements UserModel {
         throw new ReadOnlyException("user is read only for this update");
     }
 
-    @Override
-    public boolean isOtpEnabled() {
-        return false;
-    }
-
-    @Override
-    public void setOtpEnabled(boolean totp) {
-        throw new ReadOnlyException("user is read only for this update");
-
-    }
-
     /**
      * This method should not be overriden
      *
diff --git a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
index 1b83fff..705a872 100644
--- a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
+++ b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
@@ -54,7 +54,6 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
     public static String EMAIL_VERIFIED_ATTRIBUTE = "EMAIL_VERIFIED";
     public static String CREATED_TIMESTAMP_ATTRIBUTE = "CREATED_TIMESTAMP";
     public static String ENABLED_ATTRIBUTE = "ENABLED";
-    public static String OTP_ENABLED_ATTRIBUTE = "OTP_ENABLED";
 
 
     protected KeycloakSession session;
@@ -235,19 +234,6 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
        setSingleAttribute(ENABLED_ATTRIBUTE, Boolean.toString(enabled));
     }
 
-    @Override
-    public boolean isOtpEnabled() {
-        String val = getFirstAttribute(OTP_ENABLED_ATTRIBUTE);
-        if (val == null) return false;
-        else return Boolean.valueOf(val);
-    }
-
-    @Override
-    public void setOtpEnabled(boolean totp) {
-        setSingleAttribute(OTP_ENABLED_ATTRIBUTE, Boolean.toString(totp));
-
-    }
-
     /**
      * This method should not be overriden
      *
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java
new file mode 100644
index 0000000..795d0c2
--- /dev/null
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.authentication.authenticators.browser;
+
+import org.jboss.logging.Logger;
+import org.keycloak.authentication.AuthenticationFlowContext;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.Urls;
+import org.keycloak.services.managers.ClientSessionCode;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class IdentityProviderAuthenticator implements Authenticator {
+
+    private static final Logger LOG = Logger.getLogger(IdentityProviderAuthenticator.class);
+
+    @Override
+    public void authenticate(AuthenticationFlowContext context) {
+        if (context.getUriInfo().getQueryParameters().containsKey(AdapterConstants.KC_IDP_HINT)) {
+            String providerId = context.getUriInfo().getQueryParameters().getFirst(AdapterConstants.KC_IDP_HINT);
+            if (providerId == null || providerId.equals("")) {
+                LOG.tracef("Skipping: kc_idp_hint query parameter is empty");
+                context.attempted();
+            } else {
+                LOG.tracef("Redirecting: %s set to %s", AdapterConstants.KC_IDP_HINT, providerId);
+                redirect(context, providerId);
+            }
+        } else if (context.getAuthenticatorConfig() != null && context.getAuthenticatorConfig().getConfig().containsKey(IdentityProviderAuthenticatorFactory.DEFAULT_PROVIDER)) {
+            String defaultProvider = context.getAuthenticatorConfig().getConfig().get(IdentityProviderAuthenticatorFactory.DEFAULT_PROVIDER);
+            LOG.tracef("Redirecting: default provider set to %s", defaultProvider);
+            redirect(context, defaultProvider);
+        } else {
+            LOG.tracef("No default provider set or %s query parameter provided", AdapterConstants.KC_IDP_HINT);
+            context.attempted();
+        }
+    }
+
+    private void redirect(AuthenticationFlowContext context, String providerId) {
+        List<IdentityProviderModel> identityProviders = context.getRealm().getIdentityProviders();
+        for (IdentityProviderModel identityProvider : identityProviders) {
+            if (identityProvider.isEnabled() && providerId.equals(identityProvider.getAlias())) {
+                String accessCode = new ClientSessionCode(context.getRealm(), context.getClientSession()).getCode();
+                Response response = Response.temporaryRedirect(
+                        Urls.identityProviderAuthnRequest(context.getUriInfo().getBaseUri(), providerId, context.getRealm().getName(), accessCode))
+                        .build();
+
+                LOG.debugf("Redirecting to %s", providerId);
+                context.forceChallenge(response);
+                return;
+            }
+        }
+
+        LOG.warnf("Provider not found or not enabled for realm %s", providerId);
+        context.attempted();
+    }
+
+    @Override
+    public void action(AuthenticationFlowContext context) {
+    }
+
+    @Override
+    public boolean requiresUser() {
+        return false;
+    }
+
+    @Override
+    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
+        return true;
+    }
+
+    @Override
+    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+    }
+
+    @Override
+    public void close() {
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticatorFactory.java
new file mode 100644
index 0000000..635c95e
--- /dev/null
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticatorFactory.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.authentication.authenticators.browser;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorFactory;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.keycloak.provider.ProviderConfigProperty.STRING_TYPE;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class IdentityProviderAuthenticatorFactory implements AuthenticatorFactory {
+
+    protected static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
+            AuthenticationExecutionModel.Requirement.ALTERNATIVE, AuthenticationExecutionModel.Requirement.DISABLED
+    };
+
+    protected static final String DEFAULT_PROVIDER = "defaultProvider";
+
+    @Override
+    public String getDisplayType() {
+        return "Identity Provider Redirector";
+    }
+
+    @Override
+    public String getReferenceCategory() {
+        return null;
+    }
+
+    @Override
+    public boolean isConfigurable() {
+        return true;
+    }
+
+    @Override
+    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+        return REQUIREMENT_CHOICES;
+    }
+
+    @Override
+    public boolean isUserSetupAllowed() {
+        return true;
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Redirects to default Identity Provider or Identity Provider specified with kc_idp_hint query parameter";
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        ProviderConfigProperty rep = new ProviderConfigProperty(DEFAULT_PROVIDER, "Default Identity Provider", "To automatically redirect to an identity provider set to the alias of the identity provider", STRING_TYPE, null);
+        return Collections.singletonList(rep);
+    }
+
+    @Override
+    public Authenticator create(KeycloakSession session) {
+        return new IdentityProviderAuthenticator();
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public String getId() {
+        return "identity-provider-redirector";
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java
index f576805..62344bd 100644
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java
@@ -86,7 +86,6 @@ public class UpdateTotp implements RequiredActionProvider, RequiredActionFactory
         cred.setValue(totp);
         context.getSession().userCredentialManager().isValid(context.getRealm(), context.getUser(), cred);
 
-        context.getUser().setOtpEnabled(true);
         context.success();
     }
 
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
index 4af34ad..076f9af 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
@@ -47,6 +47,7 @@ import org.keycloak.protocol.ProtocolMapper;
 import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.services.Urls;
+import org.keycloak.services.resources.admin.RealmAuth;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.POST;
@@ -74,20 +75,23 @@ import static java.util.Arrays.asList;
 public class PolicyEvaluationService {
 
     private final AuthorizationProvider authorization;
+    private final RealmAuth auth;
     @Context
     private HttpRequest httpRequest;
 
     private final ResourceServer resourceServer;
 
-    PolicyEvaluationService(ResourceServer resourceServer, AuthorizationProvider authorization) {
+    PolicyEvaluationService(ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
         this.resourceServer = resourceServer;
         this.authorization = authorization;
+        this.auth = auth;
     }
 
     @POST
     @Consumes("application/json")
     @Produces("application/json")
     public void evaluate(PolicyEvaluationRequest evaluationRequest, @Suspended AsyncResponse asyncResponse) {
+        this.auth.requireView();
         KeycloakIdentity identity = createIdentity(evaluationRequest);
         EvaluationContext evaluationContext = createEvaluationContext(evaluationRequest, identity);
         authorization.evaluators().from(createPermissions(evaluationRequest, evaluationContext, authorization), evaluationContext).evaluate(createDecisionCollector(authorization, identity, asyncResponse));
@@ -167,6 +171,13 @@ public class PolicyEvaluationService {
                     collect.addAll(storeFactory.getResourceStore().findByScope(scope.getId()).stream().map(resource12 -> new ResourcePermission(resource12, asList(scope), resourceServer)).collect(Collectors.toList()));
                 }
 
+                collect.addAll(storeFactory.getResourceStore().findByResourceServer(resourceServer.getId()).stream().map(new Function<Resource, ResourcePermission>() {
+                    @Override
+                    public ResourcePermission apply(Resource resource) {
+                        return new ResourcePermission(resource, resource.getScopes(), resourceServer);
+                    }
+                }).collect(Collectors.toList()));
+
                 return collect.stream();
             }
         }).collect(Collectors.toList());
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 3b9c194..b179378 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
@@ -273,7 +273,7 @@ public class PolicyService {
     @Path("evaluate")
     public PolicyEvaluationService getPolicyEvaluateResource() {
         this.auth.requireView();
-        PolicyEvaluationService resource = new PolicyEvaluationService(this.resourceServer, this.authorization);
+        PolicyEvaluationService resource = new PolicyEvaluationService(this.resourceServer, this.authorization, this.auth);
 
         ResteasyProviderFactory.getInstance().injectProperties(resource);
 
diff --git a/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationResponse.java b/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationResponse.java
index d320a64..4f0c64a 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationResponse.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationResponse.java
@@ -132,7 +132,10 @@ public class PolicyEvaluationResponse {
                         scopes.add(scope);
                     }
                     if (evaluationResultRepresentation.getStatus().equals(Effect.PERMIT)) {
-                        result.getAllowedScopes().add(scope);
+                        List<ScopeRepresentation> allowedScopes = result.getAllowedScopes();
+                        if (!allowedScopes.contains(scope)) {
+                            allowedScopes.add(scope);
+                        }
                     }
                 }
             }
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 d31146f..64ef061 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
@@ -177,7 +177,7 @@ public class ResourceSetService {
     @GET
     @NoCache
     @Produces("application/json")
-    public Response findAll(@QueryParam("name") String name,
+    public Response find(@QueryParam("name") String name,
                             @QueryParam("uri") String uri,
                             @QueryParam("owner") String owner,
                             @QueryParam("type") String type,
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 44464b4..f050f32 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
@@ -107,6 +107,11 @@ public class ScopeService {
         }
 
         Scope scope = storeFactory.getScopeStore().findById(id);
+
+        if (scope == null) {
+            return Response.status(Status.NOT_FOUND).build();
+        }
+
         PolicyStore policyStore = storeFactory.getPolicyStore();
         List<Policy> policies = policyStore.findByScopeIds(Arrays.asList(scope.getId()), resourceServer.getId());
 
diff --git a/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java b/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java
index b02a935..fdaa12f 100644
--- a/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java
+++ b/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java
@@ -109,7 +109,7 @@ public class ResourceService {
     }
 
     private Set<String> findAll() {
-        Response response = this.resourceManager.findAll(null, null, null, null, null, -1, -1);
+        Response response = this.resourceManager.find(null, null, null, null, null, -1, -1);
         List<ResourceRepresentation> resources = (List<ResourceRepresentation>) response.getEntity();
         return resources.stream().map(ResourceRepresentation::getId).collect(Collectors.toSet());
     }
diff --git a/services/src/main/java/org/keycloak/credential/OTPCredentialProvider.java b/services/src/main/java/org/keycloak/credential/OTPCredentialProvider.java
index 48875b6..b6dd489 100644
--- a/services/src/main/java/org/keycloak/credential/OTPCredentialProvider.java
+++ b/services/src/main/java/org/keycloak/credential/OTPCredentialProvider.java
@@ -93,7 +93,7 @@ public class OTPCredentialProvider implements CredentialProvider, CredentialInpu
         model.setValue(inputModel.getValue());
         model.setDevice(inputModel.getDevice());
         model.setPeriod(policy.getPeriod());
-        model.setCreatedDate(Time.toMillis(Time.currentTime()));
+        model.setCreatedDate(Time.currentTimeMillis());
         if (model.getId() == null) {
             getCredentialStore().createCredential(realm, user, model);
         } else {
@@ -196,6 +196,10 @@ public class OTPCredentialProvider implements CredentialProvider, CredentialInpu
 
         }
         String token = ((UserCredentialModel)input).getValue();
+        if (token == null) {
+            return false;
+        }
+
         OTPPolicy policy = realm.getOTPPolicy();
         if (realm.getOTPPolicy().getType().equals(CredentialModel.HOTP)) {
             HmacOTP validator = new HmacOTP(policy.getDigits(), policy.getAlgorithm(), policy.getLookAheadWindow());
diff --git a/services/src/main/java/org/keycloak/credential/PasswordCredentialProvider.java b/services/src/main/java/org/keycloak/credential/PasswordCredentialProvider.java
index 8b94eb3..17803c1 100644
--- a/services/src/main/java/org/keycloak/credential/PasswordCredentialProvider.java
+++ b/services/src/main/java/org/keycloak/credential/PasswordCredentialProvider.java
@@ -93,7 +93,7 @@ public class PasswordCredentialProvider implements CredentialProvider, Credentia
         expirePassword(realm, user, policy);
         CredentialModel newPassword = new CredentialModel();
         newPassword.setType(CredentialModel.PASSWORD);
-        long createdDate = Time.toMillis(Time.currentTime());
+        long createdDate = Time.currentTimeMillis();
         newPassword.setCreatedDate(createdDate);
         hash.encode(cred.getValue(), policy, newPassword);
         getCredentialStore().createCredential(realm, user, newPassword);
diff --git a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
index 5ea3fb8..598b8e2 100755
--- a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
+++ b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
@@ -459,7 +459,7 @@ public class ExportUtils {
      * @return fully exported user representation
      */
     public static UserRepresentation exportUser(KeycloakSession session, RealmModel realm, UserModel user) {
-        UserRepresentation userRep = ModelToRepresentation.toRepresentation(user);
+        UserRepresentation userRep = ModelToRepresentation.toRepresentation(session, realm, user);
 
         // Social links
         Set<FederatedIdentityModel> socialLinks = session.users().getFederatedIdentities(user, realm);
diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/model/AccountBean.java b/services/src/main/java/org/keycloak/forms/account/freemarker/model/AccountBean.java
index 857bfc0..ceaaf94 100755
--- a/services/src/main/java/org/keycloak/forms/account/freemarker/model/AccountBean.java
+++ b/services/src/main/java/org/keycloak/forms/account/freemarker/model/AccountBean.java
@@ -73,7 +73,11 @@ public class AccountBean {
     }
 
     public String getUsername() {
-        return profileFormData != null ? profileFormData.getFirst("username") : user.getUsername();
+        if (profileFormData != null && profileFormData.containsKey("username")) {
+            return profileFormData.getFirst("username");
+        } else {
+            return user.getUsername();
+        }
     }
 
     public String getEmail() {
diff --git a/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java b/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java
index 44ee44d..631ff57 100755
--- a/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java
+++ b/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java
@@ -279,7 +279,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
 
         switch (page) {
             case LOGIN_CONFIG_TOTP:
-                attributes.put("totp", new TotpBean(realm, user));
+                attributes.put("totp", new TotpBean(session, realm, user));
                 break;
             case LOGIN_UPDATE_PROFILE:
                 UpdateProfileContext userCtx = (UpdateProfileContext) attributes.get(LoginFormsProvider.UPDATE_PROFILE_CONTEXT_ATTR);
diff --git a/services/src/main/java/org/keycloak/forms/login/freemarker/model/TotpBean.java b/services/src/main/java/org/keycloak/forms/login/freemarker/model/TotpBean.java
index d1e1d9c..c302533 100755
--- a/services/src/main/java/org/keycloak/forms/login/freemarker/model/TotpBean.java
+++ b/services/src/main/java/org/keycloak/forms/login/freemarker/model/TotpBean.java
@@ -16,6 +16,8 @@
  */
 package org.keycloak.forms.login.freemarker.model;
 
+import org.keycloak.credential.CredentialModel;
+import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.Base32;
@@ -36,9 +38,8 @@ public class TotpBean {
     private final String totpSecretQrCode;
     private final boolean enabled;
 
-    public TotpBean(RealmModel realm, UserModel user) {
-        this.enabled = user.isOtpEnabled();
-
+    public TotpBean(KeycloakSession session, RealmModel realm, UserModel user) {
+        this.enabled = session.userCredentialManager().isConfiguredFor(realm, user, CredentialModel.OTP);
         this.totpSecret = HmacOTP.generateSecret(20);
         this.totpSecretEncoded = TotpUtils.encode(totpSecret);
         this.totpSecretQrCode = TotpUtils.qrCode(totpSecret, realm, user);
diff --git a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
index bfbf7a1..12dba27 100755
--- a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
+++ b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
@@ -17,8 +17,6 @@
 
 package org.keycloak.protocol;
 
-import java.util.List;
-
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
@@ -31,14 +29,11 @@ import org.keycloak.events.Details;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.models.AuthenticationFlowModel;
 import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.LoginProtocol.Error;
 import org.keycloak.services.ServicesLogger;
-import org.keycloak.services.Urls;
 import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.resources.LoginActionsService;
 
 /**
@@ -95,15 +90,6 @@ public abstract class AuthorizationEndpointBase {
      * @return response to be returned to the browser
      */
     protected Response handleBrowserAuthenticationRequest(ClientSessionModel clientSession, LoginProtocol protocol, boolean isPassive, boolean redirectToAuthentication) {
-
-        List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
-        for (IdentityProviderModel identityProvider : identityProviders) {
-            if (identityProvider.isEnabled() && identityProvider.isAuthenticateByDefault()) {
-                // TODO if we are isPassive we should propagate this flag to default identity provider also if possible
-                return buildRedirectToIdentityProvider(identityProvider.getAlias(), new ClientSessionCode(realm, clientSession).getCode());
-            }
-        }
-
         AuthenticationFlowModel flow = getAuthenticationFlow();
         String flowId = flow.getId();
         AuthenticationProcessor processor = createProcessor(clientSession, flowId, LoginActionsService.AUTHENTICATE_PATH);
@@ -147,11 +133,4 @@ public abstract class AuthorizationEndpointBase {
         return realm.getBrowserFlow();
     }
 
-    protected Response buildRedirectToIdentityProvider(String providerId, String accessCode) {
-        logger.debug("Automatically redirect to identity provider: " + providerId);
-        return Response.temporaryRedirect(
-                Urls.identityProviderAuthnRequest(this.uriInfo.getBaseUri(), providerId, this.realm.getName(), accessCode))
-                .build();
-    }
-
 }
\ No newline at end of file
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 1b4db29..3f18b27 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
@@ -29,11 +29,9 @@ import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
-import org.keycloak.forms.login.LoginFormsProvider;
 import org.keycloak.models.AuthenticationFlowModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.AuthorizationEndpointBase;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
@@ -46,7 +44,6 @@ import org.keycloak.protocol.oidc.utils.RedirectUtils;
 import org.keycloak.services.ErrorPageException;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.Urls;
-import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.LoginActionsService;
 import org.keycloak.services.util.CacheControlUtil;
@@ -313,19 +310,6 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
     }
 
     private Response buildAuthorizationCodeAuthorizationResponse() {
-        String idpHint = request.getIdpHint();
-
-        if (idpHint != null && !"".equals(idpHint)) {
-            IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(idpHint);
-
-            if (identityProviderModel == null) {
-                return session.getProvider(LoginFormsProvider.class)
-                        .setError(Messages.IDENTITY_PROVIDER_NOT_FOUND, idpHint)
-                        .createErrorPage();
-            }
-            return buildRedirectToIdentityProvider(idpHint, new ClientSessionCode(realm, clientSession).getCode());
-        }
-
         this.event.event(EventType.LOGIN);
         clientSession.setNote(Details.AUTH_TYPE, CODE_AUTH_TYPE);
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
index f5e4caa..28d9514 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
@@ -19,10 +19,9 @@ package org.keycloak.protocol.oidc.endpoints;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.HttpResponse;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.common.ClientConnection;
 import org.keycloak.OAuthErrorException;
 import org.keycloak.RSATokenVerifier;
+import org.keycloak.common.ClientConnection;
 import org.keycloak.common.VerificationException;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
@@ -30,20 +29,15 @@ import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
 import org.keycloak.jose.jws.Algorithm;
 import org.keycloak.jose.jws.JWSBuilder;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.*;
 import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.services.ErrorResponseException;
+import org.keycloak.services.Urls;
 import org.keycloak.services.managers.AppAuthManager;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.resources.Cors;
-import org.keycloak.services.Urls;
 import org.keycloak.utils.MediaType;
 
 import javax.ws.rs.GET;
@@ -54,7 +48,6 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
-
 import java.security.PrivateKey;
 import java.util.HashMap;
 import java.util.Map;
@@ -179,8 +172,8 @@ public class UserInfoEndpoint {
         tokenManager.transformUserInfoAccessToken(session, userInfo, realm, clientModel, userModel, userSession, clientSession);
 
         Map<String, Object> claims = new HashMap<String, Object>();
-        claims.putAll(userInfo.getOtherClaims());
         claims.put("sub", userModel.getId());
+        claims.putAll(userInfo.getOtherClaims());
 
         Response.ResponseBuilder responseBuilder;
         OIDCAdvancedConfigWrapper cfg = OIDCAdvancedConfigWrapper.fromClientModel(clientModel);
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 6fda3f0..79a3919 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
@@ -51,7 +51,6 @@ public class KeycloakOIDCClientInstallation implements ClientInstallationProvide
         ClientManager.InstallationAdapterConfig rep = new ClientManager.InstallationAdapterConfig();
         rep.setAuthServerUrl(baseUri.toString());
         rep.setRealm(realm.getName());
-        rep.setRealmKey(realm.getPublicKeyPem());
         rep.setSslRequired(realm.getSslRequired().name().toLowerCase());
 
         if (client.isPublicClient() && !client.isBearerOnly()) rep.setPublicClient(true);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCJbossSubsystemClientInstallation.java b/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCJbossSubsystemClientInstallation.java
index 33ab677..d0bc939 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCJbossSubsystemClientInstallation.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCJbossSubsystemClientInstallation.java
@@ -40,7 +40,6 @@ public class KeycloakOIDCJbossSubsystemClientInstallation implements ClientInsta
         StringBuffer buffer = new StringBuffer();
         buffer.append("<secure-deployment name=\"WAR MODULE NAME.war\">\n");
         buffer.append("    <realm>").append(realm.getName()).append("</realm>\n");
-        buffer.append("    <realm-public-key>").append(realm.getPublicKeyPem()).append("</realm-public-key>\n");
         buffer.append("    <auth-server-url>").append(baseUri.toString()).append("</auth-server-url>\n");
         if (client.isBearerOnly()){
             buffer.append("    <bearer-only>true</bearer-only>\n");
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractPairwiseSubMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractPairwiseSubMapper.java
new file mode 100644
index 0000000..b153fe4
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractPairwiseSubMapper.java
@@ -0,0 +1,125 @@
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.*;
+import org.keycloak.protocol.ProtocolMapperConfigException;
+import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
+import org.keycloak.protocol.oidc.utils.PairwiseSubMapperValidator;
+import org.keycloak.protocol.oidc.utils.PairwiseSubMapperUtils;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Set the 'sub' claim to pairwise .
+ *
+ * @author <a href="mailto:martin.hardselius@gmail.com">Martin Hardselius</a>
+ */
+public abstract class AbstractPairwiseSubMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
+    public static final String PROVIDER_ID_SUFFIX = "-pairwise-sub-mapper";
+
+    public static String getId(String prefix) {
+        return prefix + PROVIDER_ID_SUFFIX;
+    }
+
+    public abstract String getIdPrefix();
+
+    /**
+     * Generates a pairwise subject identifier.
+     *
+     * @param mappingModel
+     * @param sectorIdentifier client sector identifier
+     * @param localSub         local subject identifier (user id)
+     * @return A pairwise subject identifier
+     */
+    public abstract String generateSub(ProtocolMapperModel mappingModel, String sectorIdentifier, String localSub);
+
+    /**
+     * Override to add additional provider configuration properties. By default, a pairwise sub mapper will only contain configuration for a sector identifier URI.
+     *
+     * @return A list of provider configuration properties.
+     */
+    public List<ProviderConfigProperty> getAdditionalConfigProperties() {
+        return new LinkedList<>();
+    }
+
+    /**
+     * Override to add additional configuration validation. Called when instance of mapperModel is created/updated for this protocolMapper through admin endpoint.
+     *
+     * @param session
+     * @param realm
+     * @param mapperContainer client or clientTemplate
+     * @param mapperModel
+     * @throws ProtocolMapperConfigException if configuration provided in mapperModel is not valid
+     */
+    public void validateAdditionalConfig(KeycloakSession session, RealmModel realm, ProtocolMapperContainerModel mapperContainer, ProtocolMapperModel mapperModel) throws ProtocolMapperConfigException {
+    }
+
+    @Override
+    public final String getDisplayCategory() {
+        return AbstractOIDCProtocolMapper.TOKEN_MAPPER_CATEGORY;
+    }
+
+    @Override
+    public final IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        setSubject(token, generateSub(mappingModel, getSectorIdentifier(clientSession.getClient(), mappingModel), userSession.getUser().getId()));
+        return token;
+    }
+
+    @Override
+    public final AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        setSubject(token, generateSub(mappingModel, getSectorIdentifier(clientSession.getClient(), mappingModel), userSession.getUser().getId()));
+        return token;
+    }
+
+    @Override
+    public final AccessToken transformUserInfoToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        setSubject(token, generateSub(mappingModel, getSectorIdentifier(clientSession.getClient(), mappingModel), userSession.getUser().getId()));
+        return token;
+    }
+
+    private void setSubject(IDToken token, String pairwiseSub) {
+        token.getOtherClaims().put("sub", pairwiseSub);
+    }
+
+    @Override
+    public final List<ProviderConfigProperty> getConfigProperties() {
+        List<ProviderConfigProperty> configProperties = new LinkedList<>();
+        configProperties.add(PairwiseSubMapperHelper.createSectorIdentifierConfig());
+        configProperties.addAll(getAdditionalConfigProperties());
+        return configProperties;
+    }
+
+    private String getSectorIdentifier(ClientModel client, ProtocolMapperModel mappingModel) {
+        String sectorIdentifierUri = PairwiseSubMapperHelper.getSectorIdentifierUri(mappingModel);
+        if (sectorIdentifierUri != null && !sectorIdentifierUri.isEmpty()) {
+            return PairwiseSubMapperUtils.resolveValidSectorIdentifier(sectorIdentifierUri);
+        }
+        return PairwiseSubMapperUtils.resolveValidSectorIdentifier(client.getRootUrl(), client.getRedirectUris());
+    }
+
+    @Override
+    public final void validateConfig(KeycloakSession session, RealmModel realm, ProtocolMapperContainerModel mapperContainer, ProtocolMapperModel mapperModel) throws ProtocolMapperConfigException {
+        ClientModel client = null;
+        if (mapperContainer instanceof ClientModel) {
+            client = (ClientModel) mapperContainer;
+            PairwiseSubMapperValidator.validate(session, client, mapperModel);
+        }
+        validateAdditionalConfig(session, realm, mapperContainer, mapperModel);
+
+        if (client != null) {
+            // Propagate changes to the sector identifier uri
+            OIDCAdvancedConfigWrapper configWrapper = OIDCAdvancedConfigWrapper.fromClientModel(client);
+            configWrapper.setSectorIdentifierUri(PairwiseSubMapperHelper.getSectorIdentifierUri(mapperModel));
+        }
+    }
+
+    @Override
+    public final String getId() {
+        return getIdPrefix() + PROVIDER_ID_SUFFIX;
+    }
+}
+
+
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/PairwiseSubMapperHelper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/PairwiseSubMapperHelper.java
new file mode 100644
index 0000000..a2aa4b3
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/PairwiseSubMapperHelper.java
@@ -0,0 +1,47 @@
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.services.ServicesLogger;
+
+public class PairwiseSubMapperHelper {
+    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+
+    public static final String SECTOR_IDENTIFIER_URI = "sectorIdentifierUri";
+    public static final String SECTOR_IDENTIFIER_URI_LABEL = "sectorIdentifierUri.label";
+    public static final String SECTOR_IDENTIFIER_URI_HELP_TEXT = "sectorIdentifierUri.tooltip";
+
+    public static final String PAIRWISE_SUB_ALGORITHM_SALT = "pairwiseSubAlgorithmSalt";
+    public static final String PAIRWISE_SUB_ALGORITHM_SALT_LABEL = "pairwiseSubAlgorithmSalt.label";
+    public static final String PAIRWISE_SUB_ALGORITHM_SALT_HELP_TEXT = "pairwiseSubAlgorithmSalt.tooltip";
+
+    public static String getSectorIdentifierUri(ProtocolMapperModel mappingModel) {
+        return mappingModel.getConfig().get(SECTOR_IDENTIFIER_URI);
+    }
+
+    public static String getSalt(ProtocolMapperModel mappingModel) {
+        return mappingModel.getConfig().get(PAIRWISE_SUB_ALGORITHM_SALT);
+    }
+
+    public static void setSalt(ProtocolMapperModel mappingModel, String salt) {
+        mappingModel.getConfig().put(PAIRWISE_SUB_ALGORITHM_SALT, salt);
+    }
+
+    public static ProviderConfigProperty createSectorIdentifierConfig() {
+        ProviderConfigProperty property = new ProviderConfigProperty();
+        property.setName(SECTOR_IDENTIFIER_URI);
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        property.setLabel(SECTOR_IDENTIFIER_URI_LABEL);
+        property.setHelpText(SECTOR_IDENTIFIER_URI_HELP_TEXT);
+        return property;
+    }
+
+    public static ProviderConfigProperty createSaltConfig() {
+        ProviderConfigProperty property = new ProviderConfigProperty();
+        property.setName(PAIRWISE_SUB_ALGORITHM_SALT);
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        property.setLabel(PAIRWISE_SUB_ALGORITHM_SALT_LABEL);
+        property.setHelpText(PAIRWISE_SUB_ALGORITHM_SALT_HELP_TEXT);
+        return property;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/SHA265PairwiseSubMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/SHA265PairwiseSubMapper.java
new file mode 100644
index 0000000..bc1caaa
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/SHA265PairwiseSubMapper.java
@@ -0,0 +1,119 @@
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.services.ServicesLogger;
+
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.*;
+
+public class SHA265PairwiseSubMapper extends AbstractPairwiseSubMapper {
+    public static final String PROVIDER_ID = "sha256";
+    private static final String HASH_ALGORITHM = "SHA-256";
+    private static final String ALPHA_NUMERIC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private final Charset charset;
+
+    public SHA265PairwiseSubMapper() throws NoSuchAlgorithmException {
+        charset = Charset.forName("UTF-8");
+        MessageDigest.getInstance(HASH_ALGORITHM);
+    }
+
+    public static ProtocolMapperModel createPairwiseMapper() {
+        return createPairwiseMapper(null);
+    }
+
+    public static ProtocolMapperModel createPairwiseMapper(String sectorIdentifierUri) {
+        Map<String, String> config;
+        ProtocolMapperModel pairwise = new ProtocolMapperModel();
+        pairwise.setName("pairwise subject identifier");
+        pairwise.setProtocolMapper(AbstractPairwiseSubMapper.getId(PROVIDER_ID));
+        pairwise.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        pairwise.setConsentRequired(false);
+        config = new HashMap<>();
+        config.put(PairwiseSubMapperHelper.SECTOR_IDENTIFIER_URI, sectorIdentifierUri);
+        pairwise.setConfig(config);
+        return pairwise;
+    }
+
+    public static ProtocolMapperModel createPairwiseMapper(String sectorIdentifierUri, String salt) {
+        Map<String, String> config;
+        ProtocolMapperModel pairwise = new ProtocolMapperModel();
+        pairwise.setName("pairwise subject identifier");
+        pairwise.setProtocolMapper(AbstractPairwiseSubMapper.getId(PROVIDER_ID));
+        pairwise.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        pairwise.setConsentRequired(false);
+        config = new HashMap<>();
+        config.put(PairwiseSubMapperHelper.SECTOR_IDENTIFIER_URI, sectorIdentifierUri);
+        config.put(PairwiseSubMapperHelper.PAIRWISE_SUB_ALGORITHM_SALT, salt);
+        pairwise.setConfig(config);
+        return pairwise;
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Calculates a pairwise subject identifier using a salted sha-256 hash.";
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getAdditionalConfigProperties() {
+        List<ProviderConfigProperty> configProperties = new LinkedList<>();
+        configProperties.add(PairwiseSubMapperHelper.createSaltConfig());
+        return configProperties;
+    }
+
+    @Override
+    public String generateSub(ProtocolMapperModel mappingModel, String sectorIdentifier, String localSub) {
+        String saltStr = getSalt(mappingModel);
+
+        Charset charset = Charset.forName("UTF-8");
+        byte[] salt = saltStr.getBytes(charset);
+        String pairwiseSub = generateSub(sectorIdentifier, localSub, salt);
+        logger.infof("local sub = '%s', pairwise sub = '%s'", localSub, pairwiseSub);
+        return pairwiseSub;
+    }
+
+    private String generateSub(String sectorIdentifier, String localSub, byte[] salt) {
+        MessageDigest sha256;
+        try {
+            sha256 = MessageDigest.getInstance(HASH_ALGORITHM);
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalStateException(e.getMessage(), e);
+        }
+        sha256.update(sectorIdentifier.getBytes(charset));
+        sha256.update(localSub.getBytes(charset));
+        byte[] hash = sha256.digest(salt);
+        return UUID.nameUUIDFromBytes(hash).toString();
+    }
+
+    private String getSalt(ProtocolMapperModel mappingModel) {
+        String salt = PairwiseSubMapperHelper.getSalt(mappingModel);
+        if (salt == null || salt.trim().isEmpty()) {
+            salt = createSalt(32);
+            PairwiseSubMapperHelper.setSalt(mappingModel, salt);
+        }
+        return salt;
+    }
+
+    private String createSalt(int len) {
+        Random rnd = new SecureRandom();
+        StringBuilder sb = new StringBuilder(len);
+        for (int i = 0; i < len; i++)
+            sb.append(ALPHA_NUMERIC.charAt(rnd.nextInt(ALPHA_NUMERIC.length())));
+        return sb.toString();
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Pairwise subject identifier";
+    }
+
+    @Override
+    public String getIdPrefix() {
+        return PROVIDER_ID;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCAdvancedConfigWrapper.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCAdvancedConfigWrapper.java
index 3233690..e16d7b8 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCAdvancedConfigWrapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCAdvancedConfigWrapper.java
@@ -17,12 +17,13 @@
 
 package org.keycloak.protocol.oidc;
 
-import java.util.HashMap;
-
 import org.keycloak.jose.jws.Algorithm;
 import org.keycloak.models.ClientModel;
+import org.keycloak.protocol.oidc.utils.SubjectType;
 import org.keycloak.representations.idm.ClientRepresentation;
 
+import java.util.HashMap;
+
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
@@ -32,6 +33,11 @@ public class OIDCAdvancedConfigWrapper {
 
     private static final String REQUEST_OBJECT_SIGNATURE_ALG = "request.object.signature.alg";
 
+    private static final String SUBJECT_TYPE = "oidc.subject_type";
+    private static final String SECTOR_IDENTIFIER_URI = "oidc.sector_identifier_uri";
+    private static final String PUBLIC = "public";
+    private static final String PAIRWISE = "pairwise";
+
     private final ClientModel clientModel;
     private final ClientRepresentation clientRep;
 
@@ -74,6 +80,27 @@ public class OIDCAdvancedConfigWrapper {
         setAttribute(REQUEST_OBJECT_SIGNATURE_ALG, algStr);
     }
 
+    public void setSubjectType(SubjectType subjectType) {
+        if (subjectType == null) {
+            setAttribute(SUBJECT_TYPE, SubjectType.PUBLIC.toString());
+            return;
+        }
+        setAttribute(SUBJECT_TYPE, subjectType.toString());
+    }
+
+    public SubjectType getSubjectType() {
+        String subjectType = getAttribute(SUBJECT_TYPE);
+        return subjectType == null ? SubjectType.PUBLIC : Enum.valueOf(SubjectType.class, subjectType);
+    }
+
+    public void setSectorIdentifierUri(String sectorIdentifierUri) {
+        setAttribute(SECTOR_IDENTIFIER_URI, sectorIdentifierUri);
+    }
+
+    public String getSectorIdentifierUri() {
+        return getAttribute(SECTOR_IDENTIFIER_URI);
+    }
+
 
     private String getAttribute(String attrKey) {
         if (clientModel != null) {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
index 087b1f6..aa56dc7 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
@@ -19,31 +19,15 @@ package org.keycloak.protocol.oidc;
 import org.keycloak.common.constants.KerberosConstants;
 import org.keycloak.common.util.UriUtils;
 import org.keycloak.events.EventBuilder;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientTemplateModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
+import org.keycloak.models.*;
 import org.keycloak.protocol.AbstractLoginProtocolFactory;
 import org.keycloak.protocol.LoginProtocol;
-import org.keycloak.protocol.oidc.mappers.AddressMapper;
-import org.keycloak.protocol.oidc.mappers.FullNameMapper;
-import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
-import org.keycloak.protocol.oidc.mappers.UserPropertyMapper;
-import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
+import org.keycloak.protocol.oidc.mappers.*;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.ClientTemplateRepresentation;
 import org.keycloak.services.ServicesLogger;
-import org.keycloak.services.managers.AuthenticationManager;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
+import java.util.*;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -146,6 +130,9 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
         ProtocolMapperModel address = AddressMapper.createAddressMapper();
         builtins.add(address);
 
+        ProtocolMapperModel pairwise = SHA265PairwiseSubMapper.createPairwiseMapper();
+        builtins.add(pairwise);
+
         model = UserSessionNoteMapper.createClaimMapper(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME,
                 KerberosConstants.GSS_DELEGATION_CREDENTIAL,
                 KerberosConstants.GSS_DELEGATION_CREDENTIAL, "String",
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 800630c..2653b9b 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
@@ -56,7 +56,7 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
 
     public static final List<String> DEFAULT_RESPONSE_TYPES_SUPPORTED = list(OAuth2Constants.CODE, OIDCResponseType.NONE, OIDCResponseType.ID_TOKEN, OIDCResponseType.TOKEN, "id_token token", "code id_token", "code token", "code id_token token");
 
-    public static final List<String> DEFAULT_SUBJECT_TYPES_SUPPORTED = list("public");
+    public static final List<String> DEFAULT_SUBJECT_TYPES_SUPPORTED = list("public", "pairwise");
 
     public static final List<String> DEFAULT_RESPONSE_MODES_SUPPORTED = list("query", "fragment", "form_post");
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/JWKSUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/JWKSUtils.java
index d8f7fe7..62d2c58 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/JWKSUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/JWKSUtils.java
@@ -30,6 +30,8 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.util.JsonSerialization;
 
 /**
+ * TODO: Merge with JWKSUtils from keycloak-core?
+ *
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
 public class JWKSUtils {
@@ -44,7 +46,7 @@ public class JWKSUtils {
     public static PublicKey getKeyForUse(JSONWebKeySet keySet, JWK.Use requestedUse) {
         for (JWK jwk : keySet.getKeys()) {
             JWKParser parser = JWKParser.create(jwk);
-            if (parser.getJwk().getPublicKeyUse().equals(requestedUse.asString()) && parser.isAlgorithmSupported(jwk.getKeyType())) {
+            if (parser.getJwk().getPublicKeyUse().equals(requestedUse.asString()) && parser.isKeyTypeSupported(jwk.getKeyType())) {
                 return parser.toPublicKey();
             }
         }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/PairwiseSubMapperUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/PairwiseSubMapperUtils.java
new file mode 100644
index 0000000..5e2dadc
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/PairwiseSubMapperUtils.java
@@ -0,0 +1,159 @@
+package org.keycloak.protocol.oidc.utils;
+
+import org.keycloak.protocol.oidc.mappers.AbstractPairwiseSubMapper;
+import org.keycloak.protocol.oidc.mappers.PairwiseSubMapperHelper;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.services.ServicesLogger;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class PairwiseSubMapperUtils {
+    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+
+    /**
+     * Returns a set of valid redirect URIs from the root url and redirect URIs registered on a client.
+     *
+     * @param clientRootUrl
+     * @param clientRedirectUris
+     * @return
+     */
+    public static Set<String> resolveValidRedirectUris(String clientRootUrl, Set<String> clientRedirectUris) {
+        Set<String> validRedirects = new HashSet<String>();
+        for (String redirectUri : clientRedirectUris) {
+            if (redirectUri.startsWith("/")) {
+                redirectUri = relativeToAbsoluteURI(clientRootUrl, redirectUri);
+                logger.debugv("replacing relative valid redirect with: {0}", redirectUri);
+            }
+            if (redirectUri != null) {
+                validRedirects.add(redirectUri);
+            }
+        }
+        return validRedirects.stream()
+                .filter(r -> r != null && !r.trim().isEmpty())
+                .collect(Collectors.toSet());
+    }
+
+    /**
+     * Tries to resolve a valid sector identifier from a sector identifier URI.
+     *
+     * @param sectorIdentifierUri
+     * @return a sector identifier iff. the sector identifier URI is a valid URI, contains a valid scheme and contains a valid host component.
+     */
+    public static String resolveValidSectorIdentifier(String sectorIdentifierUri) {
+        URI uri;
+        try {
+            uri = new URI(sectorIdentifierUri);
+        } catch (URISyntaxException e) {
+            logger.debug("Invalid sector identifier URI", e);
+            return null;
+        }
+
+        if (uri.getScheme() == null) {
+            logger.debugv("Invalid sector identifier URI: {0}", sectorIdentifierUri);
+            return null;
+        }
+
+        /*if (!uri.getScheme().equalsIgnoreCase("https")) {
+            logger.debugv("The sector identifier URI scheme must be HTTPS. Was '{0}'", uri.getScheme());
+            return null;
+        }*/
+
+        if (uri.getHost() == null) {
+            logger.debug("The sector identifier URI must specify a host");
+            return null;
+        }
+
+        return uri.getHost();
+    }
+
+    /**
+     * Tries to resolve a valid sector identifier from the redirect URIs registered on a client.
+     *
+     * @param clientRootUrl      Root url registered on the client.
+     * @param clientRedirectUris Redirect URIs registered on the client.
+     * @return a sector identifier iff. all the registered redirect URIs are located at the same host, otherwise {@code null}.
+     */
+    public static String resolveValidSectorIdentifier(String clientRootUrl, Set<String> clientRedirectUris) {
+        Set<String> hosts = new HashSet<>();
+        for (String redirectUri : resolveValidRedirectUris(clientRootUrl, clientRedirectUris)) {
+            try {
+                URI uri = new URI(redirectUri);
+                hosts.add(uri.getHost());
+            } catch (URISyntaxException e) {
+                logger.debugv("client redirect uris contained an invalid uri: {0}", redirectUri);
+            }
+        }
+        if (hosts.isEmpty()) {
+            logger.debug("could not infer any valid sector_identifiers from client redirect uris");
+            return null;
+        }
+        if (hosts.size() > 1) {
+            logger.debug("the client redirect uris contained multiple hosts");
+            return null;
+        }
+        return hosts.iterator().next();
+    }
+
+    /**
+     * Checks if the the registered client redirect URIs matches the set of redirect URIs from the sector identifier URI.
+     *
+     * @param clientRootUrl      root url registered on the client.
+     * @param clientRedirectUris redirect URIs registered on the client.
+     * @param sectorRedirects    value of the sector identifier URI.
+     * @return {@code true} iff. the all the redirect URIs can be described by the {@code sectorRedirects}, i.e if the registered redirect URIs is a subset of the {@code sectorRedirects}, otherwise {@code false}.
+     */
+    public static boolean matchesRedirects(String clientRootUrl, Set<String> clientRedirectUris, Set<String> sectorRedirects) {
+        Set<String> validRedirects = resolveValidRedirectUris(clientRootUrl, clientRedirectUris);
+        for (String redirect : validRedirects) {
+            if (!matchesRedirect(sectorRedirects, redirect)) return false;
+        }
+        return true;
+    }
+
+    private static boolean matchesRedirect(Set<String> validRedirects, String redirect) {
+        for (String validRedirect : validRedirects) {
+            if (validRedirect.endsWith("*") && !validRedirect.contains("?")) {
+                // strip off the query component - we don't check them when wildcards are effective
+                String r = redirect.contains("?") ? redirect.substring(0, redirect.indexOf("?")) : redirect;
+                // strip off *
+                int length = validRedirect.length() - 1;
+                validRedirect = validRedirect.substring(0, length);
+                if (r.startsWith(validRedirect)) return true;
+                // strip off trailing '/'
+                if (length - 1 > 0 && validRedirect.charAt(length - 1) == '/') length--;
+                validRedirect = validRedirect.substring(0, length);
+                if (validRedirect.equals(r)) return true;
+            } else if (validRedirect.equals(redirect)) return true;
+        }
+        return false;
+    }
+
+    private static String relativeToAbsoluteURI(String rootUrl, String relative) {
+        if (rootUrl == null || rootUrl.isEmpty()) {
+            return null;
+        }
+        relative = rootUrl + relative;
+        return relative;
+    }
+
+    public static ProtocolMapperRepresentation getPairwiseSubMapperRepresentation(ClientRepresentation client) {
+        List<ProtocolMapperRepresentation> mappers = client.getProtocolMappers();
+        if (mappers == null) {
+            return null;
+        }
+        for (ProtocolMapperRepresentation mapper : mappers) {
+            if (mapper.getProtocolMapper().endsWith(AbstractPairwiseSubMapper.PROVIDER_ID_SUFFIX)) return mapper;
+        }
+        return null;
+    }
+
+    public static String getSubjectIdentifierUri(ProtocolMapperRepresentation pairwiseMapper) {
+        return pairwiseMapper.getConfig().get(PairwiseSubMapperHelper.SECTOR_IDENTIFIER_URI);
+    }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/PairwiseSubMapperValidator.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/PairwiseSubMapperValidator.java
new file mode 100644
index 0000000..e6d8a6e
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/PairwiseSubMapperValidator.java
@@ -0,0 +1,113 @@
+package org.keycloak.protocol.oidc.utils;
+
+import org.keycloak.connections.httpclient.HttpClientProvider;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.protocol.ProtocolMapperConfigException;
+import org.keycloak.protocol.oidc.mappers.PairwiseSubMapperHelper;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:martin.hardselius@gmail.com">Martin Hardselius</a>
+ */
+public class PairwiseSubMapperValidator {
+
+    public static final String PAIRWISE_MALFORMED_CLIENT_REDIRECT_URI = "pairwiseMalformedClientRedirectURI";
+    public static final String PAIRWISE_CLIENT_REDIRECT_URIS_MISSING_HOST = "pairwiseClientRedirectURIsMissingHost";
+    public static final String PAIRWISE_CLIENT_REDIRECT_URIS_MULTIPLE_HOSTS = "pairwiseClientRedirectURIsMultipleHosts";
+    public static final String PAIRWISE_MALFORMED_SECTOR_IDENTIFIER_URI = "pairwiseMalformedSectorIdentifierURI";
+    public static final String PAIRWISE_FAILED_TO_GET_REDIRECT_URIS = "pairwiseFailedToGetRedirectURIs";
+    public static final String PAIRWISE_REDIRECT_URIS_MISMATCH = "pairwiseRedirectURIsMismatch";
+
+    public static void validate(KeycloakSession session, ClientModel client, ProtocolMapperModel mapperModel) throws ProtocolMapperConfigException {
+        String sectorIdentifierUri = PairwiseSubMapperHelper.getSectorIdentifierUri(mapperModel);
+        String rootUrl = client.getRootUrl();
+        Set<String> redirectUris = client.getRedirectUris();
+        validate(session, rootUrl, redirectUris, sectorIdentifierUri);
+    }
+
+    public static void validate(KeycloakSession session, String rootUrl, Set<String> redirectUris, String sectorIdentifierUri) throws ProtocolMapperConfigException {
+        if (sectorIdentifierUri == null || sectorIdentifierUri.isEmpty()) {
+            validateClientRedirectUris(rootUrl, redirectUris);
+            return;
+        }
+        validateSectorIdentifierUri(sectorIdentifierUri);
+        validateSectorIdentifierUri(session, rootUrl, redirectUris, sectorIdentifierUri);
+    }
+
+    private static void validateClientRedirectUris(String rootUrl, Set<String> redirectUris) throws ProtocolMapperConfigException {
+        Set<String> hosts = new HashSet<>();
+        for (String redirectUri : PairwiseSubMapperUtils.resolveValidRedirectUris(rootUrl, redirectUris)) {
+            try {
+                URI uri = new URI(redirectUri);
+                hosts.add(uri.getHost());
+            } catch (URISyntaxException e) {
+                throw new ProtocolMapperConfigException("Client contained an invalid redirect URI.",
+                        PAIRWISE_MALFORMED_CLIENT_REDIRECT_URI, e);
+            }
+        }
+
+        if (hosts.isEmpty()) {
+            throw new ProtocolMapperConfigException("Client redirect URIs must contain a valid host component.",
+                    PAIRWISE_CLIENT_REDIRECT_URIS_MISSING_HOST);
+        }
+
+        if (hosts.size() > 1) {
+            throw new ProtocolMapperConfigException("Without a configured Sector Identifier URI, client redirect URIs must not contain multiple host components.", PAIRWISE_CLIENT_REDIRECT_URIS_MULTIPLE_HOSTS);
+        }
+    }
+
+    private static void validateSectorIdentifierUri(String sectorIdentifierUri) throws ProtocolMapperConfigException {
+        URI uri;
+        try {
+            uri = new URI(sectorIdentifierUri);
+        } catch (URISyntaxException e) {
+            throw new ProtocolMapperConfigException("Invalid Sector Identifier URI.",
+                    PAIRWISE_MALFORMED_SECTOR_IDENTIFIER_URI, e);
+        }
+        if (uri.getScheme() == null || uri.getHost() == null) {
+            throw new ProtocolMapperConfigException("Invalid Sector Identifier URI.",
+                    PAIRWISE_MALFORMED_SECTOR_IDENTIFIER_URI);
+        }
+    }
+
+    private static void validateSectorIdentifierUri(KeycloakSession session, String rootUrl, Set<String> redirectUris, String sectorIdentifierUri) throws ProtocolMapperConfigException {
+        Set<String> sectorRedirects = getSectorRedirects(session, sectorIdentifierUri);
+        if (!PairwiseSubMapperUtils.matchesRedirects(rootUrl, redirectUris, sectorRedirects)) {
+            throw new ProtocolMapperConfigException("Client redirect URIs does not match redirect URIs fetched from the Sector Identifier URI.",
+                    PAIRWISE_REDIRECT_URIS_MISMATCH);
+        }
+    }
+
+    private static Set<String> getSectorRedirects(KeycloakSession session, String sectorIdentifierUri) throws ProtocolMapperConfigException {
+        InputStream is = null;
+        try {
+            is = session.getProvider(HttpClientProvider.class).get(sectorIdentifierUri);
+            List<String> sectorRedirects = JsonSerialization.readValue(is, TypedList.class);
+            return new HashSet<>(sectorRedirects);
+        } catch (IOException e) {
+            throw new ProtocolMapperConfigException("Failed to get redirect URIs from the Sector Identifier URI.",
+                    PAIRWISE_FAILED_TO_GET_REDIRECT_URIS, e);
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException ignored) {
+                }
+            }
+        }
+    }
+
+    public static class TypedList extends ArrayList<String> {}
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/SubjectType.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/SubjectType.java
new file mode 100644
index 0000000..ec1ba97
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/SubjectType.java
@@ -0,0 +1,13 @@
+package org.keycloak.protocol.oidc.utils;
+
+public enum SubjectType {
+    PUBLIC,
+    PAIRWISE;
+
+    public static SubjectType parse(String subjectTypeStr) {
+        if (subjectTypeStr == null) {
+            return PUBLIC;
+        }
+        return Enum.valueOf(SubjectType.class, subjectTypeStr.toUpperCase());
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java b/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java
index d634b00..f5ad8b0 100755
--- a/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java
@@ -19,22 +19,22 @@ package org.keycloak.services.clientregistration;
 
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
-import org.keycloak.models.ClientInitialAccessModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientRegistrationTrustedHostModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.*;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
+import org.keycloak.protocol.oidc.mappers.AbstractPairwiseSubMapper;
+import org.keycloak.protocol.oidc.mappers.PairwiseSubMapperHelper;
+import org.keycloak.protocol.oidc.mappers.SHA265PairwiseSubMapper;
+import org.keycloak.protocol.oidc.utils.SubjectType;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.ForbiddenException;
-import org.keycloak.services.resources.admin.AdminRoot;
 import org.keycloak.services.validation.ClientValidator;
+import org.keycloak.services.validation.PairwiseClientValidator;
 import org.keycloak.services.validation.ValidationMessages;
 
 import javax.ws.rs.core.Response;
-import java.util.Properties;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -55,7 +55,7 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
         auth.requireCreate();
 
         ValidationMessages validationMessages = new ValidationMessages();
-        if (!ClientValidator.validate(client, validationMessages)) {
+        if (!ClientValidator.validate(client, validationMessages) || !PairwiseClientValidator.validate(session, client, validationMessages)) {
             String errorCode = validationMessages.fieldHasError("redirectUris") ? ErrorCodes.INVALID_REDIRECT_URI : ErrorCodes.INVALID_CLIENT_METADATA;
             throw new ErrorResponseException(
                     errorCode,
@@ -66,6 +66,10 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
 
         try {
             ClientModel clientModel = RepresentationToModel.createClient(session, session.getContext().getRealm(), client, true);
+            OIDCAdvancedConfigWrapper configWrapper = OIDCAdvancedConfigWrapper.fromClientRepresentation(client);
+            if (configWrapper.getSubjectType().equals(SubjectType.PAIRWISE)) {
+                addPairwiseSubMapper(clientModel, configWrapper.getSectorIdentifierUri());
+            }
 
             client = ModelToRepresentation.toRepresentation(clientModel);
 
@@ -119,7 +123,7 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
         }
 
         ValidationMessages validationMessages = new ValidationMessages();
-        if (!ClientValidator.validate(rep, validationMessages)) {
+        if (!ClientValidator.validate(rep, validationMessages) || !PairwiseClientValidator.validate(session, rep, validationMessages)) {
             String errorCode = validationMessages.fieldHasError("redirectUris") ? ErrorCodes.INVALID_REDIRECT_URI : ErrorCodes.INVALID_CLIENT_METADATA;
             throw new ErrorResponseException(
                     errorCode,
@@ -128,6 +132,7 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
             );
         }
 
+        updateSubjectType(rep, client);
         RepresentationToModel.updateClient(rep, client);
         rep = ModelToRepresentation.toRepresentation(client);
 
@@ -140,6 +145,43 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
         return rep;
     }
 
+    private void updateSubjectType(ClientRepresentation rep, ClientModel client) {
+        OIDCAdvancedConfigWrapper repConfigWrapper = OIDCAdvancedConfigWrapper.fromClientRepresentation(rep);
+        SubjectType repSubjectType = repConfigWrapper.getSubjectType();
+        OIDCAdvancedConfigWrapper clientConfigWrapper = OIDCAdvancedConfigWrapper.fromClientModel(client);
+        SubjectType clientSubjectType = clientConfigWrapper.getSubjectType();
+
+        if (repSubjectType.equals(SubjectType.PAIRWISE) && clientSubjectType.equals(SubjectType.PAIRWISE)) {
+            updateSectorIdentifier(client, repConfigWrapper.getSectorIdentifierUri());
+        }
+
+        if (repSubjectType.equals(SubjectType.PAIRWISE) && clientSubjectType.equals(SubjectType.PUBLIC)) {
+            addPairwiseSubMapper(client, repConfigWrapper.getSectorIdentifierUri());
+        }
+
+        if (repSubjectType.equals(SubjectType.PUBLIC) && clientSubjectType.equals(SubjectType.PAIRWISE)) {
+            removePairwiseSubMapper(client);
+        }
+    }
+
+    private void updateSectorIdentifier(ClientModel client, String sectorIdentifierUri) {
+        client.getProtocolMappers().stream().filter(mapping -> mapping.getProtocolMapper().endsWith(AbstractPairwiseSubMapper.PROVIDER_ID_SUFFIX)).forEach(mapping -> {
+            mapping.getConfig().put(PairwiseSubMapperHelper.SECTOR_IDENTIFIER_URI, sectorIdentifierUri);
+        });
+    }
+
+    private void addPairwiseSubMapper(ClientModel client, String sectorIdentifierUri) {
+        client.addProtocolMapper(SHA265PairwiseSubMapper.createPairwiseMapper(sectorIdentifierUri));
+    }
+
+    private void removePairwiseSubMapper(ClientModel client) {
+        for (ProtocolMapperModel mapping : client.getProtocolMappers()) {
+            if (mapping.getProtocolMapper().endsWith(AbstractPairwiseSubMapper.PROVIDER_ID_SUFFIX)) {
+                client.removeProtocolMapper(mapping);
+            }
+        }
+    }
+
     public void delete(String clientId) {
         event.event(EventType.CLIENT_DELETE).client(clientId);
 
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java b/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java
index e1939ef..c377313 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java
@@ -32,6 +32,7 @@ import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
 import org.keycloak.protocol.oidc.utils.JWKSUtils;
 import org.keycloak.protocol.oidc.utils.OIDCResponseType;
+import org.keycloak.protocol.oidc.utils.SubjectType;
 import org.keycloak.representations.idm.CertificateRepresentation;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.oidc.OIDCClientRepresentation;
@@ -53,6 +54,7 @@ public class DescriptionConverter {
 
     public static ClientRepresentation toInternal(KeycloakSession session, OIDCClientRepresentation clientOIDC) throws ClientRegistrationException {
         ClientRepresentation client = new ClientRepresentation();
+
         client.setClientId(clientOIDC.getClientId());
         client.setName(clientOIDC.getClientName());
         client.setRedirectUris(clientOIDC.getRedirectUris());
@@ -113,6 +115,12 @@ public class DescriptionConverter {
             configWrapper.setRequestObjectSignatureAlg(algorithm);
         }
 
+        SubjectType subjectType = SubjectType.parse(clientOIDC.getSubjectType());
+        configWrapper.setSubjectType(subjectType);
+        if (subjectType.equals(SubjectType.PAIRWISE)) {
+            configWrapper.setSectorIdentifierUri(clientOIDC.getSectorIdentifierUri());
+        }
+
         return client;
     }
 
@@ -172,6 +180,11 @@ public class DescriptionConverter {
             response.setRequestObjectSigningAlg(config.getRequestObjectSignatureAlg().toString());
         }
 
+        response.setSubjectType(config.getSubjectType().toString().toLowerCase());
+        if (config.getSubjectType().equals(SubjectType.PAIRWISE)) {
+            response.setSectorIdentifierUri(config.getSectorIdentifierUri());
+        }
+
         return response;
     }
 
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
index d5474dc..36f9b7f 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
@@ -20,6 +20,7 @@ import org.keycloak.Config;
 import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.EnvironmentDependentProviderFactory;
 import org.keycloak.provider.Provider;
 import org.keycloak.provider.ProviderEvent;
 import org.keycloak.provider.ProviderEventListener;
@@ -190,8 +191,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
                 }
 
                 Config.Scope scope = Config.scope(spi.getName(), provider);
-                if (scope.getBoolean("enabled", true)) {
-
+                if (isEnabled(factory, scope)) {
                     factory.init(scope);
 
                     if (spi.isInternal() && !isInternal(factory)) {
@@ -202,10 +202,11 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
 
                     logger.debugv("Loaded SPI {0} (provider = {1})", spi.getName(), provider);
                 }
+
             } else {
                 for (ProviderFactory factory : pm.load(spi)) {
                     Config.Scope scope = Config.scope(spi.getName(), factory.getId());
-                    if (scope.getBoolean("enabled", true)) {
+                    if (isEnabled(factory, scope)) {
                         factory.init(scope);
 
                         if (spi.isInternal() && !isInternal(factory)) {
@@ -220,7 +221,16 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
             }
         }
         return factoryMap;
+    }
 
+    private boolean isEnabled(ProviderFactory factory, Config.Scope scope) {
+        if (!scope.getBoolean("enabled", true)) {
+            return false;
+        }
+        if (factory instanceof EnvironmentDependentProviderFactory) {
+            return ((EnvironmentDependentProviderFactory) factory).isSupported();
+        }
+        return true;
     }
 
     protected void loadSPIs(ProviderManager pm, List<Spi> spiList) {
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index e53ac00..aa536f5 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -408,7 +408,7 @@ public class AuthenticationManager {
         // refresh the cookies!
         createLoginCookie(session, realm, userSession.getUser(), userSession, uriInfo, clientConnection);
         if (userSession.getState() != UserSessionModel.State.LOGGED_IN) userSession.setState(UserSessionModel.State.LOGGED_IN);
-        if (userSession.isRememberMe()) createRememberMeCookie(realm, userSession.getUser().getUsername(), uriInfo, clientConnection);
+        if (userSession.isRememberMe()) createRememberMeCookie(realm, userSession.getLoginUsername(), uriInfo, clientConnection);
 
         // Update userSession note with authTime. But just if flag SSO_AUTH is not set
         if (!isSSOAuthentication(clientSession)) {
diff --git a/services/src/main/java/org/keycloak/services/managers/ClientManager.java b/services/src/main/java/org/keycloak/services/managers/ClientManager.java
index 7bdf5b1..3de62db 100644
--- a/services/src/main/java/org/keycloak/services/managers/ClientManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ClientManager.java
@@ -265,7 +265,6 @@ public class ClientManager {
         InstallationAdapterConfig rep = new InstallationAdapterConfig();
         rep.setAuthServerUrl(baseUri.toString());
         rep.setRealm(realmModel.getName());
-        rep.setRealmKey(realmModel.getPublicKeyPem());
         rep.setSslRequired(realmModel.getSslRequired().name().toLowerCase());
 
         if (clientModel.isPublicClient() && !clientModel.isBearerOnly()) rep.setPublicClient(true);
@@ -286,7 +285,6 @@ public class ClientManager {
         StringBuffer buffer = new StringBuffer();
         buffer.append("<secure-deployment name=\"WAR MODULE NAME.war\">\n");
         buffer.append("    <realm>").append(realmModel.getName()).append("</realm>\n");
-        buffer.append("    <realm-public-key>").append(realmModel.getPublicKeyPem()).append("</realm-public-key>\n");
         buffer.append("    <auth-server-url>").append(baseUri.toString()).append("</auth-server-url>\n");
         if (clientModel.isBearerOnly()){
             buffer.append("    <bearer-only>true</bearer-only>\n");
diff --git a/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java b/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java
index 28fc29d..67d3dc9 100644
--- a/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java
+++ b/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java
@@ -18,6 +18,7 @@ package org.keycloak.services.managers;
 
 
 import org.keycloak.common.ClientConnection;
+import org.keycloak.common.util.Time;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel;
@@ -52,6 +53,18 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
     protected LinkedBlockingQueue<LoginEvent> queue = new LinkedBlockingQueue<LoginEvent>();
     public static final int TRANSACTION_SIZE = 20;
 
+    public static volatile int markNotBefore = -1;
+    public static volatile int markCheck = -1;
+    public static volatile int testCount = 0;
+    public static volatile int clearCount = 0;
+    public static volatile int nullFailureCount = 0;
+    public static volatile int logFailureCalled = 0;
+    public static volatile int logFailure = 0;
+    public static volatile int didntWait = 0;
+    public static volatile int exception = 0;
+    public static volatile Exception exceptionObject = null;
+    public static volatile String notFoundUserId = null;
+
 
     protected abstract class LoginEvent implements Comparable<LoginEvent> {
         protected final String realmId;
@@ -90,16 +103,20 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
 
     public void failure(KeycloakSession session, LoginEvent event) {
         logger.debug("failure");
+        logFailureCalled++;
         RealmModel realm = getRealmModel(session, event);
         logFailure(event);
-        UserModel user = session.users().getUserById(event.userId, realm);
+
+        String userId = event.userId;
+        UserModel user = session.users().getUserById(userId, realm);
         UserLoginFailureModel userLoginFailure = getUserModel(session, event);
         if (user != null) {
+            logFailure++;
             if (userLoginFailure == null) {
-                userLoginFailure = session.sessions().addUserLoginFailure(realm, event.userId);
+                userLoginFailure = session.sessions().addUserLoginFailure(realm, userId);
             }
             userLoginFailure.setLastIPFailure(event.ip);
-            long currentTime = System.currentTimeMillis();
+            long currentTime = Time.currentTimeMillis();
             long last = userLoginFailure.getLastFailure();
             long deltaTime = 0;
             if (last > 0) {
@@ -109,13 +126,14 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
             if (deltaTime > 0) {
                 // if last failure was more than MAX_DELTA clear failures
                 if (deltaTime > (long) realm.getMaxDeltaTimeSeconds() * 1000L) {
+                    clearCount++;
                     userLoginFailure.clearFailures();
                 }
             }
             userLoginFailure.incrementFailures();
             logger.debugv("new num failures: {0}", userLoginFailure.getNumFailures());
 
-            int waitSeconds = realm.getWaitIncrementSeconds() * (userLoginFailure.getNumFailures() / realm.getFailureFactor());
+            int waitSeconds = realm.getWaitIncrementSeconds() *  (userLoginFailure.getNumFailures() / realm.getFailureFactor());
             logger.debugv("waitSeconds: {0}", waitSeconds);
             logger.debugv("deltaTime: {0}", deltaTime);
 
@@ -129,8 +147,12 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
                 waitSeconds = Math.min(realm.getMaxFailureWaitSeconds(), waitSeconds);
                 int notBefore = (int) (currentTime / 1000) + waitSeconds;
                 logger.debugv("set notBefore: {0}", notBefore);
+                markNotBefore = notBefore;
                 userLoginFailure.setFailedLoginNotBefore(notBefore);
             }
+        } else {
+            notFoundUserId = event.userId;
+
         }
     }
 
@@ -188,6 +210,8 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
                             }
                             session.getTransactionManager().commit();
                         } catch (Exception e) {
+                            exception++;
+                            exceptionObject = e;
                             session.getTransactionManager().rollback();
                             throw e;
                         } finally {
@@ -216,7 +240,7 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
         failures++;
         long delta = 0;
         if (lastFailure > 0) {
-            delta = System.currentTimeMillis() - lastFailure;
+            delta = Time.currentTimeMillis() - lastFailure;
             if (delta > (long)maxDeltaTimeSeconds * 1000L) {
                 totalTime = 0;
 
@@ -234,10 +258,15 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
             // wait a minimum of seconds for type to process so that a hacker
             // cannot flood with failed logins and overwhelm the queue and not have notBefore updated to block next requests
             // todo failure HTTP responses should be queued via async HTTP
-            event.latch.await(5, TimeUnit.SECONDS);
-
+            boolean awaited =
+                    event.latch.await(5, TimeUnit.SECONDS);
+            if (!awaited) {
+                    didntWait++;
+            }
         } catch (InterruptedException e) {
+            didntWait++;
         }
+        logger.trace("sent failure event");
     }
 
     @Override
@@ -245,16 +274,24 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
         UserLoginFailureModel failure = session.sessions().getUserLoginFailure(realm, user.getId());
 
         if (failure != null) {
-            int currTime = (int) (System.currentTimeMillis() / 1000);
-            if (currTime < failure.getFailedLoginNotBefore()) {
-                logger.debugv("Current: {0} notBefore: {1}", currTime, failure.getFailedLoginNotBefore());
+            int currTime = markCheck = (int) (Time.currentTimeMillis() / 1000);
+            int failedLoginNotBefore = failure.getFailedLoginNotBefore();
+            testCount++;
+            if (currTime < failedLoginNotBefore) {
+                logger.debugv("Current: {0} notBefore: {1}", currTime, failedLoginNotBefore);
                 return true;
+            } else if (failedLoginNotBefore > 0){
+                logger.debugv("failedLoginNotBefore > 0 Current: {0} notBefore: {1}", currTime, failedLoginNotBefore);
             }
+        } else {
+            logger.debugv("failure was null");
+            nullFailureCount++;
+
         }
 
+
         return false;
     }
-
     @Override
     public void close() {
 
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index c3f099c..36f643f 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -273,7 +273,7 @@ public class AccountService extends AbstractSecuredLocalService {
         } else if (types.contains(MediaType.APPLICATION_JSON_TYPE)) {
             requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
 
-            UserRepresentation rep = ModelToRepresentation.toRepresentation(auth.getUser());
+            UserRepresentation rep = ModelToRepresentation.toRepresentation(session, realm, auth.getUser());
             if (rep.getAttributes() != null) {
                 Iterator<String> itr = rep.getAttributes().keySet().iterator();
                 while (itr.hasNext()) {
@@ -569,8 +569,6 @@ public class AccountService extends AbstractSecuredLocalService {
         credentials.setValue(totpSecret);
         session.userCredentialManager().updateCredential(realm, user, credentials);
 
-        user.setOtpEnabled(true);
-
         // to update counter
         UserCredentialModel cred = new UserCredentialModel();
         cred.setType(realm.getOTPPolicy().getType());
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
index 9b6593f..5095c39 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
@@ -18,9 +18,9 @@ package org.keycloak.services.resources.admin;
 
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.BadRequestException;
-import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.authorization.admin.AuthorizationService;
+import org.keycloak.common.Profile;
 import org.keycloak.events.admin.OperationType;
 import org.keycloak.events.admin.ResourceType;
 import org.keycloak.models.ClientModel;
@@ -50,11 +50,14 @@ import org.keycloak.services.resources.KeycloakApplication;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.common.util.Time;
 import org.keycloak.services.validation.ClientValidator;
+import org.keycloak.services.validation.PairwiseClientValidator;
 import org.keycloak.services.validation.ValidationMessages;
+import org.keycloak.utils.ProfileHelper;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
+import javax.ws.rs.NotFoundException;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
@@ -127,7 +130,7 @@ public class ClientResource {
         }
 
         ValidationMessages validationMessages = new ValidationMessages();
-        if (!ClientValidator.validate(rep, validationMessages)) {
+        if (!ClientValidator.validate(rep, validationMessages) || !PairwiseClientValidator.validate(session, rep, validationMessages)) {
             Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
             throw new ErrorResponseException(
                     validationMessages.getStringMessages(),
@@ -152,10 +155,12 @@ public class ClientResource {
 
         RepresentationToModel.updateClient(rep, client);
 
-        if (TRUE.equals(rep.getAuthorizationServicesEnabled())) {
-            authorization().enable();
-        } else {
-            authorization().disable();
+        if (Profile.isPreviewEnabled()) {
+            if (TRUE.equals(rep.getAuthorizationServicesEnabled())) {
+                authorization().enable();
+            } else {
+                authorization().disable();
+            }
         }
     }
 
@@ -176,7 +181,9 @@ public class ClientResource {
 
         ClientRepresentation representation = ModelToRepresentation.toRepresentation(client);
 
-        representation.setAuthorizationServicesEnabled(authorization().isEnabled());
+        if (Profile.isPreviewEnabled()) {
+            representation.setAuthorizationServicesEnabled(authorization().isEnabled());
+        }
 
         return representation;
     }
@@ -336,7 +343,7 @@ public class ClientResource {
             }
         }
 
-        return ModelToRepresentation.toRepresentation(user);
+        return ModelToRepresentation.toRepresentation(session, realm, user);
     }
 
     /**
@@ -561,6 +568,8 @@ public class ClientResource {
 
     @Path("/authz")
     public AuthorizationService authorization() {
+        ProfileHelper.requirePreview();
+
         AuthorizationService resource = new AuthorizationService(this.session, this.client, this.auth);
 
         ResteasyProviderFactory.getInstance().injectProperties(resource);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
index dacea26..1be0cac 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
@@ -31,6 +31,7 @@ import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.ClientManager;
 import org.keycloak.services.validation.ClientValidator;
+import org.keycloak.services.validation.PairwiseClientValidator;
 import org.keycloak.services.validation.ValidationMessages;
 
 import javax.ws.rs.*;
@@ -120,7 +121,7 @@ public class ClientsResource {
         auth.requireManage();
 
         ValidationMessages validationMessages = new ValidationMessages();
-        if (!ClientValidator.validate(rep, validationMessages)) {
+        if (!ClientValidator.validate(rep, validationMessages) || !PairwiseClientValidator.validate(session, rep, validationMessages)) {
             Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
             throw new ErrorResponseException(
                     validationMessages.getStringMessages(),
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java b/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
index e3cc87f..11cb567 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
@@ -218,7 +218,7 @@ public class GroupResource {
         List<UserModel> userModels = session.users().getGroupMembers(realm, group, firstResult, maxResults);
 
         for (UserModel user : userModels) {
-            results.add(ModelToRepresentation.toRepresentation(user));
+            results.add(ModelToRepresentation.toRepresentation(session, realm, user));
         }
         return results;
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
index a7195e1..638e657 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
@@ -43,6 +43,7 @@ import org.keycloak.policy.PasswordPolicyProviderFactory;
 import org.keycloak.provider.*;
 import org.keycloak.representations.idm.ComponentTypeRepresentation;
 import org.keycloak.representations.idm.PasswordPolicyTypeRepresentation;
+import org.keycloak.representations.info.ProfileInfoRepresentation;
 import org.keycloak.theme.Theme;
 import org.keycloak.theme.ThemeProvider;
 import org.keycloak.models.KeycloakSession;
@@ -84,6 +85,7 @@ public class ServerInfoAdminResource {
         ServerInfoRepresentation info = new ServerInfoRepresentation();
         info.setSystemInfo(SystemInfoRepresentation.create(session.getKeycloakSessionFactory().getServerStartupTimestamp()));
         info.setMemoryInfo(MemoryInfoRepresentation.create());
+        info.setProfileInfo(ProfileInfoRepresentation.create());
 
         setSocialProviders(info);
         setIdentityProviders(info);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
index 86dcefc..8040820 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
@@ -20,15 +20,7 @@ import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.events.admin.OperationType;
 import org.keycloak.events.admin.ResourceType;
-import org.keycloak.mappers.FederationConfigValidationException;
-import org.keycloak.mappers.UserFederationMapper;
-import org.keycloak.mappers.UserFederationMapperFactory;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ProtocolMapperContainerModel;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.*;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.protocol.ProtocolMapper;
@@ -39,19 +31,11 @@ import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.resources.admin.RealmAuth.Resource;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import javax.ws.rs.*;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
-
 import java.text.MessageFormat;
 import java.util.LinkedList;
 import java.util.List;
@@ -269,7 +253,7 @@ public class ProtocolMappersResource {
         } catch (ProtocolMapperConfigException ex) {
             logger.error(ex.getMessage());
             Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
-            throw new ErrorResponseException(ex.getMessage(), MessageFormat.format(messages.getProperty(ex.getMessage(), ex.getMessage()), ex.getParameters()),
+            throw new ErrorResponseException(ex.getMessage(), MessageFormat.format(messages.getProperty(ex.getMessageKey(), ex.getMessage()), ex.getParameters()),
                     Response.Status.BAD_REQUEST);
         }
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 7d49223..1caa5fb 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -35,6 +35,7 @@ import org.keycloak.events.admin.ResourceType;
 import org.keycloak.exportimport.ClientDescriptionConverter;
 import org.keycloak.exportimport.ClientDescriptionConverterFactory;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
 import org.keycloak.models.GroupModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
@@ -281,7 +282,7 @@ public class RealmAdminResource {
 
         logger.debug("updating realm: " + realm.getName());
         try {
-            if (!"GENERATE".equals(rep.getPublicKey()) && (rep.getPrivateKey() != null && rep.getPublicKey() != null)) {
+            if (!Constants.GENERATE.equals(rep.getPublicKey()) && (rep.getPrivateKey() != null && rep.getPublicKey() != null)) {
                 try {
                     KeyPairVerifier.verify(rep.getPrivateKey(), rep.getPublicKey());
                 } catch (VerificationException e) {
@@ -289,7 +290,7 @@ public class RealmAdminResource {
                 }
             }
 
-            if (!"GENERATE".equals(rep.getPublicKey()) && (rep.getCertificate() != null)) {
+            if (!Constants.GENERATE.equals(rep.getPublicKey()) && (rep.getCertificate() != null)) {
                 try {
                     X509Certificate cert = PemUtils.decodeCertificate(rep.getCertificate());
                     if (cert == null) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index 47daa76..4b13659 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -246,7 +246,6 @@ public class UsersResource {
         if (rep.getLastName() != null) user.setLastName(rep.getLastName());
 
         if (rep.isEnabled() != null) user.setEnabled(rep.isEnabled());
-        if (rep.isTotp() != null) user.setOtpEnabled(rep.isTotp());
         if (rep.isEmailVerified() != null) user.setEmailVerified(rep.isEmailVerified());
 
         List<String> reqActions = rep.getRequiredActions();
@@ -294,7 +293,7 @@ public class UsersResource {
             throw new NotFoundException("User not found");
         }
 
-        UserRepresentation rep = ModelToRepresentation.toRepresentation(user);
+        UserRepresentation rep = ModelToRepresentation.toRepresentation(session, realm, user);
 
         if (realm.isIdentityFederationEnabled()) {
             List<FederatedIdentityRepresentation> reps = getFederatedIdentities(user);
@@ -693,7 +692,7 @@ public class UsersResource {
         }
 
         for (UserModel user : userModels) {
-            results.add(ModelToRepresentation.toRepresentation(user));
+            results.add(ModelToRepresentation.toRepresentation(session, realm, user));
         }
         return results;
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index 1e42e7b..d0ca449 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -35,6 +35,7 @@ import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resource.RealmResourceProvider;
 import org.keycloak.services.util.CacheControlUtil;
 import org.keycloak.services.util.ResolveRelative;
+import org.keycloak.utils.ProfileHelper;
 import org.keycloak.wellknown.WellKnownProvider;
 
 import javax.ws.rs.GET;
@@ -254,6 +255,8 @@ public class RealmsResource {
 
     @Path("{realm}/authz")
     public Object getAuthorizationService(@PathParam("realm") String name) {
+        ProfileHelper.requirePreview();
+
         init(name);
         AuthorizationProvider authorization = this.session.getProvider(AuthorizationProvider.class);
         AuthorizationService service = new AuthorizationService(authorization);
diff --git a/services/src/main/java/org/keycloak/services/ServicesLogger.java b/services/src/main/java/org/keycloak/services/ServicesLogger.java
index c6094c4..0d58f2d 100644
--- a/services/src/main/java/org/keycloak/services/ServicesLogger.java
+++ b/services/src/main/java/org/keycloak/services/ServicesLogger.java
@@ -434,4 +434,8 @@ public interface ServicesLogger extends BasicLogger {
     @Message(id=97, value="Invalid request")
     void invalidRequest(@Cause Throwable t);
 
+    @LogMessage(level = ERROR)
+    @Message(id=98, value="Failed to get redirect uris from sector identifier URI: %s")
+    void failedToGetRedirectUrisFromSectorIdentifierUri(@Cause Throwable t, String sectorIdentifierUri);
+
 }
diff --git a/services/src/main/java/org/keycloak/services/validation/PairwiseClientValidator.java b/services/src/main/java/org/keycloak/services/validation/PairwiseClientValidator.java
new file mode 100644
index 0000000..6cc2033
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/validation/PairwiseClientValidator.java
@@ -0,0 +1,41 @@
+package org.keycloak.services.validation;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.protocol.ProtocolMapperConfigException;
+import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
+import org.keycloak.protocol.oidc.utils.PairwiseSubMapperValidator;
+import org.keycloak.protocol.oidc.utils.SubjectType;
+import org.keycloak.representations.idm.ClientRepresentation;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+/**
+ * @author <a href="mailto:martin.hardselius@gmail.com">Martin Hardselius</a>
+ */
+public class PairwiseClientValidator {
+
+    public static boolean validate(KeycloakSession session, ClientRepresentation client, ValidationMessages messages) {
+        OIDCAdvancedConfigWrapper configWrapper = OIDCAdvancedConfigWrapper.fromClientRepresentation(client);
+        if (configWrapper.getSubjectType().equals(SubjectType.PAIRWISE)) {
+            String sectorIdentifierUri = configWrapper.getSectorIdentifierUri();
+            String rootUrl = client.getRootUrl();
+            Set<String> redirectUris = new HashSet<>();
+            if (client.getRedirectUris() != null) redirectUris.addAll(client.getRedirectUris());
+            return validate(session, rootUrl, redirectUris, sectorIdentifierUri, messages);
+        }
+        return true;
+    }
+
+    public static boolean validate(KeycloakSession session, String rootUrl, Set<String> redirectUris, String sectorIdentifierUri, ValidationMessages messages) {
+        try {
+            PairwiseSubMapperValidator.validate(session, rootUrl, redirectUris, sectorIdentifierUri);
+        } catch (ProtocolMapperConfigException e) {
+            messages.add(e.getMessage(), e.getMessageKey());
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/validation/ValidationMessages.java b/services/src/main/java/org/keycloak/services/validation/ValidationMessages.java
index e26ebff..a7e82c8 100644
--- a/services/src/main/java/org/keycloak/services/validation/ValidationMessages.java
+++ b/services/src/main/java/org/keycloak/services/validation/ValidationMessages.java
@@ -57,8 +57,11 @@ public class ValidationMessages {
     }
 
     public boolean fieldHasError(String fieldId) {
+        if (fieldId == null) {
+            return false;
+        }
         for (ValidationMessage message : messages) {
-            if (message.getFieldId().equals(fieldId)) {
+            if (fieldId.equals(message.getFieldId())) {
                 return true;
             }
         }
diff --git a/services/src/main/java/org/keycloak/utils/ProfileHelper.java b/services/src/main/java/org/keycloak/utils/ProfileHelper.java
new file mode 100644
index 0000000..719bd24
--- /dev/null
+++ b/services/src/main/java/org/keycloak/utils/ProfileHelper.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.utils;
+
+import org.keycloak.common.Profile;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ProfileHelper {
+
+    public static void requirePreview() {
+        if (!Profile.isPreviewEnabled()) {
+            throw new WebApplicationException("Feature not available in current profile", Response.Status.NOT_IMPLEMENTED);
+        }
+    }
+
+}
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory b/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
index 97c9299..fa7ee28 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
+++ b/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
@@ -20,6 +20,7 @@ org.keycloak.authentication.authenticators.browser.UsernamePasswordFormFactory
 org.keycloak.authentication.authenticators.browser.OTPFormAuthenticatorFactory
 org.keycloak.authentication.authenticators.browser.ScriptBasedAuthenticatorFactory
 org.keycloak.authentication.authenticators.browser.SpnegoAuthenticatorFactory
+org.keycloak.authentication.authenticators.browser.IdentityProviderAuthenticatorFactory
 org.keycloak.authentication.authenticators.directgrant.ValidateOTP
 org.keycloak.authentication.authenticators.directgrant.ValidatePassword
 org.keycloak.authentication.authenticators.directgrant.ValidateUsername
@@ -33,4 +34,4 @@ org.keycloak.authentication.authenticators.broker.IdpConfirmLinkAuthenticatorFac
 org.keycloak.authentication.authenticators.broker.IdpEmailVerificationAuthenticatorFactory
 org.keycloak.authentication.authenticators.broker.IdpUsernamePasswordFormFactory
 org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticatorFactory
-org.keycloak.protocol.saml.profile.ecp.authenticator.HttpBasicAuthenticator
+org.keycloak.protocol.saml.profile.ecp.authenticator.HttpBasicAuthenticator
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper b/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
index 9d1e10e..77830dc 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
+++ b/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
@@ -34,5 +34,5 @@ org.keycloak.protocol.saml.mappers.UserSessionNoteStatementMapper
 org.keycloak.protocol.saml.mappers.GroupMembershipMapper
 org.keycloak.protocol.oidc.mappers.UserClientRoleMappingMapper
 org.keycloak.protocol.oidc.mappers.UserRealmRoleMappingMapper
-
+org.keycloak.protocol.oidc.mappers.SHA265PairwiseSubMapper
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
index 7c1f47b..36c291f 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
@@ -20,19 +20,19 @@ package org.keycloak.testsuite.broker;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
+import org.keycloak.admin.client.resource.RealmResource;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation;
 import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.KeycloakServer;
 import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.pages.OAuthGrantPage;
 import org.keycloak.testsuite.rule.AbstractKeycloakRule;
 import org.keycloak.testsuite.rule.WebResource;
 import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.testsuite.KeycloakServer;
-import org.openqa.selenium.By;
 import org.openqa.selenium.WebDriver;
 
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -94,6 +94,16 @@ public class IdentityProviderHintTest {
 
         assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
 
-        assertEquals("Could not find an identity provider with the identifier.", this.driver.findElement(By.className("instruction")).getText());
+        System.out.println(driver.getPageSource());
+        assertTrue(driver.getTitle().equals("Log in to realm-with-broker"));
+    }
+
+    private AuthenticationExecutionInfoRepresentation findExecution(RealmResource realm) {
+            for (AuthenticationExecutionInfoRepresentation e : realm.flows().getExecutions("browser")) {
+                if (e.getProviderId().equals("identity-provider-redirector")) {
+                    return e;
+                }
+            }
+        return null;
     }
 }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
index 8315331..7462a28 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
@@ -89,7 +89,7 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
         try {
             RealmModel realmByName = session.realms().getRealmByName(realm);
             UserModel user = session.users().getUserByUsername(name, realmByName);
-            UserRepresentation userRep = user != null ? ModelToRepresentation.toRepresentation(user) : null;
+            UserRepresentation userRep = user != null ? ModelToRepresentation.toRepresentation(session, realmByName, user) : null;
             session.getTransactionManager().commit();
             return userRep;
         } finally {
@@ -102,7 +102,7 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
         session.getTransactionManager().begin();
         try {
             RealmModel realmByName = session.realms().getRealmByName(realm);
-            UserRepresentation userRep = ModelToRepresentation.toRepresentation(session.users().getUserById(id, realmByName));
+            UserRepresentation userRep = ModelToRepresentation.toRepresentation(session, realmByName, session.users().getUserById(id, realmByName));
             session.getTransactionManager().commit();
             return userRep;
         } finally {
diff --git a/testsuite/integration/src/test/resources/log4j.properties b/testsuite/integration/src/test/resources/log4j.properties
index 5d5369c..f0ff6ac 100755
--- a/testsuite/integration/src/test/resources/log4j.properties
+++ b/testsuite/integration/src/test/resources/log4j.properties
@@ -74,4 +74,7 @@ log4j.logger.org.apache.directory.server.core=warn
 log4j.logger.org.apache.directory.server.ldap.LdapProtocolHandler=error
 
 # Enable to view HttpClient connection pool activity
-#log4j.logger.org.apache.http.impl.conn=debug
\ No newline at end of file
+#log4j.logger.org.apache.http.impl.conn=debug
+
+# Enable to view details from identity provider authenticator
+# log4j.logger.org.keycloak.authentication.authenticators.browser.IdentityProviderAuthenticator=trace
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource.xsl b/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource.xsl
index 37ce56f..bf199cb 100644
--- a/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource.xsl
+++ b/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource.xsl
@@ -43,7 +43,7 @@
     <xsl:param name="pool.prefill" select="'true'"/>
     
     <xsl:variable name="newDatasourceDefinition">
-        <datasource jndi-name="java:jboss/datasources/KeycloakDS" jta="false" pool-name="KeycloakDS" use-java-context="true">
+        <datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" use-java-context="true">
             <connection-url>
                 <xsl:value-of select="$jdbc.url"/>
             </connection-url>
diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/common/keycloak-server-subsystem.xsl b/testsuite/integration-arquillian/servers/auth-server/jboss/common/keycloak-server-subsystem.xsl
index 664eecb..d104e37 100644
--- a/testsuite/integration-arquillian/servers/auth-server/jboss/common/keycloak-server-subsystem.xsl
+++ b/testsuite/integration-arquillian/servers/auth-server/jboss/common/keycloak-server-subsystem.xsl
@@ -42,8 +42,8 @@
         </modules>
     </xsl:variable>
     
-    <!--inject provider-->
-    <xsl:template match="//*[local-name()='providers']/*[local-name()='provider']">
+    <!--inject provider; note: due to ibmjdk issues it tries to find out provider which has no attributes-->
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $nsKS)]//*[local-name()='provider' and not(@*)]">
         <xsl:copy>
             <xsl:apply-templates select="@*|node()" />
         </xsl:copy>
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestingOIDCEndpointsApplicationResource.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestingOIDCEndpointsApplicationResource.java
index 6ea488f..8b5df6c 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestingOIDCEndpointsApplicationResource.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestingOIDCEndpointsApplicationResource.java
@@ -17,19 +17,6 @@
 
 package org.keycloak.testsuite.rest.resource;
 
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.keycloak.OAuth2Constants;
@@ -42,6 +29,19 @@ import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.testsuite.rest.TestApplicationResourceProviderFactory;
 
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
@@ -134,4 +134,19 @@ public class TestingOIDCEndpointsApplicationResource {
     public String getOIDCRequest() {
         return clientData.getOidcRequest();
     }
+
+    @GET
+    @Path("/set-sector-identifier-redirect-uris")
+    @Produces(MediaType.APPLICATION_JSON)
+    public void setSectorIdentifierRedirectUris(@QueryParam("redirectUris") List<String> redirectUris) {
+        clientData.setSectorIdentifierRedirectUris(new ArrayList<>());
+        clientData.getSectorIdentifierRedirectUris().addAll(redirectUris);
+    }
+
+    @GET
+    @Path("/get-sector-identifier-redirect-uris")
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<String> getSectorIdentifierRedirectUris() {
+        return clientData.getSectorIdentifierRedirectUris();
+    }
 }
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java
index 6bd7dc2..d8d2a8d 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java
@@ -18,10 +18,8 @@
 package org.keycloak.testsuite.rest;
 
 import org.keycloak.Config.Scope;
-import org.keycloak.events.admin.AdminEvent;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.representations.adapters.action.AdminAction;
 import org.keycloak.representations.adapters.action.LogoutAction;
 import org.keycloak.representations.adapters.action.PushNotBeforeAction;
 import org.keycloak.representations.adapters.action.TestAvailabilityAction;
@@ -29,6 +27,7 @@ import org.keycloak.services.resource.RealmResourceProvider;
 import org.keycloak.services.resource.RealmResourceProviderFactory;
 
 import java.security.KeyPair;
+import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingDeque;
 
@@ -70,6 +69,7 @@ public class TestApplicationResourceProviderFactory implements RealmResourceProv
 
         private KeyPair signingKeyPair;
         private String oidcRequest;
+        private List<String> sectorIdentifierRedirectUris;
 
         public KeyPair getSigningKeyPair() {
             return signingKeyPair;
@@ -86,5 +86,13 @@ public class TestApplicationResourceProviderFactory implements RealmResourceProv
         public void setOidcRequest(String oidcRequest) {
             this.oidcRequest = oidcRequest;
         }
+
+        public List<String> getSectorIdentifierRedirectUris() {
+            return sectorIdentifierRedirectUris;
+        }
+
+        public void setSectorIdentifierRedirectUris(List<String> sectorIdentifierRedirectUris) {
+            this.sectorIdentifierRedirectUris = sectorIdentifierRedirectUris;
+        }
     }
 }
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
index cba8d8e..007f3a7 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
@@ -591,7 +591,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
         RealmModel realm = getRealmByName(realmName);
         UserModel foundFederatedUser = session.users().getUserByFederatedIdentity(new FederatedIdentityModel(identityProvider, userId, userName), realm);
         if (foundFederatedUser == null) return null;
-        return ModelToRepresentation.toRepresentation(foundFederatedUser);
+        return ModelToRepresentation.toRepresentation(session, realm, foundFederatedUser);
     }
 
     @GET
@@ -603,7 +603,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
         UserFederationProviderFactory factory = (UserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, "dummy");
         UserModel user = factory.getInstance(session, null).getUserByUsername(realm, userName);
         if (user == null) return null;
-        return ModelToRepresentation.toRepresentation(user);
+        return ModelToRepresentation.toRepresentation(session, realm, user);
     }
 
     @GET
@@ -634,7 +634,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
         ClientModel client =  realm.getClientByClientId(clientId);
         UserModel user = session.users().getServiceAccount(client);
         if (user == null) return null;
-        return ModelToRepresentation.toRepresentation(user);
+        return ModelToRepresentation.toRepresentation(session, realm, user);
     }
 
     @Path("/export-import")
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api-authz-service.json b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api-authz-service.json
index 6547d2f..1ce85dd 100644
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api-authz-service.json
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api-authz-service.json
@@ -50,7 +50,7 @@
         "mavenArtifactVersion": "2.1.0-SNAPSHOT",
         "mavenArtifactId": "photoz-authz-policy",
         "sessionName": "MainOwnerSession",
-        "mavenArtifactGroupId": "org.keycloak",
+        "mavenArtifactGroupId": "org.keycloak.testsuite",
         "moduleName": "PhotozAuthzOwnerPolicy",
         "applyPolicies": "[]",
         "scannerPeriod": "1",
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/filter/AdapterActionsFilter.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/filter/AdapterActionsFilter.java
index c282dff..aad5bb8 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/filter/AdapterActionsFilter.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/filter/AdapterActionsFilter.java
@@ -27,8 +27,13 @@ import javax.servlet.FilterConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.rotation.JWKPublicKeyLocator;
 import org.keycloak.common.util.Time;
 
 /**
@@ -38,6 +43,11 @@ import org.keycloak.common.util.Time;
  */
 public class AdapterActionsFilter implements Filter {
 
+    public static final String TIME_OFFSET_PARAM = "timeOffset";
+    public static final String RESET_PUBLIC_KEY_PARAM = "resetPublicKey";
+
+    private static final Logger log = Logger.getLogger(AdapterActionsFilter.class);
+
     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
 
@@ -45,17 +55,29 @@ public class AdapterActionsFilter implements Filter {
 
     @Override
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        HttpServletRequest servletReq = (HttpServletRequest) request;
         HttpServletResponse servletResp = (HttpServletResponse) response;
 
         //Accept timeOffset as argument to enforce timeouts
-        String timeOffsetParam = request.getParameter("timeOffset");
+        String timeOffsetParam = request.getParameter(TIME_OFFSET_PARAM);
+        String resetPublicKey = request.getParameter(RESET_PUBLIC_KEY_PARAM);
+
         if (timeOffsetParam != null && !timeOffsetParam.isEmpty()) {
-            Time.setOffset(Integer.parseInt(timeOffsetParam));
+            int timeOffset = Integer.parseInt(timeOffsetParam);
+            log.infof("Time offset updated to %d for application %s", timeOffset, servletReq.getRequestURI());
+            Time.setOffset(timeOffset);
+            writeResponse(servletResp, "Offset set successfully");
+        } else if (resetPublicKey != null && !resetPublicKey.isEmpty()) {
+            AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) request.getServletContext().getAttribute(AdapterDeploymentContext.class.getName());
+            KeycloakDeployment deployment = deploymentContext.resolveDeployment(null);
+            deployment.setPublicKeyLocator(new JWKPublicKeyLocator());
+            log.infof("Restarted publicKey locator for application %s", servletReq.getRequestURI());
+            writeResponse(servletResp, "PublicKeyLocator restarted successfully");
+        } else {
+            // Continue request
+            chain.doFilter(request, response);
         }
 
-        // Continue request
-        chain.doFilter(request, response);
-
     }
 
     @Override
@@ -64,8 +86,9 @@ public class AdapterActionsFilter implements Filter {
     }
 
     private void writeResponse(HttpServletResponse response, String responseText) throws IOException {
+        response.setContentType("text/html");
         PrintWriter writer = response.getWriter();
-        writer.println(responseText);
+        writer.println("<html><body>" + responseText + "</body></html>");
         writer.flush();
     }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/AbstractShowTokensPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/AbstractShowTokensPage.java
index d370dd0..6cb1f37 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/AbstractShowTokensPage.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/AbstractShowTokensPage.java
@@ -23,6 +23,7 @@ import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.RefreshToken;
 import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
 import org.keycloak.util.JsonSerialization;
+import org.openqa.selenium.NoSuchElementException;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
 
@@ -43,6 +44,8 @@ public abstract class AbstractShowTokensPage extends AbstractPageWithInjectedUrl
             return JsonSerialization.readValue(accessToken.getText(), AccessToken.class);
         } catch (IOException e) {
             e.printStackTrace();
+        } catch (NoSuchElementException nsee) {
+            log.warn("No accessToken element found on the page");
         }
 
         return null;
@@ -53,7 +56,10 @@ public abstract class AbstractShowTokensPage extends AbstractPageWithInjectedUrl
             return JsonSerialization.readValue(refreshToken.getText(), RefreshToken.class);
         } catch (IOException e) {
             e.printStackTrace();
+        } catch (NoSuchElementException nsee) {
+            log.warn("No idToken element found on the page");
         }
+
         return null;
     }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/BasicAuth.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/BasicAuth.java
new file mode 100644
index 0000000..8880d83
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/BasicAuth.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.adapter.page;
+
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
+
+import javax.ws.rs.core.UriBuilder;
+import java.net.URL;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+public class BasicAuth extends AbstractPageWithInjectedUrl {
+
+    public static final String DEPLOYMENT_NAME = "basic-auth";
+
+    @ArquillianResource
+    @OperateOnDeployment(DEPLOYMENT_NAME)
+    private URL url;
+
+    @Override
+    public URL getInjectedUrl() {
+        //EAP6 URL fix
+        URL fixedUrl = createInjectedURL("basic-auth");
+        return fixedUrl != null ? fixedUrl : url;
+    }
+
+    @Override
+    public UriBuilder createUriBuilder() {
+        return super.createUriBuilder()
+                .userInfo("{user}:{password}")
+                .path("basic-auth")
+                .queryParam("value", "{value}");
+    }
+
+    public BasicAuth setTemplateValues(String user, String password, String value) {
+        setUriParameter("user", user);
+        setUriParameter("password", password);
+        setUriParameter("value", value);
+        return this;
+    }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/BasicAuthServlet.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/BasicAuthServlet.java
new file mode 100644
index 0000000..3c51343
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/BasicAuthServlet.java
@@ -0,0 +1,27 @@
+package org.keycloak.testsuite.adapter.servlet;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author mhajas
+ */
+@WebServlet("/basic-auth")
+public class BasicAuthServlet extends HttpServlet {
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+        String value = req.getParameter("value");
+        System.out.println("In BasicAuthServlet with value: " + value);
+
+        resp.setContentType("text/plain");
+        PrintWriter pw = resp.getWriter();
+        pw.printf(value);
+        pw.flush();
+    }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
index 9cd7625..4af2988 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
@@ -49,8 +49,6 @@ import static org.keycloak.testsuite.util.IOUtil.*;
  */
 public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
 
-    public static final String REALM_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB";
-
     protected final Logger log = org.jboss.logging.Logger.getLogger(this.getClass());
 
     private final boolean authServerSslRequired = Boolean.parseBoolean(System.getProperty("auth.server.ssl.required"));
@@ -129,7 +127,6 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
 //                ac.setRealmKey(null); // TODO verify if realm key is required for relative scneario
                     } else {
                         adapterConfig.setAuthServerUrl(getAuthServerContextRoot() + "/auth");
-                        adapterConfig.setRealmKey(REALM_KEY);
                     }
 
                     if ("true".equals(System.getProperty("app.server.ssl.required"))) {
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResourceUrls.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResourceUrls.java
index 8c5f98b..88b7b38 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResourceUrls.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResourceUrls.java
@@ -17,10 +17,10 @@
 
 package org.keycloak.testsuite.client.resources;
 
-import javax.ws.rs.core.UriBuilder;
-
 import org.keycloak.testsuite.util.OAuthClient;
 
+import javax.ws.rs.core.UriBuilder;
+
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
@@ -45,4 +45,10 @@ public class TestApplicationResourceUrls {
 
         return builder.build().toString();
     }
+
+    public static String pairwiseSectorIdentifierUri() {
+        UriBuilder builder = oidcClientEndpoints()
+                .path(TestOIDCEndpointsApplicationResource.class, "getSectorIdentifierRedirectUris");
+        return builder.build().toString();
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestOIDCEndpointsApplicationResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestOIDCEndpointsApplicationResource.java
index 54d6c35..9c4f324 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestOIDCEndpointsApplicationResource.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestOIDCEndpointsApplicationResource.java
@@ -17,15 +17,15 @@
 
 package org.keycloak.testsuite.client.resources;
 
-import java.util.Map;
+import org.keycloak.jose.jwk.JSONWebKeySet;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
-
-import org.keycloak.jose.jwk.JSONWebKeySet;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -55,4 +55,15 @@ public interface TestOIDCEndpointsApplicationResource {
     @Path("/get-oidc-request")
     @Produces(org.keycloak.utils.MediaType.APPLICATION_JWT)
     String getOIDCRequest();
+
+    @GET
+    @Path("/set-sector-identifier-redirect-uris")
+    @Produces(MediaType.APPLICATION_JSON)
+    void setSectorIdentifierRedirectUris(@QueryParam("redirectUris") List<String> redirectUris);
+
+    @GET
+    @Path("/get-sector-identifier-redirect-uris")
+    @Produces(MediaType.APPLICATION_JSON)
+    List<String> getSectorIdentifierRedirectUris();
+
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPage.java
index 78913d6..94a8fb6 100755
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPage.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPage.java
@@ -71,6 +71,9 @@ public class LoginPage extends AbstractPage {
     @FindBy(className = "alert-info")
     private WebElement loginInfoMessage;
 
+    @FindBy(className = "instruction")
+    private WebElement instruction;
+
 
     @FindBy(id = "kc-current-locale-link")
     private WebElement languageText;
@@ -128,6 +131,10 @@ public class LoginPage extends AbstractPage {
         return loginErrorMessage != null ? loginErrorMessage.getText() : null;
     }
 
+    public String getInstruction() {
+        return instruction != null ? instruction.getText() : null;
+    }
+
     public String getSuccessMessage() {
         return loginSuccessMessage != null ? loginSuccessMessage.getText() : null;
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/ProfileAssume.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/ProfileAssume.java
new file mode 100644
index 0000000..7fbf59b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/ProfileAssume.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite;
+
+import org.junit.Assume;
+import org.keycloak.common.Profile;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ProfileAssume {
+
+    public static void assumePreview() {
+        Assume.assumeTrue("Ignoring test as community/preview profile is not enabled", Profile.isPreviewEnabled());
+    }
+
+    public static void assumePreviewDisabled() {
+        Assume.assumeFalse("Ignoring test as community/preview profile is enabled", Profile.isPreviewEnabled());
+    }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java
index e4dfe0e..35d11d1 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java
@@ -377,12 +377,15 @@ public class AccountTest extends TestRealmKeycloakTest {
     }
 
     @Test
-    public void changeProfile() {
+    public void changeProfile() throws Exception {
+        setEditUsernameAllowed(false);
+
         profilePage.open();
         loginPage.login("test-user@localhost", "password");
 
         events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
 
+        Assert.assertEquals("test-user@localhost", profilePage.getUsername());
         Assert.assertEquals("Tom", profilePage.getFirstName());
         Assert.assertEquals("Brady", profilePage.getLastName());
         Assert.assertEquals("test-user@localhost", profilePage.getEmail());
@@ -391,6 +394,7 @@ public class AccountTest extends TestRealmKeycloakTest {
         profilePage.updateProfile("", "New last", "new@email.com");
 
         Assert.assertEquals("Please specify first name.", profilePage.getError());
+        Assert.assertEquals("test-user@localhost", profilePage.getUsername());
         Assert.assertEquals("", profilePage.getFirstName());
         Assert.assertEquals("New last", profilePage.getLastName());
         Assert.assertEquals("new@email.com", profilePage.getEmail());
@@ -417,6 +421,7 @@ public class AccountTest extends TestRealmKeycloakTest {
 
         profilePage.clickCancel();
 
+        Assert.assertEquals("test-user@localhost", profilePage.getUsername());
         Assert.assertEquals("Tom", profilePage.getFirstName());
         Assert.assertEquals("Brady", profilePage.getLastName());
         Assert.assertEquals("test-user@localhost", profilePage.getEmail());
@@ -426,6 +431,7 @@ public class AccountTest extends TestRealmKeycloakTest {
         profilePage.updateProfile("New first", "New last", "new@email.com");
 
         Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
+        Assert.assertEquals("test-user@localhost", profilePage.getUsername());
         Assert.assertEquals("New first", profilePage.getFirstName());
         Assert.assertEquals("New last", profilePage.getLastName());
         Assert.assertEquals("new@email.com", profilePage.getEmail());
@@ -436,18 +442,21 @@ public class AccountTest extends TestRealmKeycloakTest {
         // reset user for other tests
         profilePage.updateProfile("Tom", "Brady", "test-user@localhost");
         events.clear();
+
+        // Revert
+        setEditUsernameAllowed(true);
     }
 
-    private void setEditUsernameAllowed() {
+    private void setEditUsernameAllowed(boolean allowed) {
         RealmRepresentation testRealm = testRealm().toRepresentation();
-        testRealm.setEditUsernameAllowed(true);
+        testRealm.setEditUsernameAllowed(allowed);
         testRealm().update(testRealm);
     }
 
     @Test
     public void changeUsername() {
         // allow to edit the username in realm
-        setEditUsernameAllowed();
+        setEditUsernameAllowed(true);
 
         profilePage.open();
         loginPage.login("test-user@localhost", "password");
@@ -504,7 +513,7 @@ public class AccountTest extends TestRealmKeycloakTest {
     @Test
     public void changeUsernameLoginWithOldUsername() {
         addUser("change-username", "change-username@localhost");
-        setEditUsernameAllowed();
+        setEditUsernameAllowed(true);
 
         profilePage.open();
         loginPage.login("change-username", "password");
@@ -530,7 +539,7 @@ public class AccountTest extends TestRealmKeycloakTest {
     @Test
     public void changeEmailLoginWithOldEmail() {
         addUser("change-email", "change-username@localhost");
-        setEditUsernameAllowed();
+        setEditUsernameAllowed(true);
 
         profilePage.open();
         loginPage.login("change-username@localhost", "password");
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractExampleAdapterTest.java
index 9e7f4f1..065477a 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractExampleAdapterTest.java
@@ -17,11 +17,6 @@
 
 package org.keycloak.testsuite.adapter;
 
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.nio.file.Paths;
-
 import org.apache.commons.io.IOUtils;
 import org.jboss.shrinkwrap.api.ShrinkWrap;
 import org.jboss.shrinkwrap.api.asset.StringAsset;
@@ -29,6 +24,11 @@ import org.jboss.shrinkwrap.api.spec.JavaArchive;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.junit.Assert;
 
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Paths;
+
 /**
  *
  * @author tkyjovsk
@@ -50,11 +50,11 @@ public abstract class AbstractExampleAdapterTest extends AbstractAdapterTest {
         Assert.assertNotNull("Property ${examples.version.suffix} must bet set.", EXAMPLES_VERSION_SUFFIX);
         System.out.println(EXAMPLES_VERSION_SUFFIX);
 
+        EXAMPLES_HOME_DIR = EXAMPLES_HOME + "/example-realms";
+
         if (!System.getProperty("unpacked.container.folder.name","").isEmpty()) {
-            EXAMPLES_HOME_DIR = EXAMPLES_HOME + "/" + System.getProperty("unpacked.container.folder.name","") + "-examples";
             TEST_APPS_HOME_DIR = EXAMPLES_HOME + "/" + System.getProperty("unpacked.container.folder.name","") + "-test-apps";
         } else {
-            EXAMPLES_HOME_DIR = EXAMPLES_HOME + "/keycloak-examples-" + EXAMPLES_VERSION_SUFFIX;
             TEST_APPS_HOME_DIR = EXAMPLES_HOME + "/Keycloak-" + EXAMPLES_VERSION_SUFFIX + "-test-apps";
         }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java
index 127c863..a40275f 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java
@@ -22,6 +22,7 @@ import org.jboss.shrinkwrap.api.ShrinkWrap;
 import org.jboss.shrinkwrap.api.asset.StringAsset;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter;
 import org.keycloak.testsuite.util.WaitUtils;
 import org.openqa.selenium.By;
 
@@ -113,7 +114,7 @@ public abstract class AbstractServletsAdapterTest extends AbstractAdapterTest {
     protected void setAdapterAndServerTimeOffset(int timeOffset, String servletUri) {
         setTimeOffset(timeOffset);
         String timeOffsetUri = UriBuilder.fromUri(servletUri)
-                .queryParam("timeOffset", timeOffset)
+                .queryParam(AdapterActionsFilter.TIME_OFFSET_PARAM, timeOffset)
                 .build().toString();
 
         driver.navigate().to(timeOffsetUri);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractDemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractDemoExampleAdapterTest.java
index b1df6e0..4db4a3c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractDemoExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractDemoExampleAdapterTest.java
@@ -98,7 +98,7 @@ public abstract class AbstractDemoExampleAdapterTest extends AbstractExampleAdap
     @Override
     public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
         testRealms.add(
-                loadRealm(new File(EXAMPLES_HOME_DIR + "/preconfigured-demo/testrealm.json")));
+                loadRealm(new File(EXAMPLES_HOME_DIR + "/demo-template/testrealm.json")));
     }
 
     @Override
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractFuseExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractFuseExampleAdapterTest.java
index cc13724..b0583fb 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractFuseExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractFuseExampleAdapterTest.java
@@ -17,22 +17,23 @@
 
 package org.keycloak.testsuite.adapter.example;
 
-import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
-import java.io.File;
-import java.util.List;
 import org.jboss.arquillian.graphene.page.Page;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import org.junit.Test;
 import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.testsuite.auth.page.account.Account;
-import static org.keycloak.testsuite.util.IOUtil.loadRealm;
-import static org.keycloak.testsuite.adapter.AbstractExampleAdapterTest.EXAMPLES_HOME_DIR;
+import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
 import org.keycloak.testsuite.adapter.page.fuse.AdminInterface;
 import org.keycloak.testsuite.adapter.page.fuse.CustomerListing;
 import org.keycloak.testsuite.adapter.page.fuse.CustomerPortalFuseExample;
 import org.keycloak.testsuite.adapter.page.fuse.ProductPortalFuseExample;
+import org.keycloak.testsuite.auth.page.account.Account;
+
+import java.io.File;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
+import static org.keycloak.testsuite.util.IOUtil.loadRealm;
 import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
 import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
 import static org.keycloak.testsuite.util.WaitUtils.pause;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java
index 66702a9..9d25421 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java
@@ -23,13 +23,7 @@ import org.jboss.arquillian.test.api.ArquillianResource;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.junit.Before;
 import org.junit.Test;
-import org.keycloak.admin.client.resource.AuthorizationResource;
-import org.keycloak.admin.client.resource.ClientResource;
-import org.keycloak.admin.client.resource.ClientsResource;
-import org.keycloak.admin.client.resource.ResourcesResource;
-import org.keycloak.admin.client.resource.RoleResource;
-import org.keycloak.admin.client.resource.UserResource;
-import org.keycloak.admin.client.resource.UsersResource;
+import org.keycloak.admin.client.resource.*;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
@@ -45,11 +39,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
@@ -80,8 +70,15 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd
     }
 
     @Before
-    public void beforePhotozExampleAdapterTest() {
+    public void beforePhotozExampleAdapterTest() throws FileNotFoundException {
         deleteAllCookiesForClientPage();
+
+        for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
+            if ("Only Owner Policy".equals(policy.getName())) {
+                policy.getConfig().put("mavenArtifactVersion", System.getProperty("project.version"));
+                getAuthorizationResource().policies().policy(policy.getId()).update(policy);
+            }
+        }
     }
 
     @Override
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 083867f..065de77 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
@@ -17,6 +17,7 @@
 
 package org.keycloak.testsuite.adapter.servlet;
 
+import org.apache.commons.io.FileUtils;
 import org.jboss.arquillian.container.test.api.Deployment;
 import org.jboss.arquillian.graphene.page.Page;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
@@ -25,19 +26,31 @@ import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
+import org.keycloak.admin.client.resource.ClientResource;
 import org.keycloak.common.Version;
 import org.keycloak.common.util.Time;
 import org.keycloak.constants.AdapterConstants;
+import org.keycloak.models.Constants;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.VersionRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
 import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter;
 import org.keycloak.testsuite.adapter.page.*;
+import org.keycloak.testsuite.admin.ApiUtil;
+import org.keycloak.testsuite.auth.page.account.Applications;
+import org.keycloak.testsuite.auth.page.login.OAuthGrant;
+import org.keycloak.testsuite.console.page.events.Config;
+import org.keycloak.testsuite.console.page.events.LoginEvents;
+import org.keycloak.testsuite.util.URLAssert;
 import org.keycloak.testsuite.util.URLUtils;
 import org.keycloak.util.BasicAuthHelper;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
 
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
@@ -46,15 +59,23 @@ import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.Form;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import java.io.File;
+import java.io.IOException;
 import java.net.URI;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import static org.junit.Assert.*;
+import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
 import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
 import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
 import static org.keycloak.testsuite.util.WaitUtils.pause;
+import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
 
 /**
  *
@@ -78,6 +99,16 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
     private InputPortal inputPortal;
     @Page
     private TokenMinTTLPage tokenMinTTLPage;
+    @Page
+    private OAuthGrant oAuthGrantPage;
+    @Page
+    private Applications applicationsPage;
+    @Page
+    private LoginEvents loginEventsPage;
+    @Page
+    private BasicAuth basicAuthPage;
+    @Page
+    private Config configPage;
 
     @Deployment(name = CustomerPortal.DEPLOYMENT_NAME)
     protected static WebArchive customerPortal() {
@@ -119,6 +150,20 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
         return servletDeployment(TokenMinTTLPage.DEPLOYMENT_NAME, AdapterActionsFilter.class, AbstractShowTokensServlet.class, TokenMinTTLServlet.class, ErrorServlet.class);
     }
 
+    @Deployment(name = BasicAuth.DEPLOYMENT_NAME)
+    protected static WebArchive basicAuth() {
+        return servletDeployment(BasicAuth.DEPLOYMENT_NAME, BasicAuthServlet.class);
+    }
+
+    @Override
+    public void setDefaultPageUriParameters() {
+        super.setDefaultPageUriParameters();
+        configPage.setConsoleRealm(DEMO);
+        loginEventsPage.setConsoleRealm(DEMO);
+        applicationsPage.setAuthRealm(DEMO);
+        loginEventsPage.setConsoleRealm(DEMO);
+    }
+
     @Before
     public void beforeDemoServletsAdapterTest() {
         // Delete all cookies from token-min-ttl page to be sure we are logged out
@@ -167,6 +212,59 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
     }
 
     @Test
+    public void testRealmKeyRotationWithNewKeyDownload() throws Exception {
+        // Login success first
+        tokenMinTTLPage.navigateTo();
+        testRealmLoginPage.form().waitForUsernameInputPresent();
+        assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
+        testRealmLoginPage.form().login("bburke@redhat.com", "password");
+        assertCurrentUrlEquals(tokenMinTTLPage);
+
+        AccessToken token = tokenMinTTLPage.getAccessToken();
+        Assert.assertEquals("bburke@redhat.com", token.getPreferredUsername());
+
+        // Logout
+        String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder())
+                .queryParam(OAuth2Constants.REDIRECT_URI, tokenMinTTLPage.toString())
+                .build("demo").toString();
+        driver.navigate().to(logoutUri);
+
+        // Generate new realm key
+        RealmRepresentation realmRep = testRealmResource().toRepresentation();
+        String oldPublicKey = realmRep.getPublicKey();
+        String oldPrivateKey = realmRep.getPrivateKey();
+        realmRep.setPublicKey(Constants.GENERATE);
+        testRealmResource().update(realmRep);
+
+        // Try to login again. It should fail now
+        tokenMinTTLPage.navigateTo();
+        testRealmLoginPage.form().waitForUsernameInputPresent();
+        assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
+        testRealmLoginPage.form().login("bburke@redhat.com", "password");
+        URLAssert.assertCurrentUrlStartsWith(driver, tokenMinTTLPage.getInjectedUrl().toString());
+        assertNull(tokenMinTTLPage.getAccessToken());
+
+        String adapterActionsUrl = tokenMinTTLPage.toString() + "/unsecured/foo";
+        setAdapterAndServerTimeOffset(300, adapterActionsUrl);
+
+        // Try to login. Should work now due to realm key change
+        tokenMinTTLPage.navigateTo();
+        assertCurrentUrlEquals(tokenMinTTLPage);
+        token = tokenMinTTLPage.getAccessToken();
+        Assert.assertEquals("bburke@redhat.com", token.getPreferredUsername());
+        driver.navigate().to(logoutUri);
+
+        // Revert public keys change
+        String timeOffsetUri = UriBuilder.fromUri(adapterActionsUrl)
+                .queryParam(AdapterActionsFilter.RESET_PUBLIC_KEY_PARAM, "true")
+                .build().toString();
+        driver.navigate().to(timeOffsetUri);
+        waitUntilElement(By.tagName("body")).is().visible();
+
+        setAdapterAndServerTimeOffset(0, adapterActionsUrl);
+    }
+
+    @Test
     public void testLoginSSOAndLogout() {
         // test login to customer-portal which does a bearer request to customer-db
         customerPortal.navigateTo();
@@ -261,7 +359,7 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
         demoRealmRep.setSsoSessionIdleTimeout(1);
         testRealmResource().update(demoRealmRep);
 
-		pause(2000);
+        pause(2000);
 
         productPortal.navigateTo();
         assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
@@ -323,6 +421,10 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
 
         demoRealmRep.setSsoSessionIdleTimeout(originalIdle);
         testRealmResource().update(demoRealmRep);
+
+        String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder())
+                .queryParam(OAuth2Constants.REDIRECT_URI, securePortal.toString()).build("demo").toString();
+        driver.navigate().to(logoutUri);
     }
 
     @Test
@@ -444,6 +546,7 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
 
         // Sets 5 minutes offset and assert access token will be still the same
         setAdapterAndServerTimeOffset(300, tokenMinTTLPage.toString());
+        tokenMinTTLPage.navigateTo();
         token = tokenMinTTLPage.getAccessToken();
         int tokenIssued2 = token.getIssuedAt();
         Assert.assertEquals(tokenIssued1, tokenIssued2);
@@ -451,6 +554,7 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
 
         // Sets 9 minutes offset and assert access token will be refreshed (accessTokenTimeout is 10 minutes, token-min-ttl is 2 minutes. Hence 8 minutes or more should be sufficient)
         setAdapterAndServerTimeOffset(540, tokenMinTTLPage.toString());
+        tokenMinTTLPage.navigateTo();
         token = tokenMinTTLPage.getAccessToken();
         int tokenIssued3 = token.getIssuedAt();
         Assert.assertTrue(tokenIssued3 > tokenIssued1);
@@ -486,5 +590,193 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
         setAdapterAndServerTimeOffset(0, tokenMinTTLPage.toString());
     }
 
+    @Test
+    public void testBasicAuth() {
+        String value = "hello";
+        Client client = ClientBuilder.newClient();
+
+        Response response = client.target(basicAuthPage
+                .setTemplateValues("mposolda", "password", value).buildUri()).request().get();
+
+        assertEquals(200, response.getStatus());
+        assertEquals(value, response.readEntity(String.class));
+        response.close();
+
+        response = client.target(basicAuthPage
+                .setTemplateValues("invalid-user", "password", value).buildUri()).request().get();
+        assertEquals(401, response.getStatus());
+        String readResponse = response.readEntity(String.class);
+        assertTrue(readResponse.contains("Unauthorized") || readResponse.contains("Status 401"));
+        response.close();
+
+        response = client.target(basicAuthPage
+                .setTemplateValues("admin", "invalid-password", value).buildUri()).request().get();
+        assertEquals(401, response.getStatus());
+        readResponse = response.readEntity(String.class);
+        assertTrue(readResponse.contains("Unauthorized") || readResponse.contains("Status 401"));
+        response.close();
+
+        client.close();
+    }
+
+    @Test
+    public void grantServerBasedApp() {
+        ClientResource clientResource = ApiUtil.findClientResourceByClientId(testRealmResource(), "customer-portal");
+        ClientRepresentation client = clientResource.toRepresentation();
+        client.setConsentRequired(true);
+        clientResource.update(client);
+
+        RealmRepresentation realm = testRealmResource().toRepresentation();
+        realm.setEventsEnabled(true);
+        realm.setEnabledEventTypes(Arrays.asList("REVOKE_GRANT", "LOGIN"));
+        testRealmResource().update(realm);
+
+        customerPortal.navigateTo();
+
+        loginPage.form().login("bburke@redhat.com", "password");
+
+        assertTrue(oAuthGrantPage.isCurrent());
+
+        oAuthGrantPage.accept();
+
+        waitUntilElement(By.xpath("//body")).text().contains("Bill Burke");
+        waitUntilElement(By.xpath("//body")).text().contains("Stian Thorgersen");
+
+        applicationsPage.navigateTo();
+        applicationsPage.revokeGrantForApplication("customer-portal");
+
+        customerPortal.navigateTo();
+
+        assertTrue(oAuthGrantPage.isCurrent());
+
+        loginEventsPage.navigateTo();
+
+        if (!testContext.isAdminLoggedIn()) {
+            loginPage.form().login(adminUser);
+            testContext.setAdminLoggedIn(true);
+        }
+
+        loginEventsPage.table().filter();
+        loginEventsPage.table().filterForm().addEventType("REVOKE_GRANT");
+        loginEventsPage.table().update();
+
+        List<WebElement> resultList = loginEventsPage.table().rows();
+
+        assertEquals(1, resultList.size());
+
+        resultList.get(0).findElement(By.xpath(".//td[text()='REVOKE_GRANT']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='account']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='revoked_client']/../td[text()='customer-portal']"));
+
+        loginEventsPage.table().reset();
+        loginEventsPage.table().filterForm().addEventType("LOGIN");
+        loginEventsPage.table().update();
+        resultList = loginEventsPage.table().rows();
+
+        assertEquals(1, resultList.size());
+
+        resultList.get(0).findElement(By.xpath(".//td[text()='LOGIN']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='customer-portal']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='username']/../td[text()='bburke@redhat.com']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='consent']/../td[text()='consent_granted']"));
+
+        configPage.navigateTo();
+        configPage.form().clearLoginEvents();
+        driver.findElement(By.xpath("//div[@class='modal-dialog']//button[text()='Delete']")).click();
+    }
+
+    @Test
+    public void historyOfAccessResourceTest() throws IOException {
+        RealmRepresentation realm = testRealmResource().toRepresentation();
+        realm.setEventsEnabled(true);
+        realm.setEnabledEventTypes(Arrays.asList("LOGIN", "LOGIN_ERROR", "LOGOUT", "CODE_TO_TOKEN"));
+        testRealmResource().update(realm);
+
+        customerPortal.navigateTo();
+
+        testRealmLoginPage.form().login("bburke@redhat.com", "password");
+
+        waitUntilElement(By.xpath("//body")).text().contains("Bill Burke");
+        waitUntilElement(By.xpath("//body")).text().contains("Stian Thorgersen");
+
+        driver.navigate().to(testRealmPage.getOIDCLogoutUrl() + "?redirect_uri=" + customerPortal);
+
+        loginEventsPage.navigateTo();
+
+        if (!testContext.isAdminLoggedIn()) {
+            loginPage.form().login(adminUser);
+            testContext.setAdminLoggedIn(true);
+        }
+
+        loginEventsPage.table().filter();
+        loginEventsPage.table().filterForm().addEventType("LOGOUT");
+        loginEventsPage.table().update();
+
+        List<WebElement> resultList = loginEventsPage.table().rows();
+
+        assertEquals(1, resultList.size());
+
+        resultList.get(0).findElement(By.xpath(".//td[text()='LOGOUT']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
+
+        loginEventsPage.table().reset();
+        loginEventsPage.table().filterForm().addEventType("LOGIN");
+        loginEventsPage.table().update();
+        resultList = loginEventsPage.table().rows();
+
+        assertEquals(1, resultList.size());
+
+        resultList.get(0).findElement(By.xpath(".//td[text()='LOGIN']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='customer-portal']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='username']/../td[text()='bburke@redhat.com']"));
+
+        loginEventsPage.table().reset();
+        loginEventsPage.table().filterForm().addEventType("CODE_TO_TOKEN");
+        loginEventsPage.table().update();
+        resultList = loginEventsPage.table().rows();
+
+        assertEquals(1, resultList.size());
+        resultList.get(0).findElement(By.xpath(".//td[text()='CODE_TO_TOKEN']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='customer-portal']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='refresh_token_type']/../td[text()='Refresh']"));
+
+        configPage.navigateTo();
+        configPage.form().clearLoginEvents();
+        driver.findElement(By.xpath("//div[@class='modal-dialog']//button[text()='Delete']")).click();
+
+        String serverLogPath = null;
+
+        if (System.getProperty("app.server").equals("wildfly") || System.getProperty("app.server").equals("eap6") || System.getProperty("app.server").equals("eap")) {
+            serverLogPath = System.getProperty("app.server.home") + "/standalone/log/server.log";
+        }
+
+        String appServerUrl;
+        if (Boolean.parseBoolean(System.getProperty("app.server.ssl.required"))) {
+            appServerUrl = "https://localhost:" + System.getProperty("app.server.https.port", "8543") + "/";
+        } else {
+            appServerUrl = "http://localhost:" + System.getProperty("app.server.http.port", "8280") + "/";
+        }
+
+        if (serverLogPath != null) {
+            log.info("Checking app server log at: " + serverLogPath);
+            File serverLog = new File(serverLogPath);
+            String serverLogContent = FileUtils.readFileToString(serverLog);
+            UserRepresentation bburke = ApiUtil.findUserByUsername(testRealmResource(), "bburke@redhat.com");
+
+            Pattern pattern = Pattern.compile("User '" + bburke.getId() + "' invoking '" + appServerUrl + "customer-portal[^\\s]+' on client 'customer-portal'");
+            Matcher matcher = pattern.matcher(serverLogContent);
+
+            assertTrue(matcher.find());
+            assertTrue(serverLogContent.contains("User '" + bburke.getId() + "' invoking '" + appServerUrl + "customer-db/' on client 'customer-db'"));
+        } else {
+            log.info("Checking app server log on app-server: \"" + System.getProperty("app.server") + "\" is not supported.");
+        }
+    }
+
 
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractOfflineServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractOfflineServletsAdapterTest.java
index fa6d0a8..b8c10b6 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractOfflineServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractOfflineServletsAdapterTest.java
@@ -85,7 +85,7 @@ public abstract class AbstractOfflineServletsAdapterTest extends AbstractServlet
         String refreshTokenId = offlineTokenPage.getRefreshToken().getId();
 
         setAdapterAndServerTimeOffset(9999);
-
+        offlineTokenPage.navigateTo();
         assertCurrentUrlStartsWith(offlineTokenPage);
         Assert.assertNotEquals(offlineTokenPage.getRefreshToken().getId(), refreshTokenId);
         Assert.assertNotEquals(offlineTokenPage.getAccessToken().getId(), accessTokenId);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java
index 2973caa..5bdd305 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java
@@ -327,8 +327,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
 
         salesPostPassiveServletPage.navigateTo();
         if (forbiddenIfNotAuthenticated) {
-            waitUntilElement(By.xpath("//body")).text().not().contains("principal=");
-            assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains(FORBIDDEN_TEXT));
+            assertOnForbiddenPage();
         } else {
             waitUntilElement(By.xpath("//body")).text().contains("principal=null");
         }
@@ -407,9 +406,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
         salesPostPassiveServletPage.navigateTo();
 
         if (forbiddenIfNotAuthenticated) {
-            waitUntilElement(By.xpath("//body")).text().not().contains("principal=");
-            //Different 403 status page on EAP and Wildfly
-            assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains(FORBIDDEN_TEXT));
+            assertOnForbiddenPage();
         } else {
             waitUntilElement(By.xpath("//body")).text().contains("principal=null");
         }
@@ -422,9 +419,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
         salesPostPassiveServletPage.navigateTo();
 
         if (forbiddenIfNotAuthenticated) {
-            waitUntilElement(By.xpath("//body")).text().not().contains("principal=");
-            //Different 403 status page on EAP and Wildfly
-            assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains(FORBIDDEN_TEXT));
+            assertOnForbiddenPage();
         } else {
             waitUntilElement(By.xpath("//body")).text().contains("principal=null");
         }
@@ -724,4 +719,16 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
         driver.navigate().to(employee2ServletPage.toString() + "/setCheckRoles?roles=" + roles);
         employee2ServletPage.logout();
     }
+
+    private void assertOnForbiddenPage() {
+        switch (System.getProperty("app.server")) {
+            case "eap6":
+                waitUntilElement(By.xpath("//body")).text().not().contains("principal=");
+                String source = driver.getPageSource();
+                assertTrue(source.isEmpty() || source.contains("<body></body>"));
+                break;
+            default:
+                waitUntilElement(By.xpath("//body")).text().contains(FORBIDDEN_TEXT);
+        }
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java
index f115c49..c32ba08 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java
@@ -104,7 +104,7 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
     }
 
     void compareExecution(AuthenticationExecutionExportRepresentation expected, AuthenticationExecutionExportRepresentation actual) {
-        Assert.assertEquals("Execution flowAlias - " + actual.getAuthenticator(), expected.getFlowAlias(), actual.getFlowAlias());
+        Assert.assertEquals("Execution flowAlias - " + actual.getFlowAlias(), expected.getFlowAlias(), actual.getFlowAlias());
         Assert.assertEquals("Execution authenticator - " + actual.getAuthenticator(), expected.getAuthenticator(), actual.getAuthenticator());
         Assert.assertEquals("Execution userSetupAllowed - " + actual.getAuthenticator(), expected.isUserSetupAllowed(), actual.isUserSetupAllowed());
         Assert.assertEquals("Execution authenticatorFlow - " + actual.getAuthenticator(), expected.isAutheticatorFlow(), actual.isAutheticatorFlow());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java
index 42015ed..d7caba4 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java
@@ -94,7 +94,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
         // we'll need auth-cookie later
         AuthenticationExecutionInfoRepresentation authCookieExec = findExecutionByProvider("auth-cookie", executionReps);
 
-        compareExecution(newExecInfo("Review Profile", "idp-review-profile", true, 0, 3, DISABLED, null, new String[]{REQUIRED, DISABLED}), exec);
+        compareExecution(newExecInfo("Review Profile", "idp-review-profile", true, 0, 4, DISABLED, null, new String[]{REQUIRED, DISABLED}), exec);
 
         // remove execution
         authMgmtResource.removeExecution(exec.getId());
@@ -164,7 +164,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
 
         // Note: there is no checking in addExecution if requirement is one of requirementChoices
         // Thus we can have OPTIONAL which is neither ALTERNATIVE, nor DISABLED
-        compareExecution(newExecInfo("Cookie", "auth-cookie", false, 0, 2, OPTIONAL, null, new String[]{ALTERNATIVE, DISABLED}), exec);
+        compareExecution(newExecInfo("Cookie", "auth-cookie", false, 0, 3, OPTIONAL, null, new String[]{ALTERNATIVE, DISABLED}), exec);
     }
 
     @Test
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java
index fc50bc6..90f8874 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java
@@ -203,7 +203,7 @@ public class FlowTest extends AbstractAuthenticationTest {
         // adjust expected values before comparing
         browser.setAlias("Copy of browser");
         browser.setBuiltIn(false);
-        browser.getAuthenticationExecutions().get(2).setFlowAlias("Copy of browser forms");
+        browser.getAuthenticationExecutions().get(3).setFlowAlias("Copy of browser forms");
         compareFlows(browser, copyOfBrowser);
 
         // get new flow directly and compare
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java
index 3640af5..ee79c27 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java
@@ -125,12 +125,14 @@ public class InitialFlowsTest extends AbstractAuthenticationTest {
         AuthenticationFlowRepresentation flow = newFlow("browser", "browser based authentication", "basic-flow", true, true);
         addExecExport(flow, null, false, "auth-cookie", false, null, ALTERNATIVE, 10);
         addExecExport(flow, null, false, "auth-spnego", false, null, DISABLED, 20);
+        addExecExport(flow, null, false, "identity-provider-redirector", false, null, ALTERNATIVE, 25);
         addExecExport(flow, "forms", false, null, true, null, ALTERNATIVE, 30);
 
         List<AuthenticationExecutionInfoRepresentation> execs = new LinkedList<>();
         addExecInfo(execs, "Cookie", "auth-cookie", false, 0, 0, ALTERNATIVE, null, new String[]{ALTERNATIVE, DISABLED});
         addExecInfo(execs, "Kerberos", "auth-spnego", false, 0, 1, DISABLED, null, new String[]{ALTERNATIVE, REQUIRED, DISABLED});
-        addExecInfo(execs, "forms", null, false, 0, 2, ALTERNATIVE, true, new String[]{ALTERNATIVE, REQUIRED, DISABLED});
+        addExecInfo(execs, "Identity Provider Redirector", "identity-provider-redirector", true, 0, 2, ALTERNATIVE, null, new String[]{ALTERNATIVE, DISABLED});
+        addExecInfo(execs, "forms", null, false, 0, 3, ALTERNATIVE, true, new String[]{ALTERNATIVE, REQUIRED, DISABLED});
         addExecInfo(execs, "Username Password Form", "auth-username-password-form", false, 1, 0, REQUIRED, null, new String[]{REQUIRED});
         addExecInfo(execs, "OTP Form", "auth-otp-form", false, 1, 1, OPTIONAL, null, new String[]{REQUIRED, OPTIONAL, DISABLED});
         expected.add(new FlowExecutions(flow, execs));
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java
index 858e06e..4e07e6f 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java
@@ -146,6 +146,7 @@ public class ProvidersTest extends AbstractAuthenticationTest {
         addProviderInfo(result, "direct-grant-validate-username", "Username Validation",
                 "Validates the username supplied as a 'username' form parameter in direct grant request");
         addProviderInfo(result, "http-basic-authenticator", "HTTP Basic Authentication", "Validates username and password from Authorization HTTP header");
+        addProviderInfo(result, "identity-provider-redirector", "Identity Provider Redirector", "Redirects to default Identity Provider or Identity Provider specified with kc_idp_hint query parameter");
         addProviderInfo(result, "idp-confirm-link", "Confirm link existing account", "Show the form where user confirms if he wants " +
                 "to link identity provider with existing account or rather edit user profile data retrieved from identity provider to avoid conflict");
         addProviderInfo(result, "idp-create-user-if-unique", "Create User If Unique", "Detect if there is existing Keycloak account " +
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AbstractAuthorizationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AbstractAuthorizationTest.java
index c4979e0..2c3aac7 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AbstractAuthorizationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AbstractAuthorizationTest.java
@@ -19,11 +19,13 @@ package org.keycloak.testsuite.admin.client.authorization;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.keycloak.admin.client.resource.ClientResource;
 import org.keycloak.admin.client.resource.ResourceScopeResource;
 import org.keycloak.admin.client.resource.ResourceScopesResource;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.authorization.ScopeRepresentation;
+import org.keycloak.testsuite.ProfileAssume;
 import org.keycloak.testsuite.admin.client.AbstractClientTest;
 
 import javax.ws.rs.core.Response;
@@ -38,6 +40,11 @@ public abstract class AbstractAuthorizationTest extends AbstractClientTest {
 
     protected static final String RESOURCE_SERVER_CLIENT_ID = "test-resource-server";
 
+    @BeforeClass
+    public static void enabled() {
+        ProfileAssume.assumePreview();
+    }
+
     @Before
     public void onBeforeAuthzTests() {
         createOidcClient(RESOURCE_SERVER_CLIENT_ID);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AuthorizationDisabledInPreviewTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AuthorizationDisabledInPreviewTest.java
new file mode 100644
index 0000000..072aa5f
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AuthorizationDisabledInPreviewTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.admin.client.authorization;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.keycloak.testsuite.ProfileAssume;
+import org.keycloak.testsuite.admin.client.AbstractClientTest;
+
+import javax.ws.rs.ServerErrorException;
+import javax.ws.rs.core.Response;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AuthorizationDisabledInPreviewTest extends AbstractClientTest {
+
+    @BeforeClass
+    public static void enabled() {
+        ProfileAssume.assumePreviewDisabled();
+    }
+
+    @Test
+    public void testAuthzServicesRemoved() {
+        String id = testRealmResource().clients().findAll().get(0).getId();
+        try {
+            testRealmResource().clients().get(id).authorization().getSettings();
+        } catch (ServerErrorException e) {
+            assertEquals(Response.Status.NOT_IMPLEMENTED.getStatusCode(), e.getResponse().getStatus());
+        }
+    }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java
index fb03891..c7339ed 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java
@@ -21,11 +21,11 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.keycloak.admin.client.resource.ClientResource;
-import org.keycloak.events.admin.OperationType;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
 
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
 
 /**
  * Test getting the installation/configuration files for OIDC and SAML.
@@ -81,7 +81,7 @@ public class InstallationTest extends AbstractClientTest {
     private void assertOidcInstallationConfig(String config) {
         RealmRepresentation realmRep = realmRep();
         assertTrue(config.contains(realmRep.getId()));
-        assertTrue(config.contains(realmRep.getPublicKey()));
+        assertFalse(config.contains(realmRep.getPublicKey()));
         assertTrue(config.contains(authServerUrl()));
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java
index 81de894..b6fca90 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java
@@ -17,10 +17,12 @@
 
 package org.keycloak.testsuite.admin;
 
+import org.apache.bcel.generic.RETURN;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.resource.AuthorizationResource;
 import org.keycloak.admin.client.resource.RealmResource;
 import org.keycloak.models.AdminRoles;
 import org.keycloak.models.Constants;
@@ -45,6 +47,10 @@ import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.representations.idm.UserFederationMapperRepresentation;
 import org.keycloak.representations.idm.UserFederationProviderRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
+import org.keycloak.representations.idm.authorization.ScopeRepresentation;
 import org.keycloak.services.resources.admin.RealmAuth.Resource;
 import org.keycloak.testsuite.AbstractKeycloakTest;
 import org.keycloak.testsuite.Assert;
@@ -68,6 +74,8 @@ import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 
 import static org.junit.Assert.*;
+import static org.keycloak.services.resources.admin.RealmAuth.Resource.AUTHORIZATION;
+import static org.keycloak.services.resources.admin.RealmAuth.Resource.CLIENT;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -771,6 +779,123 @@ public class PermissionsTest extends AbstractKeycloakTest {
     }
 
     @Test
+    public void clientAuthorization() {
+        invoke(new InvocationWithResponse() {
+            public void invoke(RealmResource realm, AtomicReference<Response> response) {
+                realm.clients().create(ClientBuilder.create().clientId("foo-authz").build());
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                foo.setServiceAccountsEnabled(true);
+                foo.setAuthorizationServicesEnabled(true);
+                realm.clients().get(foo.getId()).update(foo);
+            }
+        }, CLIENT, true);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                realm.clients().get(foo.getId()).authorization().getSettings();
+            }
+        }, AUTHORIZATION, false);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                ResourceServerRepresentation settings = authorization.getSettings();
+                authorization.update(settings);
+            }
+        }, AUTHORIZATION, true);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                authorization.resources().resources();
+            }
+        }, AUTHORIZATION, false);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                authorization.scopes().scopes();
+            }
+        }, AUTHORIZATION, false);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                authorization.policies().policies();
+            }
+        }, AUTHORIZATION, false);
+        invoke(new InvocationWithResponse() {
+            public void invoke(RealmResource realm, AtomicReference<Response> response) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                response.set(authorization.resources().create(new ResourceRepresentation("Test", Collections.emptySet())));
+            }
+        }, AUTHORIZATION, true);
+        invoke(new InvocationWithResponse() {
+            public void invoke(RealmResource realm, AtomicReference<Response> response) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                response.set(authorization.scopes().create(new ScopeRepresentation("Test")));
+            }
+        }, AUTHORIZATION, true);
+        invoke(new InvocationWithResponse() {
+            public void invoke(RealmResource realm, AtomicReference<Response> response) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                PolicyRepresentation representation = new PolicyRepresentation();
+                representation.setName("Test PermissionsTest");
+                representation.setType("js");
+                HashMap<String, String> config = new HashMap<>();
+                config.put("code", "");
+                representation.setConfig(config);
+                response.set(authorization.policies().create(representation));
+            }
+        }, AUTHORIZATION, true);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                authorization.resources().resource("nosuch").update(new ResourceRepresentation());
+            }
+        }, AUTHORIZATION, true);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                authorization.scopes().scope("nosuch").update(new ScopeRepresentation());
+            }
+        }, AUTHORIZATION, true);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                authorization.policies().policy("nosuch").update(new PolicyRepresentation());
+            }
+        }, AUTHORIZATION, true);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                authorization.resources().resource("nosuch").remove();
+            }
+        }, AUTHORIZATION, true);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                authorization.scopes().scope("nosuch").remove();
+            }
+        }, AUTHORIZATION, true);
+        invoke(new Invocation() {
+            public void invoke(RealmResource realm) {
+                org.keycloak.representations.idm.ClientRepresentation foo = realm.clients().findByClientId("foo-authz").get(0);
+                AuthorizationResource authorization = realm.clients().get(foo.getId()).authorization();
+                authorization.policies().policy("nosuch").remove();
+            }
+        }, AUTHORIZATION, true);
+    }
+
+    @Test
     public void roles() {
         invoke(new Invocation() {
             public void invoke(RealmResource realm) {
@@ -1543,6 +1668,8 @@ public class PermissionsTest extends AbstractKeycloakTest {
                 return AdminRoles.VIEW_EVENTS;
             case IDENTITY_PROVIDER:
                 return AdminRoles.VIEW_IDENTITY_PROVIDERS;
+            case AUTHORIZATION:
+                return AdminRoles.VIEW_AUTHORIZATION;
             default:
                 throw new RuntimeException("Unexpected resouce");
         }
@@ -1560,6 +1687,8 @@ public class PermissionsTest extends AbstractKeycloakTest {
                 return AdminRoles.MANAGE_EVENTS;
             case IDENTITY_PROVIDER:
                 return AdminRoles.MANAGE_IDENTITY_PROVIDERS;
+            case AUTHORIZATION:
+                return AdminRoles.MANAGE_AUTHORIZATION;
             default:
                 throw new RuntimeException("Unexpected resouce");
         }
@@ -1577,6 +1706,8 @@ public class PermissionsTest extends AbstractKeycloakTest {
                 return AdminRoles.VIEW_IDENTITY_PROVIDERS;
             case IDENTITY_PROVIDER:
                 return AdminRoles.VIEW_REALM;
+            case AUTHORIZATION:
+                return AdminRoles.VIEW_IDENTITY_PROVIDERS;
             default:
                 throw new RuntimeException("Unexpected resouce");
         }
@@ -1594,6 +1725,8 @@ public class PermissionsTest extends AbstractKeycloakTest {
                 return AdminRoles.MANAGE_IDENTITY_PROVIDERS;
             case IDENTITY_PROVIDER:
                 return AdminRoles.MANAGE_REALM;
+            case AUTHORIZATION:
+                return AdminRoles.MANAGE_IDENTITY_PROVIDERS;
             default:
                 throw new RuntimeException("Unexpected resouce");
         }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java
index f08f790..926d31d 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java
@@ -57,14 +57,10 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.HashSet;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.Map;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -237,6 +233,7 @@ public class RealmTest extends AbstractAdminTest {
         assertEquals(Boolean.FALSE, rep.isRegistrationAllowed());
         assertEquals(Boolean.FALSE, rep.isRegistrationEmailAsUsername());
         assertEquals(Boolean.FALSE, rep.isEditUsernameAllowed());
+
     }
 
     @Test
@@ -267,6 +264,45 @@ public class RealmTest extends AbstractAdminTest {
     }
 
     @Test
+    public void updateRealmAttributes() {
+        // first change
+        RealmRepresentation rep = new RealmRepresentation();
+        rep.setAttributes(new HashMap<>());
+        rep.getAttributes().put("foo1", "bar1");
+        rep.getAttributes().put("foo2", "bar2");
+
+        rep.setBruteForceProtected(true);
+        rep.setDisplayName("dn1");
+
+        realm.update(rep);
+        assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM);
+
+        rep = realm.toRepresentation();
+
+        assertEquals("bar1", rep.getAttributes().get("foo1"));
+        assertEquals("bar2", rep.getAttributes().get("foo2"));
+        assertTrue(rep.isBruteForceProtected());
+        assertEquals("dn1", rep.getDisplayName());
+
+        // second change
+        rep.setBruteForceProtected(false);
+        rep.setDisplayName("dn2");
+        rep.getAttributes().put("foo1", "bar11");
+        rep.getAttributes().remove("foo2");
+
+        realm.update(rep);
+        assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM);
+
+        rep = realm.toRepresentation();
+
+        assertFalse(rep.isBruteForceProtected());
+        assertEquals("dn2", rep.getDisplayName());
+
+        assertEquals("bar11", rep.getAttributes().get("foo1"));
+        assertFalse(rep.getAttributes().containsKey("foo2"));
+    }
+
+    @Test
     public void getRealmRepresentation() {
         RealmRepresentation rep = realm.toRepresentation();
         Assert.assertEquals(REALM_NAME, rep.getRealm());
@@ -393,6 +429,13 @@ public class RealmTest extends AbstractAdminTest {
             assertEquals(realm.getBrowserSecurityHeaders(), storedRealm.getBrowserSecurityHeaders());
         }
 
+        if (realm.getAttributes() != null) {
+            HashMap<String, String> attributes = new HashMap<>();
+            attributes.putAll(storedRealm.getAttributes());
+            attributes.entrySet().retainAll(realm.getAttributes().entrySet());
+            assertEquals(realm.getAttributes(), attributes);
+        }
+
     }
 
     @Test
@@ -516,6 +559,26 @@ public class RealmTest extends AbstractAdminTest {
     }
 
     @Test
+    public void rotateRealmKeys() {
+        RealmRepresentation realmRep = realm.toRepresentation();
+        String publicKey = realmRep.getPublicKey();
+        String cert = realmRep.getCertificate();
+        assertNotNull(publicKey);
+        assertNotNull(cert);
+
+        RealmRepresentation newRealmRep = new RealmRepresentation();
+        newRealmRep.setRealm(REALM_NAME);
+        newRealmRep.setPublicKey("GENERATE");
+        realm.update(newRealmRep);
+
+        realmRep = realm.toRepresentation();
+        assertNotNull(realmRep.getPublicKey());
+        assertNotNull(realmRep.getCertificate());
+        assertNotEquals(publicKey, realmRep.getPublicKey());
+        assertNotEquals(cert, realmRep.getCertificate());
+    }
+
+    @Test
     public void clearRealmCache() {
         RealmRepresentation realmRep = realm.toRepresentation();
         assertTrue(testingClient.testing().isCached("realms", realmRep.getId()));
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java
index 7a939c3..8cef8a1 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java
@@ -51,7 +51,7 @@ public class UserFederationTest extends AbstractAdminTest {
     @Test
     public void testProviderFactories() {
         List<UserFederationProviderFactoryRepresentation> providerFactories = userFederation().getProviderFactories();
-        Assert.assertNames(providerFactories, "ldap", "kerberos", "dummy", "dummy-configurable", "sssd");
+        Assert.assertNames(providerFactories, "ldap", "kerberos", "dummy", "dummy-configurable");
 
         // Builtin provider without properties
         UserFederationProviderFactoryRepresentation ldapProvider = userFederation().getProviderFactory("ldap");
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java
index 0a4fe4b..818a84a 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AdapterInstallationConfigTest.java
@@ -35,14 +35,11 @@ public class AdapterInstallationConfigTest extends AbstractClientRegistrationTes
     private ClientRepresentation client;
     private ClientRepresentation client2;
     private ClientRepresentation clientPublic;
-    private String publicKey;
 
     @Before
     public void before() throws Exception {
         super.before();
 
-        publicKey = adminClient.realm(REALM_NAME).toRepresentation().getPublicKey();
-
         client = new ClientRepresentation();
         client.setEnabled(true);
         client.setClientId("RegistrationAccessTokenTest");
@@ -92,7 +89,6 @@ public class AdapterInstallationConfigTest extends AbstractClientRegistrationTes
         assertEquals(1, config.getCredentials().size());
         assertEquals(client.getSecret(), config.getCredentials().get("secret"));
 
-        assertEquals(publicKey, config.getRealmKey());
         assertEquals(client.getClientId(), config.getResource());
         assertEquals(SslRequired.EXTERNAL.name().toLowerCase(), config.getSslRequired());
     }
@@ -132,7 +128,6 @@ public class AdapterInstallationConfigTest extends AbstractClientRegistrationTes
 
         assertEquals(0, config.getCredentials().size());
 
-        assertEquals(publicKey, config.getRealmKey());
         assertEquals(clientPublic.getClientId(), config.getResource());
         assertEquals(SslRequired.EXTERNAL.name().toLowerCase(), config.getSslRequired());
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
index 19d6413..d13bfa1 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
@@ -55,11 +55,7 @@ import org.keycloak.testsuite.client.resources.TestOIDCEndpointsApplicationResou
 import org.keycloak.testsuite.rest.resource.TestingOIDCEndpointsApplicationResource;
 import org.keycloak.testsuite.util.OAuthClient;
 import java.security.PrivateKey;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
@@ -287,6 +283,137 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
     }
 
     @Test
+    public void createPairwiseClient() throws Exception {
+        OIDCClientRepresentation clientRep = createRep();
+        clientRep.setSubjectType("pairwise");
+
+        OIDCClientRepresentation response = reg.oidc().create(clientRep);
+        Assert.assertEquals("pairwise", response.getSubjectType());
+    }
+
+    @Test
+    public void updateClientToPairwise() throws Exception {
+        OIDCClientRepresentation response = create();
+        Assert.assertEquals("public", response.getSubjectType());
+
+        reg.auth(Auth.token(response));
+        response.setSubjectType("pairwise");
+        OIDCClientRepresentation updated = reg.oidc().update(response);
+
+        Assert.assertEquals("pairwise", updated.getSubjectType());
+    }
+
+    @Test
+    public void updateSectorIdentifierUri() throws Exception {
+        OIDCClientRepresentation clientRep = createRep();
+        clientRep.setSubjectType("pairwise");
+        OIDCClientRepresentation response = reg.oidc().create(clientRep);
+        Assert.assertEquals("pairwise", response.getSubjectType());
+        Assert.assertNull(response.getSectorIdentifierUri());
+
+        reg.auth(Auth.token(response));
+
+        // Push redirect uris to the sector identifier URI
+        List<String> sectorRedirects = new ArrayList<>();
+        sectorRedirects.addAll(response.getRedirectUris());
+        TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
+        oidcClientEndpointsResource.setSectorIdentifierRedirectUris(sectorRedirects);
+
+        response.setSectorIdentifierUri(TestApplicationResourceUrls.pairwiseSectorIdentifierUri());
+
+        OIDCClientRepresentation updated = reg.oidc().update(response);
+
+        Assert.assertEquals("pairwise", updated.getSubjectType());
+        Assert.assertEquals(TestApplicationResourceUrls.pairwiseSectorIdentifierUri(), updated.getSectorIdentifierUri());
+
+    }
+
+    @Test
+    public void createPairwiseClientWithSectorIdentifierURI() throws Exception {
+        OIDCClientRepresentation clientRep = createRep();
+
+        // Push redirect uris to the sector identifier URI
+        List<String> sectorRedirects = new ArrayList<>();
+        sectorRedirects.addAll(clientRep.getRedirectUris());
+        TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
+        oidcClientEndpointsResource.setSectorIdentifierRedirectUris(sectorRedirects);
+
+        clientRep.setSubjectType("pairwise");
+        clientRep.setSectorIdentifierUri(TestApplicationResourceUrls.pairwiseSectorIdentifierUri());
+
+        OIDCClientRepresentation response = reg.oidc().create(clientRep);
+        Assert.assertEquals("pairwise", response.getSubjectType());
+        Assert.assertEquals(TestApplicationResourceUrls.pairwiseSectorIdentifierUri(), response.getSectorIdentifierUri());
+    }
+
+    @Test
+    public void createPairwiseClientWithRedirectsToMultipleHostsWithoutSectorIdentifierURI() throws Exception {
+        OIDCClientRepresentation clientRep = createRep();
+
+        List<String> redirects = new ArrayList<>();
+        redirects.add("http://redirect1");
+        redirects.add("http://redirect2");
+
+        clientRep.setSubjectType("pairwise");
+        clientRep.setRedirectUris(redirects);
+
+        assertCreateFail(clientRep, 400, "Without a configured Sector Identifier URI, client redirect URIs must not contain multiple host components.");
+    }
+
+    @Test
+    public void createPairwiseClientWithRedirectsToMultipleHosts() throws Exception {
+        OIDCClientRepresentation clientRep = createRep();
+
+        // Push redirect URIs to the sector identifier URI
+        List<String> redirects = new ArrayList<>();
+        redirects.add("http://redirect1");
+        redirects.add("http://redirect2");
+        TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
+        oidcClientEndpointsResource.setSectorIdentifierRedirectUris(redirects);
+
+        clientRep.setSubjectType("pairwise");
+        clientRep.setSectorIdentifierUri(TestApplicationResourceUrls.pairwiseSectorIdentifierUri());
+        clientRep.setRedirectUris(redirects);
+
+        OIDCClientRepresentation response = reg.oidc().create(clientRep);
+        Assert.assertEquals("pairwise", response.getSubjectType());
+        Assert.assertEquals(TestApplicationResourceUrls.pairwiseSectorIdentifierUri(), response.getSectorIdentifierUri());
+        Assert.assertNames(response.getRedirectUris(), "http://redirect1", "http://redirect2");
+    }
+
+    @Test
+    public void createPairwiseClientWithSectorIdentifierURIContainingMismatchedRedirects() throws Exception {
+        OIDCClientRepresentation clientRep = createRep();
+
+        // Push redirect uris to the sector identifier URI
+        List<String> sectorRedirects = new ArrayList<>();
+        sectorRedirects.add("http://someotherredirect");
+        TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
+        oidcClientEndpointsResource.setSectorIdentifierRedirectUris(sectorRedirects);
+
+        clientRep.setSubjectType("pairwise");
+        clientRep.setSectorIdentifierUri(TestApplicationResourceUrls.pairwiseSectorIdentifierUri());
+
+        assertCreateFail(clientRep, 400, "Client redirect URIs does not match redirect URIs fetched from the Sector Identifier URI.");
+    }
+
+    @Test
+    public void createPairwiseClientWithInvalidSectorIdentifierURI() throws Exception {
+        OIDCClientRepresentation clientRep = createRep();
+        clientRep.setSubjectType("pairwise");
+        clientRep.setSectorIdentifierUri("malformed");
+        assertCreateFail(clientRep, 400, "Invalid Sector Identifier URI.");
+    }
+
+    @Test
+    public void createPairwiseClientWithUnreachableSectorIdentifierURI() throws Exception {
+        OIDCClientRepresentation clientRep = createRep();
+        clientRep.setSubjectType("pairwise");
+        clientRep.setSectorIdentifierUri("http://localhost/dummy");
+        assertCreateFail(clientRep, 400, "Failed to get redirect URIs from the Sector Identifier URI.");
+    }
+
+    @Test
     public void testSignaturesRequired() throws Exception {
         OIDCClientRepresentation clientRep = createRep();
         clientRep.setUserinfoSignedResponseAlg(Algorithm.RS256.toString());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java
index 65af5a4..f8fbb91 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java
@@ -16,6 +16,8 @@
  */
 package org.keycloak.testsuite.forms;
 
+import com.fasterxml.jackson.jaxrs.json.annotation.JSONP;
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -25,6 +27,7 @@ import org.keycloak.events.Errors;
 import org.keycloak.models.Constants;
 import org.keycloak.models.utils.TimeBasedOTP;
 import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.managers.DefaultBruteForceProtector;
 import org.keycloak.testsuite.AssertEvents;
 import org.keycloak.testsuite.AssertEvents.ExpectedEvent;
 import org.keycloak.testsuite.pages.AppPage;
@@ -71,6 +74,12 @@ public class BruteForceTest extends TestRealmKeycloakTest {
 
     }
 
+    @After
+    public void slowItDown() throws Exception {
+        Thread.sleep(100);
+
+    }
+
 
     @Rule
     public AssertEvents events = new AssertEvents(this);
@@ -164,6 +173,7 @@ public class BruteForceTest extends TestRealmKeycloakTest {
 
     @Test
     public void testGrantInvalidOtp() throws Exception {
+        clearVariables();
         {
             String totpSecret = totp.generateTOTP("totpSecret");
             OAuthClient.AccessTokenResponse response = getTestToken("password", totpSecret);
@@ -188,7 +198,7 @@ public class BruteForceTest extends TestRealmKeycloakTest {
         {
             String totpSecret = totp.generateTOTP("totpSecret");
             OAuthClient.AccessTokenResponse response = getTestToken("password", totpSecret);
-            Assert.assertNull(response.getAccessToken());
+            assertTokenNull(response);
             Assert.assertNotNull(response.getError());
             Assert.assertEquals(response.getError(), "invalid_grant");
             Assert.assertEquals(response.getErrorDescription(), "Account temporarily disabled");
@@ -205,8 +215,40 @@ public class BruteForceTest extends TestRealmKeycloakTest {
 
     }
 
+    public void clearVariables() {
+        DefaultBruteForceProtector.testCount = 0;
+        DefaultBruteForceProtector.markNotBefore = -1;
+        DefaultBruteForceProtector.markCheck = -1;
+        DefaultBruteForceProtector.testCount = 0;
+        DefaultBruteForceProtector.clearCount = 0;
+        DefaultBruteForceProtector.logFailure = 0;
+        DefaultBruteForceProtector.logFailureCalled = 0;
+        DefaultBruteForceProtector.didntWait = 0;
+        DefaultBruteForceProtector.nullFailureCount = 0;
+        DefaultBruteForceProtector.notFoundUserId = null;
+    }
+
+    public void assertTokenNull(OAuthClient.AccessTokenResponse response) {
+        if (response.getAccessToken() != null) {
+            if (DefaultBruteForceProtector.exceptionObject != null) {
+                DefaultBruteForceProtector.exceptionObject.printStackTrace();
+            }
+        }
+        Assert.assertNull("was mark set: " + DefaultBruteForceProtector.markNotBefore + " time test: " + DefaultBruteForceProtector.markCheck
+                        + " test count " + DefaultBruteForceProtector.testCount
+                        + " nullFailure: " + DefaultBruteForceProtector.nullFailureCount
+                        + " logFailureCalled: " + DefaultBruteForceProtector.logFailureCalled
+                        + " logFailure: " + DefaultBruteForceProtector.logFailure
+                        + " notFoundUserId: " + DefaultBruteForceProtector.notFoundUserId
+                        + " exception: " + DefaultBruteForceProtector.exception
+                , response.getAccessToken());
+    }
+
+
+
     @Test
     public void testGrantMissingOtp() throws Exception {
+        clearVariables();
         {
             String totpSecret = totp.generateTOTP("totpSecret");
             OAuthClient.AccessTokenResponse response = getTestToken("password", totpSecret);
@@ -231,7 +273,7 @@ public class BruteForceTest extends TestRealmKeycloakTest {
         {
             String totpSecret = totp.generateTOTP("totpSecret");
             OAuthClient.AccessTokenResponse response = getTestToken("password", totpSecret);
-            Assert.assertNull(response.getAccessToken());
+            assertTokenNull(response);
             Assert.assertNotNull(response.getError());
             Assert.assertEquals(response.getError(), "invalid_grant");
             Assert.assertEquals(response.getErrorDescription(), "Account temporarily disabled");
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
index f040b13..01f5854 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
@@ -482,6 +482,40 @@ public class LoginTest extends TestRealmKeycloakTest {
             setRememberMe(false);
         }
     }
+    
+    @Test
+    // KEYCLOAK-3181
+    public void loginWithEmailUserAndRememberMe() {
+        setRememberMe(true);
+
+        try {
+            loginPage.open();
+            loginPage.setRememberMe(true);
+            assertTrue(loginPage.isRememberMeChecked());
+            loginPage.login("login@test.com", "password");
+
+            Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+            Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE));
+            EventRepresentation loginEvent = events.expectLogin().user(userId)
+                                                   .detail(Details.USERNAME, "login@test.com")
+                                                   .detail(Details.REMEMBER_ME, "true")
+                                                   .assertEvent();
+            String sessionId = loginEvent.getSessionId();
+
+            // Expire session
+            testingClient.testing().removeUserSession("test", sessionId);
+
+            // Assert rememberMe checked and username/email prefilled
+            loginPage.open();
+            assertTrue(loginPage.isRememberMeChecked());
+            
+            Assert.assertEquals("login@test.com", loginPage.getUsername());
+
+            loginPage.setRememberMe(false);
+        } finally {
+            setRememberMe(false);
+        }
+    }
 
     // KEYCLOAK-1037
     @Test
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 7fea657..e1877b8 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
@@ -36,6 +36,8 @@ import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentatio
 import org.keycloak.protocol.oidc.utils.OIDCResponseType;
 import org.keycloak.representations.IDToken;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.clientregistration.ClientRegistrationService;
+import org.keycloak.services.clientregistration.oidc.OIDCClientRegistrationProviderFactory;
 import org.keycloak.services.resources.RealmsResource;
 import org.keycloak.testsuite.AbstractKeycloakTest;
 import org.keycloak.testsuite.Assert;
@@ -79,12 +81,21 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
             Assert.assertEquals(oidcConfig.getUserinfoEndpoint(), OIDCLoginProtocolService.userInfoUrl(UriBuilder.fromUri(OAuthClient.AUTH_SERVER_ROOT)).build("test").toString());
             Assert.assertEquals(oidcConfig.getJwksUri(), oauth.getCertsUrl("test"));
 
+            String registrationUri = UriBuilder
+                    .fromUri(OAuthClient.AUTH_SERVER_ROOT)
+                    .path(RealmsResource.class)
+                    .path(RealmsResource.class, "getClientsService")
+                    .path(ClientRegistrationService.class, "provider")
+                    .build("test", OIDCClientRegistrationProviderFactory.ID)
+                    .toString();
+            Assert.assertEquals(oidcConfig.getRegistrationEndpoint(), registrationUri);
+
             // Support standard + implicit + hybrid flow
             assertContains(oidcConfig.getResponseTypesSupported(), OAuth2Constants.CODE, OIDCResponseType.ID_TOKEN, "id_token token", "code id_token", "code token", "code id_token token");
             assertContains(oidcConfig.getGrantTypesSupported(), OAuth2Constants.AUTHORIZATION_CODE, OAuth2Constants.IMPLICIT);
             assertContains(oidcConfig.getResponseModesSupported(), "query", "fragment");
 
-            Assert.assertNames(oidcConfig.getSubjectTypesSupported(), "public");
+            Assert.assertNames(oidcConfig.getSubjectTypesSupported(), "pairwise", "public");
             Assert.assertNames(oidcConfig.getIdTokenSigningAlgValuesSupported(), Algorithm.RS256.toString());
             Assert.assertNames(oidcConfig.getUserInfoSigningAlgValuesSupported(), Algorithm.RS256.toString());
             Assert.assertNames(oidcConfig.getRequestObjectSigningAlgValuesSupported(), Algorithm.none.toString(), Algorithm.RS256.toString());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/jetty-web.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/jetty-web.xml
new file mode 100644
index 0000000..8c59313
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/jetty-web.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8180/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
+</Configure>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/keycloak.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/keycloak.json
new file mode 100644
index 0000000..e00b8fc
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/keycloak.json
@@ -0,0 +1,11 @@
+{
+  "realm" : "demo",
+  "resource" : "basic-auth-service",
+  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+  "auth-server-url": "/auth",
+  "ssl-required" : "external",
+  "enable-basic-auth" : "true",
+  "credentials": {
+    "secret": "password"
+  }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/keycloak-relative.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/keycloak-relative.json
new file mode 100644
index 0000000..e00b8fc
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/keycloak-relative.json
@@ -0,0 +1,11 @@
+{
+  "realm" : "demo",
+  "resource" : "basic-auth-service",
+  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+  "auth-server-url": "/auth",
+  "ssl-required" : "external",
+  "enable-basic-auth" : "true",
+  "credentials": {
+    "secret": "password"
+  }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/web.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/web.xml
new file mode 100644
index 0000000..0ea56f4
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/basic-auth/WEB-INF/web.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+
+    <module-name>basic-auth</module-name>
+
+    <security-constraint>
+        <web-resource-collection>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <!--        <user-data-constraint>
+                    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+                </user-data-constraint>  -->
+        <auth-constraint>
+            <role-name>user</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+    <login-config>
+        <auth-method>KEYCLOAK</auth-method>
+        <realm-name>demo</realm-name>
+    </login-config>
+
+    <security-role>
+        <role-name>user</role-name>
+    </security-role>
+</web-app>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-portal/WEB-INF/keycloak.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-portal/WEB-INF/keycloak.json
index b75c1d5..32703f9 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-portal/WEB-INF/keycloak.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-portal/WEB-INF/keycloak.json
@@ -1,10 +1,10 @@
 {
     "realm": "demo",
     "resource": "customer-portal",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "auth-server-url": "http://localhost:8180/auth",
+    "auth-server-url": "http://localhostt:8180/auth",
     "ssl-required" : "external",
     "expose-token": true,
+    "min-time-between-jwks-requests": 120,
     "credentials": {
         "secret": "password"
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/demorealm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/demorealm.json
index 9a4a7f6..0272584 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/demorealm.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/demorealm.json
@@ -226,6 +226,15 @@
                 "/oauth-client-cdi/*"
             ],
             "secret": "password"
+        },
+        {
+            "clientId": "basic-auth-service",
+            "standardFlowEnabled": false,
+            "directAccessGrantsEnabled": true,
+            "enabled": true,
+            "adminUrl": "/basic-auth",
+            "baseUrl": "/basic-auth",
+            "secret": "password"
         }
     ]
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/input-portal/WEB-INF/keycloak.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/input-portal/WEB-INF/keycloak.json
index a934e97..eecc24b 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/input-portal/WEB-INF/keycloak.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/input-portal/WEB-INF/keycloak.json
@@ -1,9 +1,9 @@
 {
   "realm" : "demo",
   "resource" : "input-portal",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url" : "http://${my.host.name}:8180/auth",
   "ssl-required" : "external",
+  "min-time-between-jwks-requests": 120,
   "credentials" : {
       "secret": "password"
    }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/token-min-ttl/WEB-INF/keycloak.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/token-min-ttl/WEB-INF/keycloak.json
index 85eb9a7..b86e018 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/token-min-ttl/WEB-INF/keycloak.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/token-min-ttl/WEB-INF/keycloak.json
@@ -1,11 +1,11 @@
 {
   "realm": "demo",
   "resource": "token-min-ttl",
-  "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
   "auth-server-url": "http://localhost:8180/auth",
   "ssl-required" : "external",
   "credentials": {
     "secret": "password"
   },
-  "token-minimum-time-to-live": 120
+  "token-minimum-time-to-live": 120,
+  "min-time-between-jwks-requests": 120
 }
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/token-min-ttl/WEB-INF/web.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/token-min-ttl/WEB-INF/web.xml
index f8110bc..86d07f5 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/token-min-ttl/WEB-INF/web.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/token-min-ttl/WEB-INF/web.xml
@@ -68,6 +68,12 @@
             <url-pattern>/error.html</url-pattern>
         </web-resource-collection>
     </security-constraint>
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Unsecured</web-resource-name>
+            <url-pattern>/unsecured/*</url-pattern>
+        </web-resource-collection>
+    </security-constraint>
 
     <login-config>
         <auth-method>KEYCLOAK</auth-method>
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/testrealm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/testrealm.json
index bc5b2a7..b20eb5d 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/testrealm.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/testrealm.json
@@ -95,5 +95,11 @@
                 "roles": ["customer-user"]
             }
         ]
+    },
+    "attributes": {
+        "string-attr": "foo",
+        "int-attr": "123",
+        "long-attr": "1234567890123456",
+        "bool-attr": "true"
     }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties b/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties
index 04c79fe..ce33acf 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties
@@ -61,3 +61,5 @@ log4j.logger.org.hibernate=off
 log4j.logger.org.jboss.resteasy=warn
 log4j.logger.org.apache.directory.api=warn
 log4j.logger.org.apache.directory.server.core=warn
+
+log4j.logger.org.keycloak.authentication.authenticators.browser.IdentityProviderAuthenticator=trace
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPDefaultAuthzConfigAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPDefaultAuthzConfigAdapterTest.java
new file mode 100644
index 0000000..6d63c38
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPDefaultAuthzConfigAdapterTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.adapter.example.authorization;
+
+import org.keycloak.testsuite.adapter.example.authorization.AbstractDefaultAuthzConfigAdapterTest;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+@AppServerContainer("app-server-eap")
+//@AdapterLibsLocationProperty("adapter.libs.wildfly")
+public class EAPDefaultAuthzConfigAdapterTest extends AbstractDefaultAuthzConfigAdapterTest {
+
+}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPPhotozExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPPhotozExampleAdapterTest.java
new file mode 100644
index 0000000..07b9844
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPPhotozExampleAdapterTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.adapter.example.authorization;
+
+import org.keycloak.testsuite.adapter.example.authorization.AbstractPhotozExampleAdapterTest;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+@AppServerContainer("app-server-eap")
+//@AdapterLibsLocationProperty("adapter.libs.wildfly")
+public class EAPPhotozExampleAdapterTest extends AbstractPhotozExampleAdapterTest {
+
+}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPServletAuthzAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPServletAuthzAdapterTest.java
new file mode 100644
index 0000000..3c789a4
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPServletAuthzAdapterTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.adapter.example.authorization;
+
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.keycloak.testsuite.adapter.example.authorization.AbstractDefaultAuthzConfigAdapterTest;
+import org.keycloak.testsuite.adapter.example.authorization.AbstractServletAuthzAdapterTest;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+@RunAsClient
+@AppServerContainer("app-server-eap")
+//@AdapterLibsLocationProperty("adapter.libs.wildfly")
+public class EAPServletAuthzAdapterTest extends AbstractServletAuthzAdapterTest {
+
+}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/pom.xml
index 15fc1c4..5a2a2f3 100644
--- a/testsuite/integration-arquillian/tests/other/adapters/pom.xml
+++ b/testsuite/integration-arquillian/tests/other/adapters/pom.xml
@@ -53,7 +53,10 @@
         <app.server.memory.settings>-Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m</app.server.memory.settings>
         
         <app.server.ssl.required>false</app.server.ssl.required>
-        
+
+        <settings.path></settings.path>
+        <repo.url></repo.url>
+
         <adapter.test.props>
             -Dapp.server.base.url=http://localhost:${app.server.http.port}
             -Dauth.server.base.url=http://localhost:${auth.server.http.port}
@@ -63,11 +66,14 @@
             -Dauth.server.ssl.required=${auth.server.ssl.required}
             -Dmy.host.name=localhost
             -Djava.security.krb5.conf=${project.build.directory}/dependency/kerberos/test-krb5.conf
+            -Dkie.maven.settings.custom=${settings.path}
+            -Drepo.url=${repo.url}
         </adapter.test.props>
         
         <app.server.home>${containers.home}/app-server-${app.server}</app.server.home>
         <adapter.config.bundled>true</adapter.config.bundled>
-        
+        <examples.basedir>${main.basedir}/examples</examples.basedir>
+
     </properties>
         
     <modules>
@@ -88,6 +94,23 @@
             <build>
                 <plugins>
                     <plugin>
+                        <groupId>org.commonjava.maven.plugins</groupId>
+                        <artifactId>directory-maven-plugin</artifactId>
+                        <version>0.1</version>
+                        <executions>
+                            <execution>
+                                <id>directories</id>
+                                <goals>
+                                    <goal>highest-basedir</goal>
+                                </goals>
+                                <phase>initialize</phase>
+                                <configuration>
+                                    <property>main.basedir</property>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
                         <groupId>org.codehaus.mojo</groupId>
                         <artifactId>xml-maven-plugin</artifactId>
                         <executions>
@@ -311,7 +334,7 @@
                                     </configuration>
                                 </execution>                            
                                 <execution>
-                                    <id>example-realms</id>
+                                    <id>test-apps-realms</id>
                                     <phase>generate-test-resources</phase>
                                     <goals>
                                         <goal>unpack</goal>
@@ -319,13 +342,6 @@
                                     <configuration>
                                         <artifactItems>
                                             <artifactItem>
-                                                <groupId>org.keycloak</groupId>
-                                                <artifactId>keycloak-examples-dist</artifactId>
-                                                <version>${project.version}</version>
-                                                <type>zip</type>
-                                                <includes>**/*realm.json,**/testsaml.json</includes>
-                                            </artifactItem>
-                                            <artifactItem>
                                                 <groupId>org.keycloak.testsuite</groupId>
                                                 <artifactId>integration-arquillian-test-apps-dist</artifactId>
                                                 <version>${project.version}</version>
@@ -336,9 +352,35 @@
                                         <outputDirectory>${examples.home}</outputDirectory>
                                         <overWriteIfNewer>true</overWriteIfNewer>
                                     </configuration>
-                                </execution>                            
+                                </execution>
+                            </executions>
+                        </plugin>
+                        <plugin>
+                            <artifactId>maven-resources-plugin</artifactId>
+                            <executions>
+                                <execution>
+                                    <id>example-realms</id>
+                                    <phase>generate-test-resources</phase>
+                                    <goals>
+                                        <goal>copy-resources</goal>
+                                    </goals>
+                                    <configuration>
+                                        <outputDirectory>${examples.home}/example-realms</outputDirectory>
+                                        <overWriteIfNewer>true</overWriteIfNewer>
+                                        <resources>
+                                            <resource>
+                                                <directory>${examples.basedir}</directory>
+                                                <filtering>true</filtering>
+                                                <includes>
+                                                    <include>**/*realm.json</include>
+                                                    <include>**/testsaml.json</include>
+                                                </includes>
+                                            </resource>
+                                        </resources>
+                                    </configuration>
+                                </execution>
                             </executions>
-                        </plugin>            
+                        </plugin>
                         <plugin>
                             <artifactId>maven-surefire-plugin</artifactId>
                             <configuration>
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/clients/ClientAuthorizationServicesAvailableTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/clients/ClientAuthorizationServicesAvailableTest.java
new file mode 100644
index 0000000..0dcf08b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/clients/ClientAuthorizationServicesAvailableTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.console.clients;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.junit.Test;
+import org.keycloak.common.Profile;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.testsuite.ProfileAssume;
+import org.keycloak.testsuite.console.page.clients.settings.ClientSettings;
+import org.openqa.selenium.By;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.keycloak.testsuite.auth.page.login.Login.OIDC;
+
+/**
+ *
+ * @author <a href="mailto:vramik@redhat.com">Vlastislav Ramik</a>
+ */
+public class ClientAuthorizationServicesAvailableTest extends AbstractClientTest {
+
+    private ClientRepresentation newClient;
+
+    @Page
+    private ClientSettings clientSettingsPage;
+
+    @Test
+    public void authzServicesAvailable() {
+        ProfileAssume.assumePreview();
+
+        newClient = createClientRep("oidc-public", OIDC);
+        createClient(newClient);
+        assertEquals("oidc-public", clientSettingsPage.form().getClientId());
+
+        assertTrue(driver.findElement(By.xpath("//*[@for='authorizationServicesEnabled']")).isDisplayed());
+    }
+
+    @Test
+    public void authzServicesUnavailable() throws InterruptedException {
+        ProfileAssume.assumePreviewDisabled();
+
+        newClient = createClientRep("oidc-public", OIDC);
+        createClient(newClient);
+        assertEquals("oidc-public", clientSettingsPage.form().getClientId());
+
+        assertFalse(driver.findElement(By.xpath("//*[@for='authorizationServicesEnabled']")).isDisplayed());
+
+    }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/pom.xml b/testsuite/integration-arquillian/tests/other/pom.xml
index 6b0f83c..b280525 100644
--- a/testsuite/integration-arquillian/tests/other/pom.xml
+++ b/testsuite/integration-arquillian/tests/other/pom.xml
@@ -38,8 +38,9 @@
 
     <modules>
         <module>adapters</module>
+        <module>sssd</module>
     </modules>
-    
+
     <build>
         <pluginManagement>
             <plugins>
@@ -65,7 +66,7 @@
                             </configuration>
                         </execution>
                     </executions>
-                </plugin> 
+                </plugin>
                 <plugin>
                     <artifactId>maven-resources-plugin</artifactId>
                     <executions>
diff --git a/testsuite/integration-arquillian/tests/other/sssd/pom.xml b/testsuite/integration-arquillian/tests/other/sssd/pom.xml
new file mode 100644
index 0000000..3388822
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/sssd/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>integration-arquillian-tests-other</artifactId>
+        <groupId>org.keycloak.testsuite</groupId>
+        <version>2.2.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>integration-arquillian-tests-sssd</artifactId>
+
+    <name>SSSD tests</name>
+
+    <properties>
+        <exclude.sssd>**/sssd/**/*Test.java</exclude.sssd>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>${exclude.sssd}</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+        </plugins>
+
+    </build>
+
+    <profiles>
+        <profile>
+            <id>sssd-testing</id>
+            <properties>
+                <exclude.sssd>-</exclude.sssd>
+            </properties>
+        </profile>
+    </profiles>
+
+</project>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/sssd/README.md b/testsuite/integration-arquillian/tests/other/sssd/README.md
new file mode 100644
index 0000000..03d73a0
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/sssd/README.md
@@ -0,0 +1,27 @@
+What is this module about?
+-------------------------
+
+This module containes integration tests for testing the SSSD features of Keycloak.
+
+Prerequisites
+-------------
+
+To run tests inside this module, one needs to have a linux machine configured as an `IPA` client having sssd
+  service started with infopipe support.
+
+How does one run the tests?
+--------------------------
+
+*All the commands are intended to be run from the root `keycloak` project directory.*
+
+First build the distribution of keycloak:
+`mvn clean install -B -DskipTests -Pdistribution`
+
+It may fail in the end, but it's not a problem as far as it creates a zip distribution of Keycloak inside
+distribution/server-dist/target.
+
+Then build the integration-arquillian-servers-auth-server-wildfly artifact:
+`mvn clean install -B -Pauth-server-wildfly -f testsuite/integration-arquillian/servers/pom.xml`
+
+And then, finally, it's possible to run the tests:
+`mvn test -f testsuite/integration-arquillian/tests/other/sssd/ -Pauth-server-wildfly -Psssd-testing`
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/sssd/src/test/java/org/keycloak/testsuite/sssd/SSSDTest.java b/testsuite/integration-arquillian/tests/other/sssd/src/test/java/org/keycloak/testsuite/sssd/SSSDTest.java
new file mode 100644
index 0000000..81ffa98
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/sssd/src/test/java/org/keycloak/testsuite/sssd/SSSDTest.java
@@ -0,0 +1,174 @@
+package org.keycloak.testsuite.sssd;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.representations.idm.GroupRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserFederationProviderRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.Assert;
+import org.keycloak.testsuite.AssertEvents;
+import org.keycloak.testsuite.pages.AccountPasswordPage;
+import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
+import org.keycloak.testsuite.pages.LoginPage;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class SSSDTest extends AbstractKeycloakTest {
+
+    private static final String DISPLAY_NAME = "Test user federation";
+    private static final String PROVIDER_NAME = "sssd";
+    private static final String REALM_NAME = "test";
+
+    private static final String USERNAME = "emily";
+    private static final String PASSWORD = "emily123";
+    private static final String DISABLED_USER = "david";
+    private static final String DISABLED_USER_PASSWORD = "emily123";
+
+    private static final String DEFINITELY_NOT_PASSWORD = "not" + PASSWORD;
+
+    private static final String ADMIN_USERNAME = "admin";
+    private static final String ADMIN_PASSWORD = "password";
+
+    @Page
+    protected LoginPage accountLoginPage;
+
+    @Page
+    protected AccountPasswordPage changePasswordPage;
+
+    @Page
+    protected AccountUpdateProfilePage profilePage;
+
+    @Rule
+    public AssertEvents events = new AssertEvents(this);
+
+    @Override
+    public void addTestRealms(List<RealmRepresentation> testRealms) {
+        RealmRepresentation realm = new RealmRepresentation();
+
+        realm.setRealm(REALM_NAME);
+        realm.setEnabled(true);
+
+        testRealms.add(realm);
+    }
+
+    @Before
+    public void createUserFederation() {
+        UserFederationProviderRepresentation userFederation = new UserFederationProviderRepresentation();
+
+        Map<String, String> config = new HashMap<>();
+        userFederation.setConfig(config);
+
+        userFederation.setDisplayName(DISPLAY_NAME);
+        userFederation.setPriority(0);
+        userFederation.setProviderName(PROVIDER_NAME);
+
+        adminClient.realm(REALM_NAME).userFederation().create(userFederation);
+    }
+
+    @Test
+    public void testWrongUser() {
+        log.debug("Testing wrong password for user " + USERNAME);
+
+        driver.navigate().to(getAccountUrl());
+        Assert.assertEquals("Browser should be on login page now", "Log in to " + REALM_NAME, driver.getTitle());
+        accountLoginPage.login(USERNAME, DEFINITELY_NOT_PASSWORD);
+
+        Assert.assertEquals("Invalid username or password.", accountLoginPage.getError());
+    }
+
+    @Test
+    public void testDisabledUser() {
+        log.debug("Testing disabled user " + USERNAME);
+
+        driver.navigate().to(getAccountUrl());
+        Assert.assertEquals("Browser should be on login page now", "Log in to " + REALM_NAME, driver.getTitle());
+        accountLoginPage.login(DISABLED_USER, DISABLED_USER_PASSWORD);
+
+        Assert.assertEquals("Invalid username or password.", accountLoginPage.getError());
+    }
+
+    @Test
+    public void testAdmin() {
+        log.debug("Testing wrong password for user " + ADMIN_USERNAME);
+
+        driver.navigate().to(getAccountUrl());
+        Assert.assertEquals("Browser should be on login page now", "Log in to " + REALM_NAME, driver.getTitle());
+        accountLoginPage.login(ADMIN_USERNAME, ADMIN_PASSWORD);
+
+        Assert.assertEquals("Unexpected error when handling authentication request to identity provider.", accountLoginPage.getInstruction());
+    }
+
+    @Test
+    public void testExistingUserLogIn() {
+        log.debug("Testing correct password");
+
+        driver.navigate().to(getAccountUrl());
+        Assert.assertEquals("Browser should be on login page now", "Log in to " + REALM_NAME, driver.getTitle());
+        accountLoginPage.login(USERNAME, PASSWORD);
+        Assert.assertEquals("Browser should be on account page now, logged in", "Keycloak Account Management", driver.getTitle());
+
+        testUserGroups();
+    }
+
+    @Test
+    public void changeReadOnlyProfile() throws Exception {
+
+        profilePage.open();
+        accountLoginPage.login(USERNAME, PASSWORD);
+
+        Assert.assertEquals("emily", profilePage.getUsername());
+        Assert.assertEquals("Emily", profilePage.getFirstName());
+        Assert.assertEquals("Jones", profilePage.getLastName());
+        Assert.assertEquals("emily@jones.com", profilePage.getEmail());
+
+        profilePage.updateProfile("New first", "New last", "new@email.com");
+
+        Assert.assertEquals("You can't update your account as it is read only.", profilePage.getError());
+    }
+
+    @Test
+    public void changeReadOnlyPassword() {
+        changePasswordPage.open();
+        accountLoginPage.login(USERNAME, PASSWORD);
+
+        changePasswordPage.changePassword(PASSWORD, "new-password", "new-password");
+        Assert.assertEquals("You can't update your password as your account is read only.", profilePage.getError());
+    }
+
+
+    private void testUserGroups() {
+        log.debug("Testing user groups");
+
+        List<UserRepresentation> users = adminClient.realm(REALM_NAME).users().search(USERNAME, 0, 1);
+
+        Assert.assertTrue("There must be at least one user", users.size() > 0);
+        Assert.assertEquals("Exactly our test user", USERNAME, users.get(0).getUsername());
+
+        List<GroupRepresentation> groups = adminClient.realm(REALM_NAME).users().get(users.get(0).getId()).groups();
+
+        Assert.assertEquals("User must have exactly two groups", 2, groups.size());
+        boolean wrongGroup = false;
+        for (GroupRepresentation group : groups) {
+            if (!group.getName().equalsIgnoreCase("ipausers") && !group.getName().equalsIgnoreCase("testgroup")) {
+                wrongGroup = true;
+                break;
+            }
+        }
+
+        Assert.assertFalse("There exists some wrong group", wrongGroup);
+    }
+
+    private String getAccountUrl() {
+        return getAuthRoot() + "/auth/realms/" + REALM_NAME + "/account";
+    }
+
+    private String getAuthRoot() {
+        return suiteContext.getAuthServerInfo().getContextRoot().toString();
+    }
+}
diff --git a/testsuite/integration-arquillian/test-utils/src/main/java/org/keycloak/testsuite/util/junit/AggregateResultsReporter.java b/testsuite/integration-arquillian/test-utils/src/main/java/org/keycloak/testsuite/util/junit/AggregateResultsReporter.java
index a0809c1..2b1bf6c 100644
--- a/testsuite/integration-arquillian/test-utils/src/main/java/org/keycloak/testsuite/util/junit/AggregateResultsReporter.java
+++ b/testsuite/integration-arquillian/test-utils/src/main/java/org/keycloak/testsuite/util/junit/AggregateResultsReporter.java
@@ -86,13 +86,24 @@ public class AggregateResultsReporter extends RunListener {
     }
 
     private File createReportFile() throws Exception {
-        PropertiesConfiguration config = new PropertiesConfiguration(System.getProperty("testsuite.constants"));
-        config.setThrowExceptionOnMissing(true);
+        String logDirPath = null;
 
-        final File logDir = new File(config.getString("log-dir"));
+        try {
+            PropertiesConfiguration config = new PropertiesConfiguration(System.getProperty("testsuite.constants"));
+            config.setThrowExceptionOnMissing(true);
+            logDirPath = config.getString("log-dir");
+        } catch (Exception e) {
+            logDirPath = System.getProperty("project.build.directory");
+            if (logDirPath == null) {
+                throw new RuntimeException("Could not determine the path to the log directory.");
+            }
+            logDirPath += File.separator + "surefire-reports";
+        }
+
+        final File logDir = new File(logDirPath);
         logDir.mkdirs();
 
-        final File reportFile = new File(logDir, "junit-report.xml").getAbsoluteFile();
+        final File reportFile = new File(logDir, "junit-single-report.xml").getAbsoluteFile();
         reportFile.createNewFile();
 
         return reportFile;
diff --git a/themes/src/main/resources/theme/base/account/messages/messages_en.properties b/themes/src/main/resources/theme/base/account/messages/messages_en.properties
index 8ed1de6..1f42008 100755
--- a/themes/src/main/resources/theme/base/account/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/account/messages/messages_en.properties
@@ -159,5 +159,6 @@ locale_fr=Fran\u00e7ais
 locale_it=Italian
 locale_ja=\u65E5\u672C\u8A9E
 locale_no=Norsk
+locale_lt=Lietuvi\u0173
 locale_pt-BR=Portugu\u00EAs (Brasil)
-locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439
+locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/account/messages/messages_lt.properties b/themes/src/main/resources/theme/base/account/messages/messages_lt.properties
new file mode 100644
index 0000000..f9edf13
--- /dev/null
+++ b/themes/src/main/resources/theme/base/account/messages/messages_lt.properties
@@ -0,0 +1,153 @@
+doSave=Saugoti
+doCancel=At\u0161aukti
+
+doLogOutAllSessions=Atjungti visas sesijas
+doRemove=\u0160alinti
+doAdd=Prid\u0117ti
+doSignOut=Atsijungti
+
+editAccountHtmlTitle=Redaguoti paskyr\u0105
+federatedIdentitiesHtmlTitle=Susietos paskyros
+accountLogHtmlTitle=Paskyros \u017Eurnalas
+changePasswordHtmlTitle=Keisti slapta\u017Eod\u012F
+sessionsHtmlTitle=Prisijungimo sesijos
+accountManagementTitle=Keycloak Naudotoj\u0173 Administravimas
+authenticatorTitle=Autentifikatorius
+applicationsHtmlTitle=Programos
+
+authenticatorCode=Vienkartinis kodas
+email=El. pa\u0161tas
+firstName=Vardas
+givenName=Pavard\u0117
+fullName=Pilnas vardas
+lastName=Pavard\u0117
+familyName=Pavard\u0117
+password=Slapta\u017Eodis
+passwordConfirm=Pakartotas slapta\u017Eodis
+passwordNew=Naujas slapta\u017Eodis
+username=Naudotojo vardas
+address=Adresas
+street=Gatv\u0117
+locality=Miestas arba vietov\u0117
+region=Rajonas
+postal_code=Pa\u0161to kodas
+country=\u0160alis
+emailVerified=El. pa\u0161to adresas patvirtintas
+gssDelegationCredential=GSS prisijungimo duomen\u0173 delegavimas
+
+role_admin=Administratorius
+role_realm-admin=Srities administravimas
+role_create-realm=Kurti srit\u012F
+role_view-realm=Per\u017Ei\u016Br\u0117ti srit\u012F
+role_view-users=Per\u017Ei\u016Br\u0117ti naudotojus
+role_view-applications=Per\u017Ei\u016Br\u0117ti programas
+role_view-clients=Per\u017Ei\u016Br\u0117ti klientines programas
+role_view-events=Per\u017Ei\u016Br\u0117ti \u012Fvyki\u0173 \u017Eurnal\u0105
+role_view-identity-providers=Per\u017Ei\u016Br\u0117ti tapatyb\u0117s teik\u0117jus
+role_manage-realm=Valdyti sritis
+role_manage-users=Valdyti naudotojus
+role_manage-applications=Valdyti programas
+role_manage-identity-providers=Valdyti tapatyb\u0117s teik\u0117jus
+role_manage-clients=Valdyti programas
+role_manage-events=Valdyti \u012Fvykius
+role_view-profile=Per\u017Ei\u016Br\u0117ti paskyr\u0105
+role_manage-account=Valdyti paskyr\u0105
+role_read-token=Skaityti prieigos rak\u0161\u0105
+role_offline-access=Darbas neprisijungus
+role_uma_authorization=\u012Egauti UMA autorizavimo teises
+client_account=Paskyra
+client_security-admin-console=Saugumo administravimo konsol\u0117
+client_admin-cli=Administravimo CLI
+client_realm-management=Srities valdymas
+client_broker=Tarpininkas
+
+
+requiredFields=Privalomi laukai
+allFieldsRequired=Visi laukai yra privalomi
+
+backToApplication=&laquo; Gr\u012F\u017Eti \u012F program\u0105
+backTo=Atgal \u012F {0}
+
+date=Data
+event=\u012Evykis
+ip=IP
+client=Klientas
+clients=Klientai
+details=Detaliau
+started=Suk\u016Brimo laikas
+lastAccess=V\u0117liausia prieiga
+expires=Galioja iki
+applications=Programos
+
+account=Paskyra
+federatedIdentity=Susieta tapatyb\u0117
+authenticator=Autentifikatorius
+sessions=Sesijos
+log=\u012Evykiai
+
+application=Programa
+availablePermissions=Galimos teis\u0117s
+grantedPermissions=\u012Egalintos teis\u0117s
+grantedPersonalInfo=\u012Egalinta asmenin\u0117 informacija
+additionalGrants=Papildomi \u012Fgaliojimai
+action=Veiksmas
+inResource=yra
+fullAccess=Pilna prieiga
+offlineToken=Re\u017Eimo neprisijungus raktas (token)
+revoke=At\u0161aukti \u012Fgaliojim\u0105
+
+configureAuthenticators=Sukonfig\u016Bruotas autentifikatorius
+mobile=Mobilus
+totpStep1=\u012Ediekite <a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> arba Google Authenticator savo \u012Frenginyje. Program\u0117l\u0117s prieinamos <a href="https://play.google.com">Google Play</a> ir Apple App Store.
+totpStep2=Atidarykite program\u0117l\u0119 ir nuskenuokite barkod\u0105 arba \u012Fveskite kod\u0105.
+totpStep3=\u012Eveskite program\u0117l\u0117je sugeneruot\u0105 vien\u0105 kart\u0105 galiojant\u012F kod\u0105 ir paspauskite Saugoti nor\u0117dami prisijungti.
+
+missingUsernameMessage=Pra\u0161ome \u012Fvesti naudotojo vard\u0105.
+missingFirstNameMessage=Pra\u0161ome \u012Fvesti vard\u0105.
+invalidEmailMessage=Neteisingas el. pa\u0161to adresas.
+missingLastNameMessage=Pra\u0161ome \u012Fvesti pavard\u0119.
+missingEmailMessage=Pra\u0161ome \u012Fvesti el. pa\u0161to adres\u0105.
+missingPasswordMessage=Pra\u0161ome \u012Fvesti slapta\u017Eod\u012F.
+notMatchPasswordMessage=Slapta\u017Eod\u017Eiai nesutampa.
+
+missingTotpMessage=Pra\u0161ome \u012Fvesti autentifikacijos kod\u0105.
+invalidPasswordExistingMessage=Neteisingas dabartinis slapta\u017Eodis.
+invalidPasswordConfirmMessage=Pakartotas slapta\u017Eodis nesutampa.
+invalidTotpMessage=Neteisingas autentifikacijos kodas.
+
+usernameExistsMessage=Toks naudotojas jau egzistuoja.
+emailExistsMessage=El. pa\u0161to adresas jau egzistuoja.
+
+readOnlyUserMessage=Tik skaitymui sukonfig\u016Bruotos paskyros duomen\u0173 atnaujinti neleid\u017Eiama.
+readOnlyPasswordMessage=Tik skaitymui sukonfig\u016Bruotos paskyros slapta\u017Eod\u017Eio atnaujinti neleid\u017Eiama.
+
+successTotpMessage=Mobilus autentifikatorius sukonfig\u016Bruotas.
+successTotpRemovedMessage=Mobilus autentifikatorius pa\u0161alintas.
+
+successGrantRevokedMessage=\u012Egalinimas pa\u0161alintas s\u0117kmingai.
+
+accountUpdatedMessage=J\u016Bs\u0173 paskyros duomenys s\u0117kmingai atnaujinti.
+accountPasswordUpdatedMessage=J\u016Bs\u0173 paskyros slapta\u017Eodis pakeistas.
+
+missingIdentityProviderMessage=Nenurodytas tapatyb\u0117s teik\u0117jas.
+invalidFederatedIdentityActionMessage=Neteisingas arba ne\u017Einomas veiksmas.
+identityProviderNotFoundMessage=Nurodytas tapatyb\u0117s teik\u0117jas nerastas.
+federatedIdentityLinkNotActiveMessage=Nurodyta susieta tapatyb\u0117 neaktyvi.
+federatedIdentityRemovingLastProviderMessage=J\u016Bs negalite pa\u0161alinti paskutinio tapatyb\u0117s teik\u0117jo s\u0105sajos, nes J\u016Bs neturite nusistat\u0119 paskyros slapta\u017Eod\u017Eio.
+identityProviderRedirectErrorMessage=Klaida nukreipiant \u012F tapatyb\u0117s teik\u0117jo puslap\u012F.
+identityProviderRemovedMessage=Tapatyb\u0117s teik\u0117jas s\u0117kmingai pa\u0161alintas.
+identityProviderAlreadyLinkedMessage=Susieta tapatyb\u0117 i\u0161 {0} jau susieta su kita paskyra.
+staleCodeAccountMessage=Puslapio galiojimas baig\u0117si. Bandykite dar kart\u0105.
+consentDenied=Prieiga draud\u017Eiama.
+
+accountDisabledMessage=Paskyros galiojimas sustabdytas, kreipkit\u0117s \u012F administratori\u0173.
+
+accountTemporarilyDisabledMessage=Paskyros galiojimas laikinai sustabdytas. Kreipkit\u0117s \u012F administratori\u0173 arba pabandykite v\u0117liau.
+invalidPasswordMinLengthMessage=Per trumpas slapta\u017Eodis: ma\u017Eiausias ilgis {0}.
+invalidPasswordMinLowerCaseCharsMessage=Neteisingas slapta\u017Eodis: privaloma \u012Fvesti {0} ma\u017E\u0105j\u0105 raid\u0119.
+invalidPasswordMinDigitsMessage=Neteisingas slapta\u017Eodis: privaloma \u012Fvesti {0} skaitmen\u012F.
+invalidPasswordMinUpperCaseCharsMessage=Neteisingas slapta\u017Eodis: privaloma \u012Fvesti {0} did\u017Ei\u0105j\u0105 raid\u0119.
+invalidPasswordMinSpecialCharsMessage=Neteisingas slapta\u017Eodis: privaloma \u012Fvesti {0} special\u0173 simbol\u012F.
+invalidPasswordNotUsernameMessage=Neteisingas slapta\u017Eodis: slapta\u017Eodis negali sutapti su naudotojo vardu.
+invalidPasswordRegexPatternMessage=Neteisingas slapta\u017Eodis: slapta\u017Eodis netenkina regex taisykl\u0117s(i\u0173).
+invalidPasswordHistoryMessage=Neteisingas slapta\u017Eodis: slapta\u017Eodis negali sutapti su prie\u0161 tai buvusiais {0} slapta\u017Eod\u017Eiais.
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/account/theme.properties b/themes/src/main/resources/theme/base/account/theme.properties
index deb2dc9..2cf724d 100644
--- a/themes/src/main/resources/theme/base/account/theme.properties
+++ b/themes/src/main/resources/theme/base/account/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,ja,pt-BR,ru,no
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,lt,no,pt-BR,ru
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index 2ebed9f..d3cdd9e 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -164,6 +164,12 @@ usermodel.clientRoleMapping.rolePrefix.label=Client Role prefix
 usermodel.clientRoleMapping.rolePrefix.tooltip=A prefix for each client role (optional).
 usermodel.realmRoleMapping.rolePrefix.label=Realm Role prefix
 usermodel.realmRoleMapping.rolePrefix.tooltip=A prefix for each Realm Role (optional).
+sectorIdentifierUri.label=Sector Identifier URI
+sectorIdentifierUri.tooltip=Providers that use pairwise sub values and support Dynamic Client Registration SHOULD use the sector_identifier_uri parameter. It provides a way for a group of websites under common administrative control to have consistent pairwise sub values independent of the individual domain names. It also provides a way for Clients to change redirect_uri domains without having to reregister all of their users.
+pairwiseSubAlgorithmSalt.label=Salt
+pairwiseSubAlgorithmSalt.tooltip=Salt used when calculating the pairwise subject identifier. If left blank, a salt will be generated.
+
+
 
 # client details
 clients.tooltip=Clients are trusted browser apps and web services in a realm. These clients can request a login. You can also define client specific roles.
@@ -845,6 +851,7 @@ include-representation=Include Representation
 include-representation.tooltip=Include JSON representation for create and update requests.
 clear-admin-events.tooltip=Deletes all admin events in the database.
 server-version=Server Version
+server-profile=Server Profile
 info=Info
 providers=Providers
 server-time=Server Time
@@ -986,13 +993,13 @@ authz-required=Required
 authz-import-config.tooltip=Import a JSON file containing authorization settings for this resource server.
 
 authz-policy-enforcement-mode=Policy Enforcement Mode
-authz-policy-enforcement-mode.tooltip=The policy enforcement mode dictates how policies are enforced when evaluating authorization requests. 'Enforcing' means requests are denied by default even when there is no policy associated with a given resource. 'Permissive' means requests are allowed even when there is no policy associated with a given resource. 'Disabled' completely disables the evaluation of policies and allow access to any resource.
+authz-policy-enforcement-mode.tooltip=The policy enforcement mode dictates how policies are enforced when evaluating authorization requests. 'Enforcing' means requests are denied by default even when there is no policy associated with a given resource. 'Permissive' means requests are allowed even when there is no policy associated with a given resource. 'Disabled' completely disables the evaluation of policies and allows access to any resource.
 authz-policy-enforcement-mode-enforcing=Enforcing
 authz-policy-enforcement-mode-permissive=Permissive
 authz-policy-enforcement-mode-disabled=Disabled
 
 authz-remote-resource-management=Remote Resource Management
-authz-remote-resource-management.tooltip=Should resources be managed remotely by the resource server? If false, resources can only be managed from this admin console.
+authz-remote-resource-management.tooltip=Should resources be managed remotely by the resource server? If false, resources can be managed only from this admin console.
 
 authz-export-settings=Export Settings
 authz-export-settings.tooltip=Export and download all authorization settings for this resource server.
@@ -1035,7 +1042,7 @@ authz-policy-logic.tooltip=The logic dictates how the policy decision should be 
 authz-policy-apply-policy=Apply Policy
 authz-policy-apply-policy.tooltip=Specifies all the policies that must be applied to the scopes defined by this policy or permission.
 authz-policy-decision-strategy=Decision Strategy
-authz-policy-decision-strategy.tooltip=The decision strategy dictates how the policies associated with a given permission are evaluated and how a final decision is obtained. 'Affirmative' means that at least one policy must evaluate to a positive decision in order to the overall decision be also positive. 'Unanimous' means that all policies must evaluate to a positive decision in order to the overall decision be also positive. 'Consensus' means that the number of positive decisions must be greater than the number of negative decisions. If the number of positive and negative is the same, the final decision will be negative.
+authz-policy-decision-strategy.tooltip=The decision strategy dictates how the policies associated with a given permission are evaluated and how a final decision is obtained. 'Affirmative' means that at least one policy must evaluate to a positive decision in order for the final decision to be also positive. 'Unanimous' means that all policies must evaluate to a positive decision in order for the final decision to be also positive. 'Consensus' means that the number of positive decisions must be greater than the number of negative decisions. If the number of positive and negative is the same, the final decision will be negative.
 authz-policy-decision-strategy-affirmative=Affirmative
 authz-policy-decision-strategy-unanimous=Unanimous
 authz-policy-decision-strategy-consensus=Consensus
@@ -1059,15 +1066,15 @@ authz-policy-time-not-before.tooltip=Defines the time before which the policy MU
 authz-policy-time-not-on-after=Not On or After
 authz-policy-time-not-on-after.tooltip=Defines the time after which the policy MUST NOT be granted. Only granted if current date/time is before or equal to this value.
 authz-policy-time-day-month=Day of Month
-authz-policy-time-day-month.tooltip=Defines the day of month before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the day of month before/equal which the policy MUST be granted. In this case, the policy would be granted if current day of month is between/equal the two values you provided.
+authz-policy-time-day-month.tooltip=Defines the day of month which the policy MUST be granted. You can also provide a range by filling the second field. In this case, permission is granted only if current day of month is between or equal to the two values you provided.
 authz-policy-time-month=Month
-authz-policy-time-month.tooltip=Defines the month before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the month before/equal which the policy MUST be granted. In this case, the policy would be granted if current month is between/equal the two values you provided.
+authz-policy-time-month.tooltip=Defines the month which the policy MUST be granted. You can also provide a range by filling the second field. In this case, permission is granted only if current month is between or equal to the two values you provided.
 authz-policy-time-year=Year
-authz-policy-time-year.tooltip=Defines the year before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the year before/equal which the policy MUST be granted. In this case, the policy would be granted if current year is between/equal the two values you provided.
+authz-policy-time-year.tooltip=Defines the year which the policy MUST be granted. You can also provide a range by filling the second field. In this case, permission is granted only if current year is between or equal to the two values you provided.
 authz-policy-time-hour=Hour
-authz-policy-time-hour.tooltip=Defines the hour before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the hour before/equal which the policy MUST be granted. In this case, the policy would be granted if current hour is between/equal the two values you provided.
+authz-policy-time-hour.tooltip=Defines the hour which the policy MUST be granted. You can also provide a range by filling the second field. In this case, permission is granted only if current hour is between or equal to the two values you provided.
 authz-policy-time-minute=Minute
-authz-policy-time-minute.tooltip=Defines the minute before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the minute before/equal which the policy MUST be granted. In this case, the policy would be granted if current minute is between/equal the two values you provided.
+authz-policy-time-minute.tooltip=Defines the minute which the policy MUST be granted. You can also provide a range by filling the second field. In this case, permission is granted only if current minute is between or equal to the two values you provided.
 
 # Authz Drools Policy Detail
 authz-add-drools-policy=Add Drools Policy
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_lt.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_lt.properties
new file mode 100644
index 0000000..b65bb7c
--- /dev/null
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_lt.properties
@@ -0,0 +1,1131 @@
+consoleTitle=Keycloak administravimo konsol\u0117
+
+# Common messages
+enabled=\u012Egalintas
+name=Pavadinimas
+displayName=Rodomas pavadinimas
+displayNameHtml=Rodomas pavadinimas HTML formatu
+save=Saugoti
+cancel=At\u0161aukti
+onText=ON
+offText=OFF
+client=Klientas
+clients=Klientai
+clear=I\u0161valyti
+selectOne=Pasirinkite vien\u0105...
+
+true=Taip
+false=Ne
+
+endpoints=Prieigos adresai
+
+# Realm settings
+realm-detail.enabled.tooltip=Naudotojai ir programos prie srities gali prieiti tik tuomet, kai ji \u012Fgalinta
+realm-detail.oidc-endpoints.tooltip=Atidaromas langas su OpenID Connect prieigos URL adresais
+registrationAllowed=Naudotoj\u0173 registracija
+registrationAllowed.tooltip=\u012Egalina naudotoj\u0173 registravimosi s\u0105saj\u0105. Prisijungimo lange rodoma nuoroda \u012F registravimosi puslap\u012F.
+registrationEmailAsUsername=El. pa\u0161tas kaip naudojo vardas
+registrationEmailAsUsername.tooltip=Jei \u012Fgalintas tuomet naudotojo vardo laukas registravimosi lange yra slepiamas ir naujai besiregistruojantiems naudotojams el. pa\u0161to adresas naudojamas kaip naudotojo vardas.
+editUsernameAllowed=Naudotojo vardo redagavimas
+editUsernameAllowed.tooltip=Jei \u012Fgalintas, tuomet naudotojas gali keisti savo naudotojo vard\u0105.
+resetPasswordAllowed=Slapta\u017Eod\u017Eio priminimas
+resetPasswordAllowed.tooltip=Prisijungimo lange rodoma nuoroda pamir\u0161to slapta\u017Eod\u017Eio atk\u016Brimui.
+rememberMe=Prisiminti mane
+rememberMe.tooltip=Prisijungimo lange rodyti pasirinkim\u0105 leid\u017Eiant\u012F naudotojui likti prisijungus netgi tuomet, kai nar\u0161ykl\u0117 yra i\u0161jungiama/\u012Fjungiama tol, kol nepasibaigia prisijungimo sesija.
+verifyEmail=El. pa\u0161to patvirtinimas
+verifyEmail.tooltip=Reikalauti naudotojo patvirtinti el. pa\u0161to adres\u0105 pirmojo prisijungimo metu.
+sslRequired=Reikalauti SSL
+sslRequired.option.all=visoms u\u017Eklausoms
+sslRequired.option.external=i\u0161orin\u0117ms u\u017Eklausoms
+sslRequired.option.none=niekada
+sslRequired.tooltip=Ar HTTPS privalomas? 'niekada' - HTTPS nereikalaujamas. 'i\u0161orin\u0117ms u\u017Eklausoms' - jungiantis i\u0161 localhost ar serverio IP adres\u0173 galima prieiti ir per HTTP. 'visoms u\u017Eklausoms' - HTTPS reikalaujamas jungiantis i\u0161 vis\u0173 IP adres\u0173.
+publicKey=Vie\u0161as raktas
+privateKey=Privatus raktas
+gen-new-keys=Generuoti naujus raktus
+certificate=Sertifikatas
+host=Serveris
+smtp-host=SMTP serveris
+port=Prievadas
+smtp-port=SMTP prievadas (numatyta reik\u0161m\u0117 25)
+from=Nuo
+sender-email-addr=Siunt\u0117jo el. pa\u0161to adresas
+enable-ssl=\u012Egalinti SSL
+enable-start-tls=\u012Egalinti StartTLS
+enable-auth=\u012Egalinti autentifikacij\u0105
+username=Naudotojo vardas
+login-username=Prisijungimui naudojamas naudotojo vardas
+password=Slapta\u017Eodis
+login-password=Prisijungimui naudojamas slapta\u017Eodis
+login-theme=Prisijungimo lango tema
+login-theme.tooltip=Pasirinkite kaip atrodys J\u016Bs\u0173 prisijungimo, TOTP, teisi\u0173 suteikimo, naudotoj\u0173 registracijos ir slapta\u017Eod\u017Ei\u0173 priminimo langai.
+account-theme=Naudotojo profilio tema
+account-theme.tooltip=Pasirinkite kaip atrodys naudotojo profilio valdymo langai.
+admin-console-theme=Administravimo konsol\u0117s tema
+select-theme-admin-console=Pasirinkite kaip atrodys administravimo konsol\u0117s langai.
+email-theme=El. pa\u0161to tema
+select-theme-email=Pasirinkite kaip atrodys siun\u010Diami el. pa\u0161to lai\u0161kai.
+i18n-enabled=Daugiakalbyst\u0117s palaikymas
+supported-locales=Palaikomos kalbos
+supported-locales.placeholder=Pasirinkite arba \u012Fra\u0161ykite kalbos pavadinim\u0105
+default-locale=Numatyta kalba
+realm-cache-clear=Srities pod\u0117lis
+realm-cache-clear.tooltip=I\u0161 vis\u0173 sri\u010Di\u0173 pa\u0161alinama visa pod\u0117lyje (cache) esanti informacija
+user-cache-clear=Naudotoj\u0173 pod\u0117lis
+user-cache-clear.tooltip=I\u0161 vis\u0173 sri\u010Di\u0173 pa\u0161alinama visa naudotoj\u0173 pod\u0117lyje (cache) esanti informacija
+revoke-refresh-token=Prieigos rakt\u0105 naudoti tik kart\u0105
+revoke-refresh-token.tooltip=Jei \u012Fgalintas, tuomet atnaujinimo raktai (Refresh Token) gali b\u016Bti naudojami tik vien\u0105 kart\u0105. Kitu atveju - atnaujinimo raktai gali b\u016Bti pernaudojami daugel\u012F kart\u0173. 
+sso-session-idle=SSO sesijos neveikimo laikas
+seconds=Sekund\u0117s
+minutes=Minut\u0117s
+hours=Valandos
+days=Dienos
+sso-session-max=SSO sesijos maksimalus laikas
+sso-session-idle.tooltip=Laikas, po kurio neaktyvi sesija bus u\u017Ebaigta. Sesijos pasibaigimo metu visi raktai (Tokens) ir nar\u0161ykli\u0173 sesijos sunaikinamos.
+sso-session-max.tooltip=Laikas, po kurio prisijungimo sesija yra sunaikinama. Sesijos pasibaigimo metu visi raktai (Tokens) ir nar\u0161ykli\u0173 sesijos sunaikinamos.
+offline-session-idle=Neprisijungusios sesijos neveikimo laikas
+offline-session-idle.tooltip=Darbo neprisijungus sesijos neveikimo laikas, po kurio neaktyvi sesija bus u\u017Ebaigta. Darbo neprisijungus metu, prisijungimo raktai turi b\u016Bti atnaujinami bent kart\u0105 per nurodyt\u0105 period\u0105. Kitu atveju sesijos galiojmas bus sustabdytas.
+access-token-lifespan=Prisijungimo rakto galiojimo laikas
+access-token-lifespan.tooltip=Laikas, po kurio prisijungimui naudojamas raktas (Access Token) nustoja galioti. Rekomenduojama, kad \u0161ios reik\u0161m\u0117s galiojimas b\u016Bt\u0173 reliatyviai trumpas palyginus su SSO galiojimo laiku.
+access-token-lifespan-for-implicit-flow=Prisijungimo rakto galiojimo laikas (Implicit Flow)
+access-token-lifespan-for-implicit-flow.tooltip=Laikas, po kurio prisijungimui naudojamas OpenID Connect Implicit Flow raktas nustoja galioti. Rekomenduojama, kad \u0161ios reik\u0161m\u0117s galiojimas b\u016Bt\u0173 reliatyviai trumpas palyginus su SSO galiojimo laiku. \u0160is parametras skiriasi nuo 'Prisijungimo rakto galiojimo laikas', nes n\u0117ra galimyb\u0117s atnaujinti prieigos rakto naudojant OpenID Connect Implicit Flow.  
+client-login-timeout=Kliento prisijungimui skirtas laikas
+client-login-timeout.tooltip=Laikas, per kur\u012F klientas turi u\u017Ebaigti prisijungimo proces\u0105. Normaliu atveju reik\u0161m\u0117 tur\u0117t\u0173 b\u016Bti 1 minut\u0117.
+login-timeout=Naudotojo prisijungimui skirtas laikas
+login-timeout.tooltip=Laikas, per kur\u012F naudotojas turi u\u017Ebaigti prisijungimo proces\u0105. Rekomenduojamas pakankamai ilgas laiko tarpas. Pvz. 30 minu\u010Di\u0173 ar daugiau.
+login-action-timeout=Naudotojo prisijungimo veiksmui skirtas laikas
+login-action-timeout.tooltip=Laikas, per kur\u012F naudotojas turi u\u017Ebaigti su prisijungimu susijus\u012F veiksm\u0105. Pavyzd\u017Eiui atnaujinti slapta\u017Eod\u012F ar sukonfig\u016Bruoti TOTP. Rekomenduojamas laikas - 5 minut\u0117s ar daugiau.
+headers=Antra\u0161t\u0117s
+brute-force-detection=Grubios j\u0117gos ataka
+x-frame-options=X-Frame-Options
+x-frame-options-tooltip=Numatyta reik\u0161m\u0117 draud\u017Eia puslapius naudoti kitose svetain\u0117se per iframe (paspauskite antra\u0161t\u0119 nor\u0117dami gauti daugiau informacijos)
+content-sec-policy=Content-Security-Policy
+content-sec-policy-tooltip=Numatyta reik\u0161m\u0117 draud\u017Eia puslapius naudoti kitose svetain\u0117se per iframe (paspauskite antra\u0161t\u0119 nor\u0117dami gauti daugiau informacijos)
+content-type-options=X-Content-Type-Options
+content-type-options-tooltip=Numatyta reik\u0161m\u0117 draud\u017Eia Internet Explorer ir Google Chrome atlikti priimti kitokias MIME reik\u0161mes (MIME-sniffing) nei deklaruotas turinio tipas (content-type) (paspauskite antra\u0161t\u0119 nor\u0117dami gauti daugiau informacijos)
+max-login-failures=Maksimalus bandym\u0173 prisijungim\u0173 skai\u010Dius
+max-login-failures.tooltip=Pasiekus maksimal\u0173 nes\u0117kming\u0173 bandym\u0173 prisijungti skai\u010Di\u0173 \u012Fjungiamas specialus r\u0117\u017Eimas, kuomet laukimo intervalas yra didinamas po kiekvieno sekan\u010Dio neteisingo bandymo.
+wait-increment=Laukimo laiko didinimas po
+wait-increment.tooltip=Laikas, kur\u012F naudotojo prisijungimai yra draud\u017Eiami, kai n\u0117s\u0117kming\u0173 bandym\u0173 skai\u010Dius pasiekia nustatyt\u0105 rib\u0105
+quick-login-check-millis=Per greito bandymo prisijungti laikas milisekund\u0117mis
+quick-login-check-millis.tooltip=Jei n\u0117s\u0117kmingi bandymai prisijungti seka vienas kit\u0105 per greitai, tuomet naudotojo paskyra yra u\u017Erakinama.
+min-quick-login-wait=Per greito bandymo prisijungti u\u017Erakinimo laikas
+min-quick-login-wait.tooltip=Laikas, kur\u012F naudotojo prisijungimai yra draud\u017Eiami, kai n\u0117s\u0117kmingi bandymai prisijungti seka vienas kit\u0105 per greitai.
+max-wait=Maksimalus u\u017Erakinimo laikas
+max-wait.tooltip=Maksimalus laikas, kuomet naudotojo paskyra yra u\u017Erakinama po nes\u0117kming\u0173 bandym\u0173 prisijungti.
+failure-reset-time=Pamir\u0161ti nepavykusius prisijungimus po
+failure-reset-time.tooltip=Laikas, po kurio nepavyk\u0119 prisijungimai bus pamir\u0161ti
+realm-tab-login=Prisijungimas
+realm-tab-keys=Raktai
+realm-tab-email=El. pa\u0161tas
+realm-tab-themes=Temos
+realm-tab-cache=Pod\u0117lis
+realm-tab-tokens=Raktai
+realm-tab-client-initial-access=Pradiniai prieigos raktai
+realm-tab-security-defenses=Saugos priemon\u0117s
+realm-tab-general=Bendra informacija
+add-realm=Prid\u0117ti srit\u012F
+
+#Session settings
+realm-sessions=Srities sesijos
+revocation=At\u0161aukimai
+logout-all=Atjungti visus
+active-sessions=Aktyvios sesijos
+sessions=Sesijos
+not-before=Ne anks\u010Diau
+not-before.tooltip=At\u0161aukti visus raktus i\u0161duotus prie\u0161 nurodyt\u0105 dat\u0105.
+set-to-now=Parinkti dabartin\u0119 dat\u0105
+push=Informuoti apie at\u0161aukim\u0105
+push.tooltip=Visus klientus, kurie turi administravimo URL, informuoti apie nauj\u0105 rakt\u0173 at\u0161aukimo taisykl\u0119.
+
+#Protocol Mapper
+usermodel.prop.label=Atributas
+usermodel.prop.tooltip=S\u0105sajos UserModel atributo metodo pavadinimas. Pavyzd\u017Eiui reik\u0161m\u0117 'email' atitinka UserMode.getEmail() metod\u0105.
+usermodel.attr.label=Naudotojo atributas
+usermodel.attr.tooltip=I\u0161saugoto naudotojo atributo pavadinimas kuris naudojamas UserModel.attribute rinkinyje.
+userSession.modelNote.label=Naudotojo sesijos pastaba
+userSession.modelNote.tooltip=I\u0161saugotos naudotojo sesijos pastaba, kuri saugoma UserSessionModel.note rinkinyje.
+multivalued.label=Daugiareik\u0161mis
+multivalued.tooltip=Nurodo, kad atributas gali tur\u0117ti daugiau nei vien\u0105 reik\u0161m\u0119. Jei pa\u017Eym\u0117tas, tuomet visos reik\u0161m\u0117s nustatomos kaip privalomos. Kitu atveju privaloma tik pirmoji reik\u0161m\u0117.
+selectRole.label=Parinkite rol\u0119
+selectRole.tooltip=Kair\u0117je pus\u0117je esan\u010Diame laukelyje \u012Fveskite rol\u0117s pavadinim\u0105 arba paspauskite Rinktis nor\u0117dami nurodyti pageidaujam\u0105 rol\u0119.
+tokenClaimName.label=Reikalaujamo rakto pavadinimas
+tokenClaimName.tooltip=\u012E rakt\u0105 \u012Fterpiamas privalomas atributas. Galite nurodyte piln\u0105 keli\u0105 iki atributo, pavyzd\u017Eiui 'address.street'. Pateiktu atveju bus sukuriamas sud\u0117tinis (nested) JSON objektas.
+jsonType.label=Privalomo atributo JSON tipas
+jsonType.tooltip=Naudojamas JSON lauko tipas, kuris turi b\u016Bti u\u017Epildomas rakto privalomoje JSON informacijoje. Galimi tipai: long, int, boolean ir String.
+includeInIdToken.label=Prid\u0117ti prie ID rakto
+includeInIdToken.tooltip=Ar privaloma informacija turi b\u016Bti pridedama prie ID rakto?
+includeInAccessToken.label=Prid\u0117ti prie prieigos rakto
+includeInAccessToken.tooltip=Ar privaloma informacija turi b\u016Bti pridedama prie prieigos rakto?
+includeInUserInfo.label=Prid\u0117ti prie naudotojo informacijos
+includeInUserInfo.tooltip=Ar privaloma informacija turi b\u016Bti pridedama prie naudotojo informacijos?
+usermodel.clientRoleMapping.clientId.label=Kliento ID
+usermodel.clientRoleMapping.clientId.tooltip=Kliento ID naudojamas roli\u0173 atribut\u0173 susiejime
+usermodel.clientRoleMapping.rolePrefix.label=Kliento rol\u0117s prefiksas
+usermodel.clientRoleMapping.rolePrefix.tooltip=Prefiksas, pridedamas prie\u0161 kiekvien\u0105 kliento rol\u0119 (neprivalomas)
+usermodel.realmRoleMapping.rolePrefix.label=Srities rol\u0117s prefiksas
+usermodel.realmRoleMapping.rolePrefix.tooltip=Prefiksas, pridedamas prie\u0161 kiekvien\u0105 srities rol\u0119 (neprivalomas)
+
+# client details
+clients.tooltip=Klientai - tai srities nar\u0161ykl\u0117s program\u0117l\u0117s arba tinklin\u0117s paslaugos, kuriomis pasitikima. Klientai gali jungtis prie sistemos. Klientams galima nurodyti specifines roles.
+search.placeholder=Ie\u0161koti...
+create=Sukurti
+import=Importuoti
+client-id=Kliento ID
+base-url=Pagrindinis URL
+actions=Veiksmai
+not-defined=Nenurodyta
+edit=Redaguoti
+delete=Trinti
+no-results=Rezultat\u0173 n\u0117ra
+no-clients-available=N\u0117ra sukonfig\u016Bruot\u0173 klient\u0173
+add-client=Prid\u0117ti klient\u0105
+select-file=Parinkti rinkmen\u0105
+view-details=Per\u017Ei\u016Br\u0117ti detaliau
+clear-import=I\u0161valyti importuojamas rinkmenas
+client-id.tooltip=Identifikatorius, naudojamas URI adresuose ir prieigos raktuose. Pavyzd\u017Eiui 'my-client'. SAML protokolo atveju, \u0161i\u0105 reik\u0161m\u0119 tikimasi gauti kaip authn u\u017Eklausos siunt\u0117j\u0105
+client.name.tooltip=Reik\u0161m\u0117, kuri rodoma naudotojams. Pavyzd\u017Eiui 'My Client'. Galimos lokalizuotos reik\u0161m\u0117s - pavyzd\u017Eiui\: ${my_client}
+client.enabled.tooltip=Klientai, kurie n\u0117ra \u012Fgalinti, negali inicijuoti prisijungimo arba gauti prieigos raktus.
+consent-required=Reikalingas patvirtinimas
+consent-required.tooltip=Jei \u012Fgalinta, tuomet naudotojai privalo patvirtinti, kad pageidauja prisijungti prie kliento (programos).
+client-protocol=Kliento protokolas
+client-protocol.tooltip='OpenID connect' leid\u017Eia klientams tikrinti galutinio naudotojo tapatyb\u0119 remiantis autorizacijos serverio atlikta autentifikacija. 'SAML' \u012Fgalina \u017Einiatinklio, \u012Fskaitant skirting\u0173 domen\u0173 atvejus, vieningos autentifikacijos ir autorizacijos scenarijus perduodant informacij\u0105 saugiose \u017Einut\u0117se.
+access-type=Prieigos tipas
+access-type.tooltip='Konfidencialus' klientai nor\u0117dami inicijuoti prisijungimo protokol\u0105 privalo perduoti slapt\u0105 kod\u0105. 'Vie\u0161as' klientai neprivalo perduoti slapto kodo. 'Tik ne\u0161\u0117jas' klientai - tai tinklin\u0117s paslaugos, kurios niekada neinicijuoja prisijungimo.
+standard-flow-enabled=\u012Egalinta standartin\u0117 seka
+standard-flow-enabled.tooltip=\u012Egalina standartin\u012F OpenID Connect nukreipim\u0105, kuomet autentifikacijos metu yra perduodamas autorizacijos kodas. OpenID Connect arba OAuth2 specifikacijos terminais tai rei\u0161kia 'Authorization Code Flow' \u012Fgalinim\u0105 \u0161iam klientui.
+implicit-flow-enabled=\u012Egalinta i\u0161reik\u0161tin\u0117 seka
+implicit-flow-enabled.tooltip=\u012Egalina OpenID Connect nukreipim\u0105, kuomet autentifikacijos metu n\u0117ra perduodamas autorizacijos kodas. OpenID Connect arba OAuth2 specifikacijos terminais tai rei\u0161kia  'Implicit Flow' \u012Fgalinim\u0105 \u0161iam klientui.
+direct-access-grants-enabled=\u012Egalintas tiesiogin\u0117s prieigos suteikimas
+direct-access-grants-enabled.tooltip=\u012Egalina tiesiogin\u012F prieigos suteikim\u0105, kuomet klientas turi prieig\u0105 prie naudotojo vardo ir slapta\u017Eod\u017Eio ir prieigos rakt\u0173 gavimui \u0161iais duomenimis gali tiesiogiai apsikeisti su Keycloak serveriu. OAuth2 specifikacijos terminais, \u0161iam klientui \u012Fgalinimas 'Resource Owner Password Credentials Grant'.
+service-accounts-enabled=\u012Egalintas paslaugos naudotojas
+service-accounts-enabled.tooltip=\u012Egalina klient\u0105 autentifikuotis su Keycloak serveriu ir gauti dedikuot\u0105 prieigos rakt\u0105 skirt\u0105 \u0161iam klientui. OAuth2 specifikacijos terminais, tai rei\u0161kia 'Client Credentials Grant' teis\u0119 \u0161iam klientui.
+include-authnstatement=\u012Etraukti AuthnStatement
+include-authnstatement.tooltip=Ar prisijungimo b\u016Bdas ir laikas \u0161ur\u0117t\u0173 b\u016Bti \u012Ftraukiami \u012F prisijungimo operacijos atsakym\u0105?
+sign-documents=Pasira\u0161yti dokumentus
+sign-documents.tooltip=Ar SAML dokumentai turi b\u016Bt\u012F pasira\u0161omi \u0161ios srities?
+sign-assertions=Pasira\u0161yti sprendinius
+sign-assertions.tooltip=Ar SAML sprendiniai SAML dokumentuose turi b\u016Bti pasira\u0161omi? \u0160is nustatymas neb\u016Btinas, kuomet naudojamas viso dokumento pasira\u0161ymas.
+signature-algorithm=Para\u0161o algoritmas
+signature-algorithm.tooltip=Para\u0161o algoritmas naudojamas dokument\u0173 pasira\u0161ymui.
+canonicalization-method=Standartizavimo metodas
+canonicalization-method.tooltip=XML para\u0161o metodas.
+encrypt-assertions=U\u017Ekoduoti sprendinius
+encrypt-assertions.tooltip=Ar SAML sprendiniai turi b\u016Bti u\u017Ekoduojami kliento vie\u0161uoju raktu naudojant AES?
+client-signature-required=Privalomas kliento para\u0161as
+client-signature-required.tooltip=Ar kliento siun\u010Diamos SAML u\u017Eklausos ir atsakymai bus pasira\u0161yti? Jei taip, tuomet ar juos privaloma tikrinti?
+force-post-binding=Priverstinai naudoti POST s\u0105ry\u0161\u012F
+force-post-binding.tooltip=Visuomet naudoti POST s\u0105ry\u0161\u012F siun\u010Diant atsakymus.
+front-channel-logout=I\u0161registravimas per nar\u0161ykl\u0119
+front-channel-logout.tooltip=Jei \u012Fgalinta, tuomet atsijungimas atliekamas nar\u0161ykl\u0117s nukreipimu \u012F kliento puslap\u012F. Kitu atveju, atsijungimas atliekamas perduodant serveris-serveris u\u017Eklaus\u0105.
+force-name-id-format=Priverstinai naudoti NameID format\u0105
+force-name-id-format.tooltip=Ignoruoti NameID tapatyb\u0117s identifikatoriaus format\u0105, naudojant administratoriaus konsol\u0117je nurodyt\u0105 format\u0105.
+name-id-format=NameID formatas
+name-id-format.tooltip=Koks tapatyb\u0117s identifikatoriaus formatas turi b\u016Bti naudojamas.
+root-url=\u0160akninis URL
+root-url.tooltip=Prie reliatyvi\u0173 nuorod\u0173 pridedamas \u0161akninis URL
+valid-redirect-uris=Leid\u017Eiamos nukreipimo nuorodos
+valid-redirect-uris.tooltip=Nukreipimo URI \u0161ablonas, kuomet nar\u0161yklei leid\u017Eiama nukreipti naudotoj\u0105 po s\u0117kmingos autentifikacijos ar atsijungimo metu. Leid\u017Eiami pakaitos simboliai, pvz. 'http://pavyzdys.lt/*'. Leid\u017Eiami reliatyv\u016Bs keliai pvz. /mano/reliatyvus/kelias/*. Reliatyvumas skai\u010Diuojamas nuo kliento \u0161akninio URL (jei nurodyta) arba nuo autentifikacijos serverio \u0161akninio adreso. SAML atveju, kuomet tikimasi gav\u0117jo paslaugos URL \u012Ftraukimo \u012F prisijungimo u\u017Eklaus\u0105, privaloma nurodyti teisingus URI \u0161ablonus.
+base-url.tooltip=Numatytas URL, kuris turi b\u016Bti naudojamas naudotojo nukreipimui atgal \u012F klient\u0105.
+admin-url=Administravimo URL
+admin-url.tooltip=Kliento administravimo tinklin\u0117s s\u0105sajos URL. \u012Era\u0161yti tuomet, kai klientas palaiko adapterio REST API. \u0160is REST API leid\u017Eia autentifikacijos serveriui perduoti at\u0161aukimo ir kitas su administravimu susijusias taisykles. Da\u017Eniausiai \u0161is URL sutampa su kliento pagrindiniu URL.
+master-saml-processing-url=\u0160akninis SAML apdorojimo URL
+master-saml-processing-url.tooltip=Kuomet sukonfig\u016Bruotas, \u0161is URL bus naudojamas visoms, 'SP's Assertion Consumer' ir 'Single Logout Services' u\u017Eklausoms. Detalioje SAML prieigos adres\u0173 konfig\u016Bravimo skyriuje \u0161ios reik\u0161m\u0117s gali b\u016Bti atskirai pakeistos.
+idp-sso-url-ref=IDP inicijuojamo SSO URL fragmento pavadinimas
+idp-sso-url-ref.tooltip=Pavadinimas, kuris IDP inicijuoto SSO prisijungimo metu, perduodamas klientui per URL fragment\u0105. Palikus tu\u0161\u010Di\u0105 reik\u0161m\u0119 IDP inicjuojam\u0105 SSO prisijungimo funkcionalumas i\u0161jungiamas. \u0160is fragmentas buv naudojamas formuojant \u0161i\u0105 nuorod\u0105: {server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}
+idp-sso-relay-state=IDP inicijuotos SSO b\u016Bsenos perdavimas
+idp-sso-relay-state.tooltip=SSO b\u016Bsenos parametro (RelayState) perdavimas kartu su IDP inicijuota SSO SAML u\u017Eklausa.
+web-origins=\u0160aknin\u0117s nuorodos
+web-origins.tooltip=Leid\u017Eiamos CORS nuorodos. Nor\u0117dami leisti nukreipim\u0105 \u012F teisingas nuorodas, naudokite '+'. Nor\u0117dami leisti visas nuorodas, naudokite '*'.
+fine-oidc-endpoint-conf=Detalioji OpenID prisijungimo konfig\u016Bracija
+fine-oidc-endpoint-conf.tooltip=Nor\u0117dami konfig\u016Bruoti kliento s\u0105sajos su OpenID prisijungimo protokolu i\u0161pl\u0117stines nuostatas, i\u0161skleiskite \u0161\u012F skyri\u0173.
+user-info-signed-response-alg=Naudotojo informacijos pasira\u0161yto atsako algoritmas
+user-info-signed-response-alg.tooltip=JWA algoritmas naudojamas pasira\u0161yti naudotojo informacijos prieigos ta\u0161ko atsak\u0105. Jei nustatyta 'unsigned', tuomet naudotojo informacijos atsakas nebus pasira\u0161ytas ir bus gr\u0105\u017Eintas application/json formatu.
+request-object-signature-alg=U\u017Eklausos objekto para\u0161o algoritmas
+request-object-signature-alg.tooltip=JWA algoritmas, kur\u012F klientas naudoja siun\u010Diant OIDC u\u017Eklausos objekt\u0105, nusakyt\u0105 'request' arba 'request_uri' parameterais. Jei nustatyta 'any', tuomet u\u017Eklausos objektas gali b\u016Bti nepasira\u0161ytas arba pasira\u0161ytas bet kuriuo algoritmu.
+fine-saml-endpoint-conf=Detalioji SAML prieigos ta\u0161k\u0173 konfig\u016Bracija
+fine-saml-endpoint-conf.tooltip=Nor\u0117dami konfig\u016Bruoti sprendini\u0173 pri\u0117mimo ir vieningo atsijungimo paslaugas, i\u0161skleiskite \u0161\u012F skyri\u0173.
+assertion-consumer-post-binding-url=Sprendini\u0173 naudotojo paslaugos POST jungties URL
+assertion-consumer-post-binding-url.tooltip=Kliento sprendini\u0173 pri\u0117mimo paslaugos (prisijungimo rezultat\u0173) SAML POST jungties URL. Jei toki\u0173 jung\u010Di\u0173 neturite, tuomet palikite tu\u0161\u010Dias reik\u0161mes.
+assertion-consumer-redirect-binding-url=Sprendini\u0173 pri\u0117mimo paslaugos nukreipimo jungties URL
+assertion-consumer-redirect-binding-url.tooltip=Kliento sprendinio pri\u0117mimo paslaugos SAML nukreipimo jungties URL (prisijungimo atsakymams). Jei toki\u0173 jung\u010Di\u0173 neturite, tuomet palikite tu\u0161\u010Dias reik\u0161mes.
+logout-service-binding-post-url=Atsijungimo paslaugos POST jungties URL
+logout-service-binding-post-url.tooltip=Kliento vieningo atsijungimo SAML POST jungties URL. Jei naudojate kitas jungtis, tuomet \u0161ias reik\u0161mes galite palikti neu\u017Epildytas.
+logout-service-redir-binding-url=Atsijungimo paslaugos nukreipimo jungties URL
+logout-service-redir-binding-url.tooltip=Kliento vieningo atsijungimo paslaugos SAML nukreipimo jungties. Jei naudojate kitas jungtis, tuomet \u0161ias reik\u0161mes galite palikti neu\u017Epildytas.
+
+# client import
+import-client=\u012Ediegti programos nustatymus
+format-option=Formato pasirinkimas
+select-format=Pasirinkite format\u0105
+import-file=Importuoti rinkmen\u0105
+
+# client tabs
+settings=Nustatymai
+credentials=Prisijungimo duomenys
+saml-keys=SAML raktai
+roles=Rol\u0117s
+mappers=Atribut\u0173 atitikmenys
+mappers.tooltip=Protokolo atribut\u0173 susiejimas atlieka rakt\u0173 ir dokument\u0173 transformacijas. Naudotojo duomenys gali b\u016Bti ver\u010Diami \u012F protokolo teiginius, arba tiesiog transformuoti bet kurias u\u017Eklausas perduodamas tarp kliento ir autentifikacijos serverio.
+scope=Apimtis
+scope.tooltip=Apimties atitikmen\u0173 parinkimas leid\u017Eia apriboti, kurios naudotojo rol\u0117s kartu su raktu bus perduodamos klientui.
+sessions.tooltip=Per\u017Ei\u016Br\u0117ti \u0161io kliento aktyvias sesijas. Matysite \u0161iuo metu prisijungusius naudotojus bei j\u0173 prisijungimo laikus.
+offline-access=Darbas neprisijungus
+offline-access.tooltip=Per\u017Ei\u016Br\u0117ti \u0161io kliento darbo neprisijungus r\u0117\u017Eimo aktyvias sesijas. Matysite naudotojus, kuriems yra i\u0161duoti darbo neprisijungus raktai bei j\u0173 i\u0161davimo laikus. Nor\u0117dami at\u0161aukti visus \u0161iam klientui i\u0161duotus raktus, eikite \u012F at\u0161aukim\u0173 kortel\u0119 ir pasirinkite 'Parinkti dabartin\u0119 dat\u0105'  
+clustering=Klasteriai
+installation=Diegimas
+installation.tooltip=Klient\u0173 konfig\u016Bravimo pagalbin\u0117 priemon\u0117, padedanti sugeneruoti klient\u0173 adapteri\u0173 konfig\u016Bracijas, kurias galima atsisi\u0173sti, kopijuoti ar \u012Fkelti i\u0161 i\u0161karpin\u0117s
+service-account-roles=Paslaugos paskyros rol\u0117s
+service-account-roles.tooltip=Dedikuot\u0173 roli\u0173 priskyrimas \u0161ios paslaugos naudotojui  
+
+# client credentials
+client-authenticator=Kliento autentifikavimo priemon\u0117s
+client-authenticator.tooltip=Kliento autentifikavimo priemon\u0117s naudojamos kliento autentifikavimuisi \u012F Keycloak server\u012F
+certificate.tooltip=Kliento sertifikatas naudojamas kliento i\u0161duot\u0173 ir priva\u010Diu raktu pasira\u0161yt\u0173 JWT prieigos rakt\u0173 tikrinimui.
+publicKey.tooltip=Kliento i\u0161duotas vie\u0161asis raktas pasira\u0161ytas kliento priva\u010Diu raktu ir skirtas JWT tikrinimui.
+no-client-certificate-configured=Nesukonfig\u016Bruotas nei vienas kliento sertifikatas
+gen-new-keys-and-cert=Nauj\u0173 rakt\u0173 ir sertifikat\u0173 generavimas
+import-certificate=Importuoti sertifikat\u0105
+gen-client-private-key=Generuoti kliento privat\u0173 rakt\u0105
+generate-private-key=Generuoti privat\u0173 rakt\u0105
+archive-format=Archyvo formatas
+archive-format.tooltip=Java rakt\u0173 saugykla (keystore) arba PKCS12 formato rinkmena.
+key-alias=Rakto pseudonimas
+key-alias.tooltip=Privataus rakto ir sertifikato rinkmenos pseudonimas.
+key-password=Rakto slapta\u017Eodis
+key-password.tooltip=Slapta\u017Eod\u017Ei\u0173 saugykloje esan\u010Dio privataus rakto slapta\u017Eodis
+store-password=Saugyklos slapta\u017Eodis
+store-password.tooltip=Slapta\u017Eodis, reikalingas norint atidaryti slapta\u017Eod\u017Ei\u0173 saugykl\u0105
+generate-and-download=Generuoti ir atsisi\u0173sti
+client-certificate-import=Kliento sertifikato importavimas
+import-client-certificate=Importuoti kliento sertifikatus
+jwt-import.key-alias.tooltip=Slapta\u017Eod\u017Ei\u0173 saugyklos pseudonimas
+secret=Slaptas kodas
+regenerate-secret=Pergeneruoti slapt\u0105 kod\u0105
+registrationAccessToken=Registracijos prieigos raktas
+registrationAccessToken.regenerate=Pergeneruoti registracijos prieigos rakt\u0105
+registrationAccessToken.tooltip=Registracijos prieigos raktas klientams suteikia prieig\u0105 prie klient\u0173 registracijos paslaugos 
+add-role=Prid\u0117ti rol\u0119
+role-name=Rol\u0117s pavadinimas
+composite=Sud\u0117tinis
+description=Apra\u0161ymas
+no-client-roles-available=Kliento rol\u0117s nesukonfig\u016Bruotos
+scope-param-required=Privalomas taikymo srities parametras
+scope-param-required.tooltip=\u0160i rol\u0117 suteikiama tik tuo atveju, kai taikymo srities parametras su rol\u0117s vardu panaudotas autorizacijos u\u017Eklausoje ar rakte. 
+composite-roles=Sud\u0117tin\u0117s rol\u0117s
+composite-roles.tooltip=Visos susietos rol\u0117s bus automati\u0161kai priskiriamos naudotojui prisikiriant \u0161i\u0105 sud\u0117tin\u0119 rol\u0119.  
+realm-roles=Srities rol\u0117s
+available-roles=Galimos rol\u0117s
+add-selected=Prid\u0117ti pa\u017Eym\u0117tas
+associated-roles=Priskirtos rol\u0117s
+composite.associated-realm-roles.tooltip=Srities apmities rol\u0117s susietos su \u0161ia sud\u0117tine role.
+composite.available-realm-roles.tooltip=Srities apmities rol\u0117s, kurias galima susieti su \u0161ia sud\u0117tine role.
+remove-selected=Pa\u0161alinti pa\u017Eym\u0117tas
+client-roles=Kliento rol\u0117s
+select-client-to-view-roles=Nor\u0117dami pamatyti priskirtas roles pa\u017Eym\u0117kite klient\u0105
+available-roles.tooltip=\u0160io kliento rol\u0117s, kurios gali b\u016Bti priskiritos \u0161iai kompozicinei rolei.
+client.associated-roles.tooltip=Su \u0161iuo klientu susietos sud\u0117tin\u0117s rol\u0117s. 
+add-builtin=Prid\u0117ti numatytuosius
+category=Kategorija
+type=Tipas
+no-mappers-available=N\u0117ra susiet\u0173 atribut\u0173
+add-builtin-protocol-mappers=Prid\u0117ti numatytuosius protokolo atribut\u0173 susiejimus
+add-builtin-protocol-mapper=Prid\u0117ti numatytuosius protokolo atribut\u0173 susiejimus
+scope-mappings=atribut\u0173 susiejimo taikymo sritis
+full-scope-allowed=Taikymas pilna apimtimi
+full-scope-allowed.tooltip=\u012Egalinimo atveju visi apribojimai i\u0161jungiami
+scope.available-roles.tooltip=Srities lygio rol\u0117s, kurios gali b\u016Bti priskiriamos \u0161iai taikymo sri\u010Diai.
+assigned-roles=Priskirtos rol\u0117s
+assigned-roles.tooltip=Srities lygio rol\u0117s, kurios yra priskirtos \u0161iai taikymo sri\u010Diai.
+effective-roles=Aktyvios rol\u0117s
+realm.effective-roles.tooltip=Priskirtos srities lygio rol\u0117s, kurios gali gali b\u016Bti paveld\u0117tos i\u0161 sud\u0117tini\u0173 roli\u0173.
+select-client-roles.tooltip=Nor\u0117dami pamatyti visas roles pa\u017Eym\u0117kite klient\u0105
+assign.available-roles.tooltip=Kliento rol\u0117s, kurias galima priskirti.
+client.assigned-roles.tooltip=Priskirtos kliento rol\u0117s.
+client.effective-roles.tooltip=Priskirtos kliento rol\u0117s, kurios gali gali b\u016Bti paveld\u0117tos i\u0161 sud\u0117tini\u0173 roli\u0173.
+basic-configuration=Pagrindin\u0117 konfig\u016Bracija
+node-reregistration-timeout=Mazgo persiregistravimui skirtas laikas
+node-reregistration-timeout.tooltip=Nurodykite maksimal\u0173 laiko interval\u0105, per kur\u012F mazgai privalo i\u0161 naujo prisiregistruoti. Jei mazgas neatsi\u0173s persiregistravimo u\u017Eklausos per nurodyt\u0105 laik\u0105, tuomet \u0161is mazgas bus i\u0161registruojamas i\u0161 Keycloak 
+registered-cluster-nodes=Registruoti klasterio mazgus
+register-node-manually=Registruoti mazg\u0105 rankiniu b\u016Bdu
+test-cluster-availability=Tikrinti ar mazgas prieinamas
+last-registration=V\u0117liausia registracija
+node-host=Mazgo serveris
+no-registered-cluster-nodes=Nepriregistuotas nei vienas klasterio mazgas
+cluster-nodes=Klasterio mazgai
+add-node=Prid\u0117ti mazg\u0105
+active-sessions.tooltip=\u0160io kliento aktyvi\u0173 naudotoj\u0173 sesij\u0173 skai\u010Dius.
+show-sessions=Rodyti sesijas
+show-sessions.tooltip=D\u0117mesio, \u0161is veiksmas gali ilgai u\u017Etrukti priklausomai nuo aktyvi\u0173 sesij\u0173 skai\u010Diaus.
+user=Naudotojas
+from-ip=Prisijungimo IP
+session-start=Sesijos prad\u017Eios laikas
+first-page=Pirmas puslapis
+previous-page=Atgalinis puslapis
+next-page=Sekantis puslapis
+client-revoke.not-before.tooltip=At\u0161aukti visus \u0161io kliento raktus i\u0161duotus prie\u0161 nurodyt\u0105 dat\u0105. 
+client-revoke.push.tooltip=Kuomet nurodytas administravimo URL, taisykl\u0117 perduodama klientui.
+select-a-format=Formato parinkimas
+download=Atsisi\u0173sti
+offline-tokens=Darbo neprisijungus raktai
+offline-tokens.tooltip=Rakt\u0173 skai\u010Dius, kurie naudojami darbui neprisijungus
+show-offline-tokens=Rodyti raktus
+show-offline-tokens.tooltip=D\u0117mesio, \u0161is veiksmas gali ilgai u\u017Etrukti priklausomai nuo aktyvi\u0173 darbo neprisijungus sesij\u0173 skai\u010Diaus.
+token-issued=Rakto i\u0161davimo laikas
+last-access=V\u0117liausios prieigos laikas
+last-refresh=V\u0117liausio atnaujinimo laikas
+key-export=Eksportuoti rakt\u0105
+key-import=Importuoti rakt\u0105
+export-saml-key=Eksportuoti SAML rakt\u0105
+import-saml-key=Importuoti SAML rakt\u0105
+realm-certificate-alias=Srities sertifikato pseudonimas
+realm-certificate-alias.tooltip=Srities sertifikato, kuris taip pat saugomas saugykloje, pseudonimas.
+signing-key=Pasira\u0161ymo raktas
+saml-signing-key=SAML pasira\u0161ymo raktas.
+private-key=Privatus raktas
+generate-new-keys=Generuoti naujus raktus
+export=Eksportuoti
+encryption-key=U\u017Ekodavimo raktas
+saml-encryption-key.tooltip=SAML u\u017Ekodavimo raktas.
+service-accounts=Paslaugos naudotojo profiliai
+service-account.available-roles.tooltip=\u0160ios paslaugos paskyrai galimos priskirti srities rol\u0117s 
+service-account.assigned-roles.tooltip=Paslaugos paskyrai priskirtos srities rol\u0117s.
+service-account-is-not-enabled-for=Kliento {{client}} paslaugos paskyra ne\u012Fgalinta
+create-protocol-mappers=Protokolo atitkmen\u0173 susiejimas
+create-protocol-mapper=Protokolo atitkmenens susiejimas
+protocol=Protokolas
+protocol.tooltip=Protokolas...
+id=ID
+mapper.name.tooltip=Atitikmens susiejimo vardas.
+mapper.consent-required.tooltip=Ar teikiant laikin\u0105 prieig\u0105 naudotojas privalo pateikti sutikim\u0105 d\u0117l duomen\u0173 perdavimo?
+consent-text=Sutikimo tekstas
+consent-text.tooltip=Tekstas, kuris rodomas naudotojo sutikimo puslapyje.
+mapper-type=Atitikmens tipas
+mapper-type.tooltip=Atitikmens tipas
+# realm identity providers
+identity-providers=Tapatyb\u0117s teik\u0117jai
+table-of-identity-providers=Tapatyb\u0117s teik\u0117j\u0173 s\u0105ra\u0161as
+add-provider.placeholder=Prid\u0117ti teik\u0117j\u0105...
+provider=Teik\u0117jas
+gui-order=GUI eili\u0161kumas
+first-broker-login-flow=Pirmojo prisijungimo eiga
+post-broker-login-flow=Sekan\u010Di\u0173 prisijungim\u0173 eiga
+redirect-uri=Nukreipimo URI
+redirect-uri.tooltip=Tapatyb\u0117s teik\u0117jo konfig\u016Bravimo nuoroda.
+alias=Pseudonimas
+identity-provider.alias.tooltip=Pseudonimas, kuris vienareik\u0161mi\u0161kai identifikuoja tapatyb\u0117s teik\u0117j\u0105 ir yra naudojamas konstruojant nukreipimo nuorod\u0105.
+identity-provider.enabled.tooltip=\u012Egalinti \u0161\u012F tapatyb\u0117s teik\u0117j\u0105.
+authenticate-by-default=Autentifikuoti i\u0161 karto
+identity-provider.authenticate-by-default.tooltip=Jei \u012Fgalinta, tuomet bus bandoma autentifikuoti naudotoj\u0105 prie\u0161 parodant prisijungimo lang\u0105.
+store-tokens=Saugoti raktus
+identity-provider.store-tokens.tooltip=Jei \u012Fgalinta, tuomet po naudotoj\u0173 prisijungimo, prieigos raktai bus i\u0161saugoti.
+stored-tokens-readable=Saugoti raktus skaitomame formate
+identity-provider.stored-tokens-readable.tooltip=Jei \u012Fgalinta, tuomet naudotojai gali per\u017Ei\u016Br\u0117ti i\u0161saugotus prieigos raktus. \u012Egalinama broker.read-token rol\u0117.
+update-profile-on-first-login=Profilio duomen\u0173 atnaujinimas pirmojo prisijungimo metu
+on=On
+off=Off
+on-missing-info=Kuomet tr\u016Bksta informacijos
+update-profile-on-first-login.tooltip=Nurodykite s\u0105lygas, kuomet naudotojas privalo atnaujinti savo profil\u012F pirmojo prisijungimo metu.
+trust-email=El. pa\u0161tas patikimas
+trust-email.tooltip=Jei \u012Fgalintas, tuomet \u0161io tapatyb\u0117s teik\u0117jo pateiktas el. pa\u0161to adresas laikomas patikimu ir, nepaisant bendr\u0173j\u0173 srities nustatym\u0173, n\u0117ra papildomai tikrinamas.
+gui-order.tooltip=Eili\u0161kum\u0105 GUI lange (pvz. Prisijungimo langas) nurodantis skai\u010Dius 
+first-broker-login-flow.tooltip=Autentifikacijos eigos pseudonimas, kuris bus su\u017Eadintas \u0161io tapatyb\u0117s teik\u0117jo naudotojui prisijungus pirm\u0105 kart\u0105. Terminas 'pirmas kartas' rei\u0161kia, kad Keycloak sistemoje nebuvo saugomas naudotojo profilis susietas su autentifikuotu \u0161io tapatyb\u0117s teik\u0117jo naudotoju.
+post-broker-login-flow.tooltip=Autentifikacijos eigos pseudonimas, kuris bus su\u017Eadintas po kiekvieno prisijungimo naudojant \u0161\u012F tapatyb\u0117s teik\u0117j\u0105. Naudingas tuomet, kai atlikti papildomus tikrinimus (pvz. OTP). Palikite tu\u0161\u010Di\u0105 reik\u0161m\u0119 jei nenorite su\u017Eadinti papildom\u0173 tikrinim\u0173 autentifikatoriumi jungiantis per \u0161\u012F tapatyb\u0117s teik\u0117j\u0105. Tur\u0117kite omenyje, kad autentifikatoriaus realizacijos turi daryti prielaid\u0105, kad ClientSession naudotojas yra tapatyb\u0117s teik\u0117jo nustatytas.
+openid-connect-config=OpenID prisijungimo konfig\u016Bracija
+openid-connect-config.tooltip=OIDC SP ir i\u0161orinio IDP konfig\u016Bracija.
+authorization-url=Autorizacijos URL
+authorization-url.tooltip=Autorizacijos URL adresas.
+token-url=Prieigos rakt\u0173 URL
+token-url.tooltip=Prieigos rakt\u0173 URL.
+logout-url=Atsijungimo URL
+identity-provider.logout-url.tooltip=Adresas, kuris turi b\u016Bti naudojamas norint atjungti naudotoj\u0105 nuo i\u0161orinio tapatyb\u0117s teik\u0117jo.
+backchannel-logout=Foninis atjungimas
+backchannel-logout.tooltip=Ar i\u0161orinis tapatyb\u0117s teik\u0117jas palaiko serveris-serveris naudotojo atjungimo b\u016Bd\u0105?
+user-info-url=Naudotojo informacijos URL
+user-info-url.tooltip=Naudotojo informacijos URL. Neprivalomas.
+identity-provider.client-id.tooltip=Kliento identifikatorius u\u017Eregistruotas tapatyb\u0117s teik\u0117jo sistemoje.
+client-secret=Kliento slaptas kodas
+show-secret=Rodysi slapt\u0105 kod\u0105
+hide-secret=Sl\u0117pti slapt\u0105 kod\u0105
+client-secret.tooltip=Kliento slaptas kodas u\u017Eregistruotas tapatyb\u0117s teik\u0117jo sistemoje.
+issuer=I\u0161dav\u0117jas
+issuer.tooltip=I\u0161dav\u0117jo identifikatorius perduodamas i\u0161dav\u0117jo atsakyme. Tikrinimas nebus atliekamas jei reik\u0161m\u0117 tu\u0161\u010Dia.
+default-scopes=Numatytosios taikymo sritys
+identity-provider.default-scopes.tooltip=Taikymos sritys, kurios siun\u010Diamos autorizavimo u\u017Eklausoje. Reik\u0161m\u0117s turi b\u016Bti atskirtos tarpo simboliu. Numatyta reik\u0161m\u0117 - 'openid'.
+prompt=Raginimas
+unspecified.option=nenurodyta
+none.option=jokio
+consent.option=sutikimo tekstas
+login.option=prisijungimas
+select-account.option=paskyros pasirinkimas
+prompt.tooltip=Nurodo, ar autorizacijos serveris galutini\u0173 naudotoj\u0173 reikalauja pakartotinai patvirtinti sutikim\u0105 ar prisijungti.
+validate-signatures=Para\u0161o tikrinimas
+identity-provider.validate-signatures.tooltip=\u012Egalinamas i\u0161orini\u0173 IDP para\u0161\u0173 tikrinimas.
+validating-public-key=Vie\u0161as raktas para\u0161o tikrinimui
+identity-provider.validating-public-key.tooltip=PEM formato vie\u0161asis raktas, kuris turi b\u016Bti naudojamas i\u0161orinio IDP para\u0161t\u0173 tikrinimui.
+import-external-idp-config=Importuoti i\u0161orinio IDP konfig\u016Bracij\u0105
+import-external-idp-config.tooltip=Leid\u017Eia \u012Fkelti konfig\u016Bracin\u0119 rinkmen\u0105 arba nurodyti atsisiuntimo URL su i\u0161orinio IDP metaduomenimis.
+import-from-url=Importuoti i\u0161 URL
+identity-provider.import-from-url.tooltip=Importuoti metaduomenis i\u0161 nutolusio IDP aptikimo apra\u0161o (IDP discovery descriptor).
+import-from-file=Importuoti i\u0161 rinkmenos
+identity-provider.import-from-file.tooltip=Importuoti metaduomenis i\u0161 rinkmenos, kuri\u0105 atsisiunt\u0117te i\u0161 IDP aptikimo apra\u0161o (IDP discovery descriptor).
+saml-config=SAML konfig\u016Bracija
+identity-provider.saml-config.tooltip=SAML SP ir i\u0161oriniu IDP konfig\u016Bracija.
+single-signon-service-url=Vieningo prisijungimo paslaugos URL
+saml.single-signon-service-url.tooltip=Adresas, kuriuo turi b\u016Bti siun\u010Diamos autentifikacijos u\u017Eklausos (SAML AuthnRequest).
+single-logout-service-url=Vieningo atsijungimo paslaugos URL
+saml.single-logout-service-url.tooltip=Adresas, kuriuo turi b\u016Bti siun\u010Diamos naudotojo atjungimo u\u017Eklausos.
+nameid-policy-format=NameID taisykli\u0173 formatas
+nameid-policy-format.tooltip=Nurodykite URI nuorod\u0105 atitinkan\u010Di\u0105 vardo identifikatoriaus format\u0105. Numatyta reik\u0161m\u0117 urn:oasis:names:tc:SAML:2.0:nameid-format:persistent.
+http-post-binding-response=Si\u0173sti atsakymus HTTP-POST
+http-post-binding-response.tooltip=Jei \u012Fgalinta, tuomet atsakymai siun\u010Diami HTTP-POST saistymu. Kitu atveju bus naudojamas HTTP-REDIRECT.
+http-post-binding-for-authn-request=Si\u0173sti AuthnRequest HTTP-POST 
+http-post-binding-for-authn-request.tooltip=Jei \u012Fgalinta, tuomet AuthnRequest siun\u010Diami HTTP-POST saistymu. Kitu atveju bus naudojamas HTTP-REDIRECT.
+want-authn-requests-signed=Reikalaujami pasira\u0161yt\u0173 AuthnRequests
+want-authn-requests-signed.tooltip=Nurodykite, ar tapatyb\u0117s teik\u0117jas tikisi pasira\u0161yt\u0173 AuthnRequest u\u017Eklaus\u0173.
+force-authentication=Priverstin\u0117 autentifikacija
+identity-provider.force-authentication.tooltip=Jei \u012Fgalinta, tuomet tapatyb\u0117s teik\u0117jas privalo autentifikuoti naudotoj\u0105 i\u0161 naujo nepasitikint ankstesniu prisijungimu.
+validate-signature=Para\u0161o tikrinimas
+saml.validate-signature.tooltip=\u012Ejungti/i\u0161jungti SAML atsakym\u0173 para\u0161o tikrinim\u0105.
+validating-x509-certificate=X509 sertifikatas tikrinimui
+validating-x509-certificate.tooltip=PEM formato sertifikatas, kuris turi b\u016Bti naudojamas para\u0161\u0173 tikrinimui.
+saml.import-from-url.tooltip=Importuoti metaduomenis i\u0161 nutolusio IDP SAML subjekto apra\u0161o.
+social.client-id.tooltip=Kliento identifikatorius u\u017Eregistruotas tapatyb\u0117s teik\u0117jo sistemoje.
+social.client-secret.tooltip=Kliento saugos kodas u\u017Eregistruotas tapatyb\u0117s teik\u0117jo sistemoje.
+social.default-scopes.tooltip=Autorizacijos metu siun\u010Diamos taikymo sritys. Galim\u0173 reik\u0161mi\u0173 s\u0105ra\u0161o, skirtuko ir numatytos reik\u0161m\u0117s ie\u0161kokite tapatyb\u0117s teik\u0117jo sistemos dokumentacijoje..
+key=Raktas
+stackoverflow.key.tooltip=Stack Overflow kliento registracijos metu gautas raktas.
+
+# User federation
+sync-ldap-roles-to-keycloak=Sinchronizuoti LDAP roles \u012F Keycloak
+sync-keycloak-roles-to-ldap=Sinchronizuoti Keycloak roles \u012F LDAP
+sync-ldap-groups-to-keycloak=Sinchronizuoti LDAP grupes \u012F Keycloak
+sync-keycloak-groups-to-ldap=Sinchronizuoti Keycloak grupes \u012F LDAP
+
+realms=Sritys
+realm=Sritis
+
+identity-provider-mappers=Tapatyb\u0117s teik\u0117jo atitikmen\u0173 susiejimai
+create-identity-provider-mapper=Sukurti tapatyb\u0117s teik\u0117jo atitikmens susiejim\u0105
+add-identity-provider-mapper=Prid\u0117ti tapatyb\u0117s teik\u0117jo atitikmens susiejim\u0105
+client.description.tooltip=Nurodomas kliento apra\u0161as. Pavyzd\u017Eiui 'Mano laiko lenteli\u0173 klientas'. Palaikomos lokalizuotos reik\u0161m\u0117s. Pavyzd\u017Eiui\: ${my_client_description}
+
+expires=Galioja iki
+expiration=Galiojimas
+expiration.tooltip=Nurodykite kiek laiko galios prieigos raktas 
+count=Kiekis
+count.tooltip=Nurodykite kiek klient\u0173 gali b\u016Bti sukurti naudojant prieigos rakt\u0105
+remainingCount=Lik\u0119s kiekis
+created=Sukurta
+back=Atgal
+initial-access-tokens=Pradiniai prieigos raktai
+add-initial-access-tokens=Prid\u0117ti pradin\u012F prieigos rakt\u0105
+initial-access-token=Pradinis prieigos raktas
+initial-access.copyPaste.tooltip=Nukopijuokite ir \u012Fklijuokite prieigos rakt\u0105 prie\u0161 i\u0161eidami i\u0161 \u0161io puslapio. V\u0117liau negal\u0117site kopijuoti \u0161i\u0173 prieigos rakt\u0173.
+continue=T\u0119sti
+initial-access-token.confirm.title=Kopijuoti pradinius prieigos raktus
+initial-access-token.confirm.text=Pra\u0161ome \u012Fsitikinti, kad nusikopijavote pradinius prieigos raktus nes v\u0117liau prie rakt\u0173 nebegal\u0117site prieiti
+no-initial-access-available=N\u0117ra galim\u0173 pradini\u0173 prieigos rak\u0161\u0173
+
+trusted-hosts-legend=Patikimi kliento registracijos serveriai
+trusted-hosts-legend.tooltip=Serveri\u0173 vardai, kuriais pasitikima kliento registracijos metu. Klient\u0173 registravimo u\u017Eklausos i\u0161 \u0161i\u0173 serveri\u0173 gali b\u016Bti siun\u010Diamos be pradini\u0173 prieigos rakt\u0173. Klient\u0173 registracijos skai\u010Dius ribojamas pagal nurodyt\u0105 kiekvieno serverio limit\u0105.
+no-client-trusted-hosts-available=N\u0117ra galim\u0173 patikim\u0173 serveri\u0173
+add-client-reg-trusted-host=Prid\u0117ti patikim\u0105 server\u012F
+hostname=Serverio vardas
+client-reg-hostname.tooltip=Pilnas serverio vardas arba IP adresas. Klient\u0173 registracijomis su \u0161iuo serverio vardu arba IP adresu bus pasitikima ir leid\u017Eiama nauj\u0173 klient\u0173 registracija.
+client-reg-count.tooltip=Limitas, kiek registravimo u\u017Eklaus\u0173 galima atsi\u0173sti i\u0161 kiekvieno serverio. Limitas bus atkurtas tik po atk\u016Brimo.
+client-reg-remainingCount.tooltip=I\u0161 \u0161io serverio lik\u0119s galim\u0173 registracijos u\u017Eklaus\u0173 skai\u010Dius. Limitas bus atkurtas tik po atk\u016Brimo.
+reset-remaining-count=Atk\u016Brimo limit\u0105
+
+client-templates=Klient\u0173 \u0161ablonai
+client-templates.tooltip=Klient\u0173 \u0161ablonai leid\u017Eia nurodyti bendr\u0105 vis\u0173 klient\u0173 konfig\u016Bracij\u0105
+
+groups=Grup\u0117s
+
+group.add-selected.tooltip=Grupei galimos priskirti srities rol\u0117s.
+group.assigned-roles.tooltip=Su \u0161ia grupe susietos srities roles
+group.effective-roles.tooltip=Visos srities susietos rol\u0117s. \u0160iame s\u0105ra\u0161e taip pat rodomos visos rol\u0117s, kurios priskirtos sud\u0117tin\u0117ms rol\u0117ms.
+group.available-roles.tooltip=\u0160io kliento galimos susieti rol\u0117s.
+group.assigned-roles-client.tooltip=Susietos \u0161io kliento rol\u0117s.
+group.effective-roles-client.tooltip=Visos \u0161io kliento susietos rol\u0117s. \u0160iame s\u0105ra\u0161e taip pat rodomos visos rol\u0117s, kurios priskirtos sud\u0117tin\u0117ms rol\u0117ms.
+
+default-roles=Numatytosios rol\u0117s
+no-realm-roles-available=Sritis neturi roli\u0173
+
+users=Naudotojai
+user.add-selected.tooltip=Naudotojui galimos priskirti srities rol\u0117s.
+user.assigned-roles.tooltip=Su \u0161iuo naudotoju susietos srities rol\u0117s
+user.effective-roles.tooltip=Visos srities susietos rol\u0117s. \u0160iame s\u0105ra\u0161e taip pat rodomos visos rol\u0117s, kurios priskirtos sud\u0117tin\u0117ms rol\u0117ms.
+user.available-roles.tooltip=\u0160io kliento galimos susieti rol\u0117s.
+user.assigned-roles-client.tooltip=Susietos \u0161io kliento rol\u0117s.
+user.effective-roles-client.tooltip=Visos \u0161io kliento susietos rol\u0117s. \u0160iame s\u0105ra\u0161e taip pat rodomos visos rol\u0117s, kurios priskirtos sud\u0117tin\u0117ms rol\u0117ms.
+default.available-roles.tooltip=Galimos priskirti srities rol\u0117s.
+realm-default-roles=Numatytosios srities rol\u0117s
+realm-default-roles.tooltip=Srities rol\u0117s, kurios automati\u0161kai priskiriamos naujiems naudotojams.
+default.available-roles-client.tooltip=\u0160io kliento rol\u0117s, kurios automati\u0161kai gali b\u016Bti priskiriamos naudotojams.
+client-default-roles=Numatytosios kliento rol\u0117s
+client-default-roles.tooltip=Kliento rol\u0117s, kurios automati\u0161kai priskiriamos naujiems naudotojams.
+composite.available-roles.tooltip=Srities rol\u0117s, kurias galima susieti su \u0161ia sud\u0117tine role.
+composite.associated-roles.tooltip=Srities rol\u0117s, kurios susietos su \u0161ia sud\u0117tine role.
+composite.available-roles-client.tooltip=Kliento rol\u0117s, kurias galima susieti su \u0161ia sud\u0117tine role.
+composite.associated-roles-client.tooltip=Kliento rol\u0117s, kurios susietos su \u0161ia sud\u0117tine role.
+partial-import=Dalinis duomen\u0173 importavimas
+partial-import.tooltip=Dalinis duomen\u0173 importavimas leid\u017Eia \u012Fkelti prie\u0161 tai eksportuot\u0105 JSON rinkmen\u0105 su naudotojais, klientais ir kitais resursais.
+
+file=Rinkmena
+exported-json-file=Eksportuota JSON rinkmena
+import-from-realm=\u012Ekelti i\u0161 srities
+import-users=\u012Ekelti naudotojus
+import-groups=\u012Ekelti grupes
+import-clients=\u012Ekelti klientus
+import-identity-providers=\u012Ekelti tapatyb\u0117s teik\u0117jus
+import-realm-roles=\u012Ekelti srities roles
+import-client-roles=\u012Ekelti klient\u0173 roles
+if-resource-exists=Jei resursas egzistuoja
+fail=Nevykdyti
+skip=Praleisti
+overwrite=Perra\u0161yti
+if-resource-exists.tooltip=Nurodykite k\u0105 daryti kuomet bandoma \u012Fkelti jau egzistuojant\u012F resurs\u0105.
+
+action=Veiksmas
+role-selector=Roli\u0173 parinkimas
+realm-roles.tooltip=Srities rol\u0117s, kurias galima pasirinkti.
+
+select-a-role=Pasirinkti rol\u0119
+select-realm-role=Pasirinkti srities rol\u0119
+client-roles.tooltip=Kliento rol\u0117s, kurias galite pa\u017Eym\u0117ti.
+select-client-role=Pasirinkti kliento rol\u0119
+
+client-template=Kliento \u0161ablonas
+client-template.tooltip=Kliento \u0161ablonas, i\u0161 kurio paveldima konfig\u016Bracija
+client-saml-endpoint=Kliento SAML adresas
+add-client-template=Kliento \u0161ablono k\u016Brimas
+
+manage=Valdyti
+authentication=Autentifikavimas
+user-federation=Naudotoj\u0173 federavimas
+user-storage=Naudotoj\u0173 saugykla
+events=\u012Evykiai
+realm-settings=Srities nustatymai
+configure=Konfig\u016Bruoti
+select-realm=Pasirinkite srit\u012F
+add=Prid\u0117ti
+
+client-template.name.tooltip=Kliento \u0161ablono pavadinimas. Privalo b\u016Bti unikalus \u0161ioje srityje
+client-template.description.tooltip=Kliento \u0161ablono apra\u0161ymas
+client-template.protocol.tooltip=Kurio SSO protokolo konfig\u016Bracija teikia \u0161is \u0161ablonas
+
+add-user-federation-provider=Prid\u0117ti naudotoj\u0173 federacijos teik\u0117ja
+required-settings=Privalomi nustatymai
+provider-id=Teik\u0117jo ID
+console-display-name=Konsol\u0117je rodomas pavadinimas
+console-display-name.tooltip=Administravimo konsol\u0117je rodomas teik\u0117jo pavadinimas.
+priority=Prioritetas
+priority.tooltip=Skai\u010Dius nurodantis naudotojo paie\u0161kos \u0161iame federacijos teik\u0117juje prioritet\u0105. Pirmiausia imama su ma\u017Eesniu skai\u010Diumi.
+sync-settings=Sinchronizuoti nustatymus
+periodic-full-sync=Pilnas periodinis sinchronizavimas
+periodic-full-sync.tooltip=Ar turi b\u016Bti atliekamas periodinis pilnas teik\u0117jo naudotoj\u0173 sinchronizavimas \u012F Keycloak?
+full-sync-period=Pilno sinchronizavimo intervalas
+full-sync-period.tooltip=Laikas sekund\u0117mis, kas kur\u012F atliekamas pilnas naudotoj\u0173 sinchronizavimas \u012F Keycloak sistem\u0105
+periodic-changed-users-sync=Periodinis pakeitim\u0173 sinchronizavimas
+periodic-changed-users-sync.tooltip=Ar turi b\u016Bti atliekamas naujai u\u017Eregistruot\u0173 naudotoj\u0173 ar naudotoj\u0173 su redaguotais profilio duomenimis periodinis sinchronizavimas \u012F Keycloak?
+changed-users-sync-period=Periodinis sinchronizavimo intervalas
+changed-users-sync-period.tooltip=Laikas sekund\u0117mis, kas kur\u012F atliekamas naujai u\u017Eregistruot\u0173 naudotoj\u0173 ar naudotoj\u0173 su redaguotais profilio duomenimis sinchronizavimas \u012F Keycloak 
+synchronize-changed-users=Sinchronizuoti naudotoj\u0173 pakeitimus
+synchronize-all-users=Sinchronizuoti visus naudotojus
+kerberos-realm=Kerberos sritis
+kerberos-realm.tooltip=Kerberos srities pavadinimas. Pavyzd\u017Eiui FOO.ORG
+server-principal=Pagrindinis serveris
+server-principal.tooltip=Pilnas HTTP paslaugai skirtas pagrindinio serverio su domenu pavadinimas. Pavyzd\u017Eiui HTTP/host.foo.org@FOO.ORG
+keytab=KeyTab
+keytab.tooltip=Kelias iki Kerberos KeyTab rinkmenos talpinan\u010Dios prisijungimo prie pagrindinio serverio duomenis. Pavyzd\u017Eiui /etc/krb5.keytab
+debug=Derinti
+debug.tooltip=Ar \u012Fgalinti Krb5LoginModule veikimo prane\u0161im\u0173 ra\u0161ym\u0105 \u012F standarin\u0119 i\u0161vest\u012F derinimo r\u0117\u017Eimu?
+allow-password-authentication=Leisti autentifikacij\u0105 naudojant slapta\u017Eod\u012F
+allow-password-authentication.tooltip=Ar suteikti galimyb\u0119 naudotojui prisijungti prie Kerberos naudojant naudotojo vard\u0105 ir slapta\u017Eod\u012F?
+edit-mode=Pakeitim\u0173 r\u0117\u017Eimas
+edit-mode.tooltip=READ_ONLY rei\u0161kia, kad naudotojui neleid\u017Eiama keisti slapta\u017Eod\u017Eio ir autentifikacija visuomet bus atliekama Kerberos. UNSYNCED rei\u0161kia, kad naudotojui leid\u017Eiama keisti slapta\u017Eod\u012F saugom\u0105 Keycloak duomen\u0173 baz\u0117je ir kuris bus naudojamas autentifikacijos metu vietoj Kerberos slapta\u017Eod\u017Eio.
+ldap.edit-mode.tooltip=READ_ONLY rei\u0161kia, kad LDAP saugykla bus naudojama vien tik skaitymo r\u0117\u017Eimu. WRITABLE rei\u0161kia, kad duomenys sinchronizuojami atgal \u012F LDAP pagal poreik\u012F. UNSYNCED rei\u0161kia, kad naudotoj\u0173 duomenys bus importuoti, ta\u010Diau niekuomet nesinchronizuojami atgal \u012F LDAP.
+update-profile-first-login=Pirmojo prisijungimo metu atnaujinti duomenis
+update-profile-first-login.tooltip=Pirmojo prisijungimo metu atnaujinti naudotojo profilio duomenis
+sync-registrations=Sinchronizuoti registracijas
+ldap.sync-registrations.tooltip=Ar naujai u\u017Esiregistrav\u0119 naudotojai tur\u0117t\u0173 b\u016Bti sinchonizuojami \u012F LDAP saugykl\u0105? Federavimo teik\u0117jas, \u012F kur\u012F sinchronizuojami nauji naudotojai, parenkamas pagal prioritet\u0105. Pirmiausia imami su ma\u017Eiausiu skai\u010Diumi.
+vendor=Gamintojas
+ldap.vendor.tooltip=LDAP gamintojas (teik\u0117jas)
+username-ldap-attribute=Prisijungimo vardo LDAP atributas
+ldap-attribute-name-for-username=LDAP atributo pavadinimas, kuriame saugomas naudotojo prisijungimo vardas
+username-ldap-attribute.tooltip=LDAP atributas, kuris turi b\u016Bti susietas su Keycloak naudotojo prisijungimo vardu. Su daugeliu LDAP serveri\u0173 gali b\u016Bti naudojamas 'uid' atributas. ActiveDirectory gali b\u016Bti 'sAMAccountName' arba 'cn'. Reikalaujama, kad nurodytas LDAP atributas b\u016Bt\u0173 u\u017Epildytas visiems naudotojams kurie importuojami i\u0161 LDAP \u012F Keycloak.
+rdn-ldap-attribute=RDN LDAP atributas
+ldap-attribute-name-for-user-rdn=LDAP atributo pavadinimas, kuriame saugomas naudotojo RDN
+rdn-ldap-attribute.tooltip=LDAP atributas, kuris naudojamas kaip RDN (Relative Distinguished Name) vietoj tipinio naudotojo DN (Distinguished Name). Da\u017Eniausiai reik\u0161m\u0117 sutampa su prisijungimo vardo LDAP atributu, ta\u010Diau pastarasis n\u0117ra privalomas. Pavyzd\u017Eiui ActiveDirectory da\u017Eniausiai kaip RDN atributas naudojamas 'cn' nors prisijungimo vardo atributas b\u016Bna 'sAMAccountName'.
+uuid-ldap-attribute=UUID LDAP atributas
+ldap-attribute-name-for-uuid=LDAP atributo pavadinimas, kuriame saugomas UUID
+uuid-ldap-attribute.tooltip=LDAP atributas, kuris naudojamas kaip unikalus LDAP objekt\u0173 identifikatorius (UUID). Daugelis LDAP serveri\u0173 naudoja 'entryUUID', ta\u010Diau pasitaiko ir i\u0161im\u010Di\u0173. Pavyzd\u017Eiui ActiveDirectory naudojamas 'objectGUID' atributas. Jei j\u016Bs\u0173 LDAP serveris nepalaiko UUID atribut\u0173, tuomet galite naudoti bet kur\u012F kit\u0105 atribut\u0105 kuris u\u017Etikrina LDAP naudotoj\u0173 unikalum\u0105. Pavyzd\u017Eiui 'uid' arba 'entryDN'.
+user-object-classes=Naudotoj\u0173 objekt\u0173 klas\u0117s
+ldap-user-object-classes.placeholder=LDAP naudotoj\u0173 objekt\u0173 klas\u0117s (skiriamos kableliu)
+ldap.user-object-classes.tooltip=LDAP atributo objectClass atskirtos kableliu reik\u0161m\u0117s skirtos LDAP naudotojo objektui. Pavyzd\u017Eiui: 'inetOrgPerson, organizationalPerson' . Naujai registruoti Keycloak naudotojai bus \u012Fra\u0161yti \u0161 LDAP su visomis nurodytomis objekt\u0173 klas\u0117mis. Egzistuojantys LDAP naudotoj\u0173 objektai randami tik tuomet, kai jie turi visas \u0161ias nurodytas objekto klases.
+
+ldap-connection-url=LDAP jungties URL
+ldap-users-dn=LDAP naudotoj\u0173 DN
+ldap-bind-dn=LDAP prisijungimo DN
+ldap-bind-credentials=LDAP prisijungimo slapta\u017Eodis
+ldap-filter=LDAP filtras
+
+connection-url=Jungties URL
+ldap.connection-url.tooltip=Jungties \u012F LDAP server\u012F URL
+test-connection=Tikrinti jungt\u012F
+users-dn=Naudotoj\u0173 DN
+ldap.users-dn.tooltip=\u0160aknin\u0117 LDAP med\u017Eio DN (Distinguished Name) kuriame saugomi naudotojai. Jei pavyzd\u017Eiui tipinio naudotojo DN yra 'uid=john,ou=users,dc=example,dc=com' tuomet \u0161io atributo reik\u0161m\u0117 tur\u0117t\u0173 b\u016Bti 'ou=users,dc=example,dc=com' 
+authentication-type=Autentifikacijos tipas
+ldap.authentication-type.tooltip=LDAP autentifikacijos tipas. Galimi 'none' (anonimin\u0117 LDAP prieiga) arba 'simple' (Prisijungimo DN + slapta\u017Eodis autentifikacijai) autentifikacijos b\u016Bdai
+bind-dn=Prisijungimo DN
+ldap.bind-dn.tooltip=LDAP administratoriaus DN (Distinguished Name), kuris turi b\u016Bti naudojamas Keycloak prieiti prie LDAP serverio
+bind-credential=Prisijungimo slapta\u017Eodis
+ldap.bind-credential.tooltip=LDAP administratoriaus slapta\u017Eodis
+test-authentication=Tikrinti autentifikacij\u0105
+custom-user-ldap-filter=Papildomas naudotoj\u0173 LDAP filtras
+ldap.custom-user-ldap-filter.tooltip=Papildomas LDAP filtras, kuris turi b\u016Bti naudojamas surast\u0173 naudotoj\u0173 nufiltravimui. Palikite tu\u0161\u010Di\u0105 lauk\u0105 jei papildomas filtravimas nereikalingas. \u012Esitikinkite, kad filtras prasideda '(' ir baigiasi ')' simboliais
+search-scope=Paie\u0161kos apimtis
+ldap.search-scope.tooltip=Jei pasirinkta vieno lygio paie\u0161ka, tuomet naudotoj\u0173 ie\u0161koma vien tik nurodytame naudotoj\u0173 DN. Kai pasirinkta paie\u0161ka medyje, tuomet naudotoj\u0173 ie\u0161koma visose med\u017Eio \u0161akose. I\u0161samesn\u0117s informacijos ie\u0161kokite LDAP dokumentacij\u0105
+use-truststore-spi=Naudoti rakt\u0173 saugyklos SPI
+ldap.use-truststore-spi.tooltip=Nurodykite, kuomet LDAP jungtis naudos standalone.xml/domain.xml sukonfig\u016Bruot\u0105 patikim\u0173 liudijim\u0173/rakt\u0173 saugyklos SPI. 'Visada' rei\u0161kia, kad bus naudojama visada. 'Niekada' rei\u0161kia, kad sukonfig\u016Bruota liudijim\u0173 saugykla nebus naudojama. 'Tik LDAP' rei\u0161kia, kad saugykla bus naudojama tik su LDAP jungtimis. Pastaba: jei standalone.xml/domain.xml nesukonfig\u016Bruotas, tuomet bus naudojama standartin\u0117 Java cacerts arba 'javax.net.ssl.trustStore' parametre nurodyta liudijim\u0173 saugykla.
+connection-pooling=Jung\u010Di\u0173 buferizavimas
+ldap.connection-pooling.tooltip=Ar Keycloak tur\u0117t\u0173 naudoti jung\u010Di\u0173 telkin\u012F jungiantis prie LDAP serverio?
+ldap.pagination.tooltip=Ar LDAP serveris palaiko puslapiavim\u0105?
+kerberos-integration=Kerberos intergacija
+allow-kerberos-authentication=Leisti Kerberos autentifikacij\u0105
+ldap.allow-kerberos-authentication.tooltip=\u012Egalina HTTP naudotoj\u0173 autentifikacij\u0105 naudojant SPNEGO/Kerberos raktus. Duomenys apie prisijungus\u012F naudotoj\u0105 bus teikiama \u0161io LDAP serverio
+use-kerberos-for-password-authentication=Naudoti Kerberos autentifikacijai su slapta\u017Eod\u017Eiu
+ldap.use-kerberos-for-password-authentication.tooltip=Ar jungiantis su naudotojo vardu ir slapta\u017Eod\u017Eiu naudoti Kerberos server\u012F vietoj LDAP serverio Directory Service API
+batch-size=Paketo dydis
+ldap.batch-size.tooltip=Vienos tranzacijos metu \u012F Keycloak importuojam\u0173 LDAP naudotoj\u0173 skai\u010Dius.
+ldap.periodic-full-sync.tooltip=Ar \u012Fgalinti periodin\u0119 piln\u0105 LDAP naudotoj\u0173 sinchronizacij\u0105 \u012F Keycloak?
+ldap.periodic-changed-users-sync.tooltip=Ar \u012Fgalinti periodin\u0119 naujai registruot\u0173 arba su pakeistais duomenimis LDAP naudotoj\u0173 sinchronizacij\u0105 \u012F Keycloak? 
+ldap.changed-users-sync-period.tooltip=Intervalas sekund\u0117mis, kas kur\u012F atliekamas periodinis naujai registruot\u0173 arba su pakeistais duomenimis LDAP naudotoj\u0173 sinchronizavimas \u012F Keycloak
+user-federation-mappers=Federuoto naudotojo atribut\u0173 atitikmenys
+create-user-federation-mapper=Sukurti federuoto naudotojo atributo atitikmen\u012F
+add-user-federation-mapper=Prid\u0117ti federuoto naudotojo atributo atitikmen\u012F
+provider-name=Teik\u0117jo pavadinimas
+no-user-federation-providers-configured=Nesukonfig\u016Bruotas nei vienas naudotoj\u0173 federacijos teik\u0117jas
+no-user-storage-providers-configured=Nesukonfig\u016Bruota nei viena naudotoj\u0173 saugykla
+add-identity-provider=Prid\u0117ti tapatyb\u0117s teik\u0117j\u0105
+add-identity-provider-link=Prid\u0117ti s\u0105saj\u0105 su tapatyb\u0117s teik\u0117ju
+identity-provider=Tapatyb\u0117s teik\u0117jas
+identity-provider-user-id=Tapatyb\u0117s teik\u0117jo naudotojo ID
+identity-provider-user-id.tooltip=Unikalus, tapatyb\u0117s teik\u0117jo saugomas, naudotojo ID 
+identity-provider-username=Tapatyb\u0117s teik\u0117jo naudotojo vardas
+identity-provider-username.tooltip=Tapatyb\u0117s teik\u0117jo sistemoje saugomas naudotojo vardas
+pagination=Puslapiavimas
+
+browser-flow=Autentifikacijos seka
+browser-flow.tooltip=Pasirinkite autentifikacijos nar\u0161ykl\u0117je sek\u0105
+registration-flow=Registracijos seka
+registration-flow.tooltip=Pasirinkite registracijos nar\u0161ykl\u0117je sek\u0105.
+direct-grant-flow=Tiesiogini\u0173 teisi\u0173 seka
+direct-grant-flow.tooltip=Pasirinkite tiesiogini\u0173 teisi\u0173 sek\u0105 (direct grant authentication).
+reset-credentials=Prisijungimo duomen\u0173 atk\u016Brimo seka
+reset-credentials.tooltip=Pasirinkite prisijungimo duomen\u0173 priminimo nar\u0161ykl\u0117je sek\u0105
+client-authentication=Klient\u0173 autentifikacijos seka
+client-authentication.tooltip=Pasirinkite klient\u0173 autentifikacijos sek\u0105.
+new=Naujas
+copy=Kopijuoti
+add-execution=Prid\u0117ti i\u0161imt\u012F
+add-flow=Prid\u0117ti sek\u0105
+auth-type=Autentifikacijos tipas
+requirement=Privalomumas
+config=Konfig\u016Bruoti
+no-executions-available=N\u0117ra sukonfig\u016Bruot\u0173 i\u0161im\u010Di\u0173
+authentication-flows=Autentifikacijos sekos
+create-authenticator-config=Sukurti autentifikatoriaus konfig\u016Bracij\u0105
+authenticator.alias.tooltip=Konfig\u016Bracijos pavadinimas
+otp-type=OTP tipas
+time-based=Paremtas laiku
+counter-based=Paremtas skaitliuku
+otp-type.tooltip='totp' paremtas ribot\u0105 laik\u0105 galiojan\u010Diu vienkartiniu slapta\u017Eod\u017Eiu. 'hotp' - ribot\u0105 kart\u0173 galiojan\u010Diu vienkartiniu slapta\u017Eod\u017Eiu.
+otp-hash-algorithm=OTP mai\u0161os algoritmas
+otp-hash-algorithm.tooltip=Kuris mai\u0161os algoritmas turi b\u016Bti naudojamas OTP generavimui.
+number-of-digits=Skaitmen\u0173 skai\u010Dius
+otp.number-of-digits.tooltip=Kiek OTP tur\u0117t\u0173 tur\u0117ti skaitmen\u0173?
+look-ahead-window=Neatitikimo langas
+otp.look-ahead-window.tooltip=Koks intervalas yra leid\u017Eiamas tuo atveju, kai prieigos rakt\u0173 generatoriaus ir serverio laikai arba skaitliukai nesutampa. 
+initial-counter=Pradin\u0117 skaitliuko reik\u0161m\u0117
+otp.initial-counter.tooltip=Kokia turi b\u016Bti pradin\u0117 skaitliuko reik\u0161m\u0117?
+otp-token-period=OTP rakto galiojimo intervalas
+otp-token-period.tooltip=Kiek sekund\u017Eiu galios OTP prieigos raktas? Numatyta reik\u0161m\u0117 30 sekund\u017Ei\u0173.
+table-of-password-policies=Slapta\u017Eod\u017Eio taisykli\u0173 lentel\u0117
+add-policy.placeholder=Prid\u0117ti taisykl\u0119...
+policy-type=Taisykl\u0117s tipas
+policy-value=Taisykl\u0117s reik\u0161m\u0117
+admin-events=Administravimo \u012Fvykiai
+admin-events.tooltip=Rodomi srities administravimo \u012Fvykiai susij\u0119 su  administratoriaus paskyra, pvz. srities k\u016Brimas. Pasirinkite konfig\u016Bravimo skilt\u012F nor\u0117dami kad \u012Fvykiai b\u016Bt\u0173 saugomi.
+login-events=Prisijungimo \u012Fvykiai
+filter=Filtruoti
+update=Atnaujinti
+reset=I\u0161valyti
+resource-types=Resurso tipas
+operation-types=Veiksmas
+select-operations.placeholder=Pasirinkite veiksmus...
+resource-path=Resurso kelias
+resource-path.tooltip=Filtravimas pagal resurso keli\u0105. Palaikomas pakaitos simbolis '*' atitinkantis vien\u0105 kelio element\u0105 ir '**' daugiau nei vien\u0105 element\u0105. Pavyzd\u017Eiui 'realms/*/clients/asbc' visose sritise randa klient\u0105 su identifikatoriumi 'asbc'. Kitas pavyzdys 'realms/master/**' randa visus veiksmus 'master' srityje.
+date-(from)=Data (Nuo)
+date-(to)=Data (Iki)
+authentication-details=Autentifikacijos informacija
+ip-address=IP adresas
+time=Laikas
+operation-type=Veiksmo tipas
+auth=Autentifikacijos informacija
+representation=Reprezentacija
+register=Registracijos
+required-action=Privalomi veiksmai
+default-action=Numatytas veiksmas
+auth.default-action.tooltip=Jei \u012Fgalintas, tuomet visi nauji naudotojai prival\u0117s atlikti pa\u017Eym\u0117tus veiksmus.
+no-required-actions-configured=N\u0117ra nei vieno sukonfig\u016Bruoto privalomo veiksmo
+defaults-to-id=Nenurod\u017Eius bus naudojamas identifikatorius
+flows=Sekos
+bindings=S\u0105ry\u0161iai
+required-actions=Privalomi veiksmai
+password-policy=Slapta\u017Eod\u017Ei\u0173 taisykl\u0117s
+otp-policy=OTP taisykl\u0117s
+user-groups=Naudotoj\u0173 grup\u0117s
+default-groups=Numatytos grup\u0117s
+groups.default-groups.tooltip=Nurodykite grupes, \u012F kurias automati\u0161kai \u012Ftraukiami nauji naudotojai.
+cut=I\u0161kirpti
+paste=\u012Eklijuoti
+
+create-group=Sukurti grup\u0119
+create-authenticator-execution=Sukurti autentifikatoriaus veiksmo vykdym\u0105
+create-form-action-execution=Sukurti formos veiksmo vykdym\u0105
+create-top-level-form=Sukurti auk\u0161\u010Diausio lygio form\u0105
+flow.alias.tooltip=\u012Era\u0161ykite sekos rodom\u0105 pavadinim\u0105.
+top-level-flow-type=Auk\u0161\u010Diausio lygio sekos tipas
+flow.generic=generic
+flow.client=client
+top-level-flow-type.tooltip=Kokio tipo \u0161i auk\u0161\u010Diausio lygio sritis? 'client' tipas naudojamas klient\u0173 (program\u0173) autentifikacijai. 'generic' naudojamas visais kitais atvejais.
+create-execution-flow=Sukurti vykdymo sek\u0105
+flow-type=Sekos tipas
+flow.form.type=form
+flow-type.tooltip=Kokios r\u016B\u0161ies \u0161i forma?
+form-provider=Formos teik\u0117jas
+default-groups.tooltip=Naujai sukurti ar u\u017Eregistruoti naudotojai automati\u0161kai priskiriami \u0161ioms grup\u0117ms
+select-a-type.placeholder=pasirinkite tip\u0105
+available-groups=Galimos grup\u0117s
+available-groups.tooltip=Nurodykite grup\u0119, kuri bus numatytoji.
+value=Reik\u0161m\u0117
+table-of-group-members=Grup\u0117s nari\u0173 lentel\u0117
+last-name=Pavard\u0117
+first-name=Vardas
+email=El. pa\u0161tas
+toggle-navigation=Perjungti navigacij\u0105
+manage-account=Valdyti paskyr\u0105
+sign-out=Atsijungti
+server-info=Serverio informacija
+resource-not-found=Resuras <strong>nerastas</strong>...
+resource-not-found.instruction=Negalime rasti j\u016Bs\u0173 ie\u0161komo resurso. \u012Esitikinkite, kad \u012Fved\u0117te teising\u0105 URL.
+go-to-the-home-page=Eiti \u012F pradin\u012F puslap\u012F &raquo;
+page-not-found=Puslapis <strong>nerastas</strong>...
+page-not-found.instruction=Negalime rasti j\u016Bs\u0173 ie\u0161komo puslapio. \u012Esitikinkite, kad \u012Fved\u0117te teising\u0105 URL.
+events.tooltip=Rodomi srities i\u0161saugoti \u012Fvykiai. Rodomi \u012Fvykiai susij\u0119 su naudotoj\u0173 paskyromis, pavyzd\u017Eiui naudotojo prisijungimas. Nor\u0117dami keisti nustatymus pasirinkite 'Konfig\u016Bruoti'
+select-event-types.placeholder=Pasirinkite \u012Fvykiu tipus...
+events-config.tooltip=Rodoma naudotoj\u0173 ir administravimo \u012Fvyki\u0173 konfig\u016Bracija.
+select-an-action.placeholder=Pasirinkite veiksm\u0105...
+event-listeners.tooltip=Nurodykite srities \u012Fvyki\u0173 gav\u0117jus.
+login.save-events.tooltip=Jei \u012Fgalinta, tuomet su prisijungimu susij\u0119 veiksmai saugomi duomen\u0173 baz\u0117je ir tampa prieinami per administravimo bei naudotojo paskyros valdymo skydus. 
+clear-events.tooltip=I\u0161trinti visus \u012Fvykius i\u0161 duomen\u0173 baz\u0117s.
+events.expiration.tooltip=Nustato \u012Fvyki\u0173 galiojimo laik\u0105. Nebegaliojantys \u012Fvykiai periodi\u0161kai i\u0161trinami i\u0161 duomen\u0173 baz\u0117s.
+admin-events-settings=Administravimo veiksm\u0173 nustatymai
+save-events=Saugoti \u012Fvykius
+admin.save-events.tooltip=Jei \u012Fgalinta, tuomet administravimo veiksmai saugomi duomen\u0173 baz\u0117je ir tampa prieinami per administravimo valdymo skyd\u0105.
+saved-types.tooltip=Nurodykite veiksm\u0173 tipus, kurie tur\u0117t\u0173 b\u016Bti i\u0161saugoti.
+include-representation=I\u0161saugoti reprezentacij\u0105
+include-representation.tooltip=I\u0161saugoti kur\u016Bmo ir redagavimo u\u017Eklaus\u0173 JSON reprezentacij\u0105.
+clear-admin-events.tooltip=I\u0161trina visus su administravimu susijusius veiksmus i\u0161 duomen\u0173 baz\u0117s.
+server-version=Serverio versija
+info=Informacija
+providers=Teik\u0117jai
+server-time=Serverio laikas
+server-uptime=Serverio veikimo laikas
+memory=Atmintis
+total-memory=Viso atminties
+free-memory=Laisva atmintis
+used-memory=Naudojama atmintis
+system=Sistema
+current-working-directory=Darbinis katalogas
+java-version=Java Version
+java-vendor=Java Vendor
+java-runtime=Java Runtime
+java-vm=Java VM
+java-vm-version=Java VM Version
+java-home=Java Home
+user-name=User Name
+user-timezone=User Timezone
+user-locale=User Locale
+system-encoding=System Encoding
+operating-system=Operating System
+os-architecture=OS Architecture
+spi=SPI
+granted-roles=Suteiktos rol\u0117s
+granted-protocol-mappers=Suteiktos protokolo atitikmen\u0173 s\u0105sajos
+additional-grants=Papildomai suteikta
+revoke=At\u0161aukti
+new-password=Naujas slapta\u017Eodis
+password-confirmation=Pakartotas slapta\u017Eodis
+reset-password=Pakeisti slapta\u017Eod\u012F
+credentials.temporary.tooltip=Jei \u012Fgalinta, tuomet naudotojas prival\u0117s pasikeisti slapta\u017Eod\u012F sekan\u010Dio prisijungimo metu
+remove-totp=\u0160alinti TOTP
+credentials.remove-totp.tooltip=\u0160alinti vienkartin\u012F naudotojo slapta\u017Eod\u017Ei\u0173 generatori\u0173.
+reset-actions=Atkurti veiksmus
+credentials.reset-actions.tooltip=Nurodykite naudotojui el. pa\u0161tu siun\u010Diamus privalomus atlikti veiksmus. 'Patvirtinti el. pa\u0161to adres\u0105' \u012F naudotojo el. pa\u0161to adres\u0105 siun\u010Dia patvirtinimo nuorod\u0105. 'Atnaujinti profilio informacij\u0105' reikalauja naudotojo per\u017Ei\u016Br\u0117ti ir atnaujinti profilio informacij\u0105. 'Atnaujinti slapta\u017Eod\u012F' reikalauja naudotojo pasikeisti slapta\u017Eod\u012F. 'Konfig\u016Bruoti TOTP' reikalauja atnaujinti mobilaus slapta\u017Eod\u017Ei\u0173 generatoriaus konfig\u016Bracij\u0105.
+reset-actions-email=Atk\u016Brimo veiksm\u0173 siuntimas
+send-email=Si\u0173sti el. pa\u0161to lai\u0161k\u0105
+credentials.reset-actions-email.tooltip=Naudotojui siun\u010Diamas el. pa\u0161to lai\u0161kas su nuorodomis leid\u017Eian\u010Diomis atlikti pasirinktus veiksmus. Naudotojas atidar\u0119s siun\u010Diam\u0105 nuorod\u0105 gal\u0117s atlikti atk\u016Brimo veiksmus. Veism\u0173 atlikimui naudotoj\u0173 nebus reikalaujama prisijungti. Pavyzd\u017Eiui parinkus slapta\u017Eod\u017Eio atk\u016Brimo veiksm\u0105, naudotojas gal\u0117s neprisijung\u0119s nurodyti nauj\u0105 slapta\u017Ed\u012F.
+add-user=Prid\u0117ti naudotoj\u0105
+created-at=Suk\u016Brimo data
+user-enabled=Naudotojas \u012Fgalintas
+user-enabled.tooltip=Ne\u012Fgalintam naudotojai neleid\u017Eiama prisijungti prie sistemos. 
+user-temporarily-locked=Naudotojas laikinai u\u017Erakintas
+user-temporarily-locked.tooltip=Naudotojas laikintai u\u017Erakintas, nes per daug klydo prisijungiant prie sistemos.
+unlock-user=Atrakinti naudotoj\u0105
+federation-link=Federacijos s\u0105saja
+email-verified=El. pa\u0161tas patvirtintas
+email-verified.tooltip=Ar naudotojo el. pa\u0161to adresas yra patvirtintas?
+required-user-actions=Privalomi veiksmai naudotojui
+required-user-actions.tooltip=Nurodykite kuriuos veiksmus po prisijungimo naudotojas privalo atlikti. 'Patvirtinti el. pa\u0161to adres\u0105' \u012F naudotojo el. pa\u0161to adres\u0105 siun\u010Dia patvirtinimo nuorod\u0105. 'Atnaujinti profilio informacij\u0105' reikalauja naudotojo per\u017Ei\u016Br\u0117ti ir atnaujinti profilio informacij\u0105. 'Atnaujinti slapta\u017Eod\u012F' reikalauja naudotojo pasikeisti slapta\u017Eod\u012F. 'Konfig\u016Bruoti TOTP' reikalauja atnaujinti mobilaus slapta\u017Eod\u017Ei\u0173 generatoriaus konfig\u016Bracij\u0105.
+locale=Lokal\u0117
+select-one.placeholder=Pasirinkite...
+impersonate=\u012Ek\u016Bnyti
+impersonate-user=\u012Ek\u016Bnyti naudotoj\u0105
+impersonate-user.tooltip=Prisijungti kaip \u0161is naudotojas. Jei j\u016Bs\u0173 sritis sutampa su naudotojo sritimi, tuomet j\u016Bs\u0173 sesija bus baigta prie\u0161 prisijungiant \u0161iuo naudotoju.
+identity-provider-alias=Tapatyb\u0117s teik\u0117jo pseudonimas
+provider-user-id=Teik\u0117jo naudotojo ID
+provider-username=Teik\u0117jo naudotojo vardas
+no-identity-provider-links-available=N\u0117ra nei vienos tapatyb\u0117s teik\u0117jo s\u0105sajos
+group-membership=Naryst\u0117 grup\u0117se
+group-membership.tooltip=Visos grup\u0117s, kuri\u0173 narys yra \u0161is naudotojas. Pa\u017Eym\u0117kite grup\u0119 ir paspauskite 'Palikti' nor\u0117dami pa\u0161alinti naudotoj\u0105 i\u0161 grup\u0117s.
+leave=Palikti
+membership.available-groups.tooltip=Grup\u0117s, \u012F kurias galima \u012Ftraukti naudotoj\u0105. Pa\u017Eym\u0117kite grup\u0119 ir paspauskite \u012Ftraukti.
+table-of-realm-users=Srities naudotoj\u0173 s\u0105ra\u0161as
+view-all-users=Rodyti visus naudotojus
+unlock-users=Atrakinti naudotojus
+no-users-available=Naudotoj\u0173 n\u0117ra
+users.instruction=\u012Eveskite paie\u0161kos kriterij\u0173 arba paspauskite rodyti visus naudotojus
+consents=Sutikimai
+started=Prad\u0117ta
+logout-all-sessions=Atjungti visas sesijas
+logout=Seanso pabaiga
+new-name=Naujas pavadinimas
+ok=Gerai
+attributes=Atributai
+role-mappings=Roli\u0173 susiejimas
+members=Nariai
+details=Detaliau
+identity-provider-links=S\u0105sajos su tapatyb\u0117s teik\u0117jais
+register-required-action=Registruoti privalom\u0105 atlikti veiksm\u0105
+gender=Lytis
+address=Adresas
+phone=Telefonas
+profile-url=Profilio URL
+picture-url=Nuotraukos URL
+website=Internetin\u0117 svetain\u0117
+import-keys-and-cert=Importuoti raktus ir sertifikatus
+import-keys-and-cert.tooltip=\u012Ekelti kliento rakt\u0173 por\u0105 ir sertifikat\u0105.
+upload-keys=\u012Ekelti raktus
+download-keys-and-cert=Atsisi\u0173sti raktus ir sertifikat\u0105
+no-value-assigned.placeholder=N\u0117ra priskirtos reik\u0161m\u0117s
+remove=\u0160alinti
+no-group-members=Grup\u0117 neturi nari\u0173
+temporary=Laikinas
+join=Prijungti
+event-type=\u012Evykio tipas
+events-config=\u012Evyki\u0173 konfig\u016Bracija
+event-listeners=\u012Evyki\u0173 gav\u0117jai
+login-events-settings=Prisijungimo \u012Fvyki\u0173 nustatymai
+clear-events=I\u0161valyti \u012Fvykius
+saved-types=Saugomi tipai
+clear-admin-events=I\u0161valyti administravimo \u012Fvykius
+clear-changes=I\u0161valyti pasikeitimus
+error=Klaida
+
+# Authz
+# Authz Common
+authz-authorization=Autorizacija
+authz-owner=Savininkas
+authz-uri=URI
+authz-scopes=Taikymo sritys
+authz-resource=Resursas
+authz-resource-type=Resurso tipas
+authz-resources=Resursai
+authz-scope=Taikymo sritis
+authz-authz-scopes=Autorizacijos taikymo sritys
+authz-policies=Taisykl\u0117s
+authz-permissions=Leidimai
+authz-evaluate=I\u0161bandyti
+authz-icon-uri=Ikonos URI
+authz-icon-uri.tooltip=Ikonos paveiksliuko URI.
+authz-select-scope=Parinkite taikymo srit\u012F
+authz-select-resource=Parinkite resurs\u0105
+authz-associated-policies=Susietos taisykl\u0117s
+authz-any-resource=Bet kuris resursas
+authz-any-scope=Bet kuri taikymo sritis
+authz-any-role=Bet kuri rol\u0117
+authz-policy-evaluation=I\u0161bandyti taisykl\u0119
+authz-select-client=Parinkite klient\u0105
+authz-select-user=Parinkite naudotoj\u0105
+authz-entitlements=Teis\u0117s
+authz-no-resources=Resurs\u0173 n\u0117ra
+authz-result=Rezultatas
+authz-authorization-services-enabled=Autorizacija \u012Fgalinta
+authz-authorization-services-enabled.tooltip=\u012Egalinti detal\u0173 kliento autorizacijos palaikym\u0105
+authz-required=Privalimas
+
+# Authz Settings
+authz-import-config.tooltip=Importuoti \u0161io resurs\u0173 serverio autorizacijos nustatym\u0173 JSON rinkmen\u0105.
+
+authz-policy-enforcement-mode=Taisykli\u0173 vykdymo r\u0117\u017Eimas
+authz-policy-enforcement-mode.tooltip=Taisykli\u0173 vykdymo r\u0117\u017Eimas nusako kaip turi b\u016Bti tenkinamos autorizacijos u\u017Eklaus\u0173 taisykl\u0117s. 'Taikyti' rei\u0161kia, kad tuo atveju kai n\u0117ra sukonfig\u016Bruota nei viena su resursu susijusi taisykl\u0117, prieiga draud\u017Eiama. 'Liberalus' rei\u0161kia, kad tuo atveju kai n\u0117ra sukonfig\u016Bruota nei viena su resursu susijusi taisykl\u0117, prieiga leid\u017Eiama. 'I\u0161jungta' rei\u0161kia, kad neatliekamas taisykli\u0173 tikrinimas ir prieiga leid\u017Eiama prie vis\u0173 resurs\u0173.
+authz-policy-enforcement-mode-enforcing=Taikyti
+authz-policy-enforcement-mode-permissive=Liberalus
+authz-policy-enforcement-mode-disabled=I\u0161jungta
+
+authz-remote-resource-management=Nuotolinis resurs\u0173 valdymas
+authz-remote-resource-management.tooltip=Ar leid\u017Eiama nuotoliniu b\u016Bdu resurs\u0173 serveriui valdyti resursus? Jei ne\u012Fgalinta, tuomet resursai gali b\u016Bti valdomi tik per \u0161i\u0105 administravimo konsol\u0119.
+
+authz-export-settings=Eksportuoti nustatymus
+authz-export-settings.tooltip=Eksportuoti ir atsisi\u0173sti visus \u0161io resurs\u0173 serverio autorazacijos nustatymus.
+
+# Authz Resource List
+authz-no-resources-available=N\u0117ra galim\u0173 resurs\u0173.
+authz-no-scopes-assigned=N\u0117ra susiet\u0173 taikymo sri\u010Di\u0173.
+authz-no-type-defined=N\u0117ra nurodyt\u0173 tip\u0173.
+authz-no-permission-assigned=Nera susiet\u0173 leidim\u0173.
+authz-no-policy-assigned=N\u0117ra susiet\u0173 taisykli\u0173.
+authz-create-permission=Sukurti leidim\u0105
+
+# Authz Resource Detail
+authz-add-resource=Prid\u0117ti resurs\u0105
+authz-resource-name.tooltip=Unikalus resurso vardas. Vardas turi unikaliai identifikuoti resurs\u0105. Naudingas, kuomet ie\u0161koma specifini\u0173 resurs\u0173.
+authz-resource-owner.tooltip=\u0160io resurso savininkas.
+authz-resource-type.tooltip=\u0160io resurso tipas. Reik\u0161m\u0117 leid\u017Eia sugrupuoti skirtingus resursus turin\u010Dius t\u0105 pat\u012F tip\u0105.
+authz-resource-uri.tooltip=URI kuris taip pat gali b\u016Bti naudojamas vienareik\u0161mi\u0161kam resurso identifikavimui.
+authz-resource-scopes.tooltip=Su \u0161iuo resursu susietos taikymo sritys.
+
+# Authz Scope List
+authz-add-scope=Pri\u0117ti taikymo srit\u012F
+authz-no-scopes-available=N\u0117ra galim\u0173 taikymo sri\u010Di\u0173.
+
+# Authz Scope Detail
+authz-scope-name.tooltip=Unikalus taikymo srities pavadinimas. \u0160is pavadinimas gali vienareik\u0161mi\u0161kai identifikuoti taikymo srit\u012F. Naudingas kuomet ie\u0161koma \u0161ios tam tikros srities. 
+
+# Authz Policy List
+authz-all-types=Visi tipai
+authz-create-policy=Sukurti taisykl\u0119
+authz-no-policies-available=N\u0117ra galim\u0173 taisykli\u0173.
+
+# Authz Policy Detail
+authz-policy-name.tooltip=\u0160ios taisykl\u0117s pavadinimas.
+authz-policy-description.tooltip=\u0160ios taisykl\u0117s apra\u0161ymas.
+authz-policy-logic=Logika
+authz-policy-logic-positive=Teigiama
+authz-policy-logic-negative=Neigiama
+authz-policy-logic.tooltip=Logika nurodo kaip turi b\u016Bti tenkinama taisykl\u0117. Jei nurodyta 'Teigiama', tuomet \u0161ios taisykl\u0117s vykdymo metu gautas rezultatas (leisti arba drausti) bus naudojamas sprendinio pri\u0117mimui. Jei nurodyta 'Neigiama', tuomet \u0161ios taisykl\u0117s vykdymo rezultatas bus paneigtas, t.y. leid\u017Eiama taps draud\u017Eiama ir atvirk\u0161\u010Diai.
+authz-policy-apply-policy=Pritaikyti taisykl\u0119
+authz-policy-apply-policy.tooltip=Nurodo visas taisykles, kurios turi b\u016Bti \u012Fvertintos \u0161ios taisykl\u0117s ar leidimo taikymo sri\u010Diai.
+authz-policy-decision-strategy=Sprendimo strategija
+authz-policy-decision-strategy.tooltip=Sprendimo strategija nurodo kaip priimamas galutinis sprendimas, kuomet yra vykdomos visos \u0161io leidimo taisykl\u0117s. 'Pozityvi' rei\u0161kia, kad galutiniam teigiamam sprendimui turi b\u016Bti tenkinama bent viena taisykl\u0117. 'Vienbals\u0117' rei\u0161kia, kad galutiniam teigiamam sprendimui visos taisykl\u0117s turi b\u016Bti teigiamos. 'Daugumos' rei\u0161kia, kad galutinis teigiamas sprendimas bus priimtas tuomet, kai teigiam\u0173 taisykli\u0173 bus daugiau nei neigiam\u0173. Jei teigiam\u0173 ir neigiam\u0173 taisykli\u0173 skai\u010Dius yra vienodas, tuomet galutinis rezultatas bus neigiamas.
+authz-policy-decision-strategy-affirmative=Pozityvi
+authz-policy-decision-strategy-unanimous=Vienbals\u0117
+authz-policy-decision-strategy-consensus=Daugumos
+authz-select-a-policy=Parinkite taisykl\u0119
+
+# Authz Role Policy Detail
+authz-add-role-policy=Prid\u0117ti rol\u0117s taisykl\u0119
+authz-no-roles-assigned=N\u0117ra susiet\u0173 roli\u0173.
+authz-policy-role-realm-roles.tooltip=Nurodo kurios *srities* rol\u0117(s) tenkina \u0161i\u0105 taisykl\u0119.
+authz-policy-role-clients.tooltip=Parinkite klien\u0105 nor\u0117dami rodyti tik \u0161io kliento roles.
+authz-policy-role-client-roles.tooltip=Nurodo *kliento* rol\u0117(\u012Fs) kurios tenkina \u0161i\u0105 taisykl\u0119.
+
+# Authz User Policy Detail
+authz-add-user-policy=Prid\u0117ti naudotojo taisykl\u0119
+authz-no-users-assigned=N\u0117ra susiet\u0173 naudotoj\u0173.
+authz-policy-user-users.tooltip=Nurodo kurie naudotojai tenkina \u0161i\u0105 taisykl\u0119.
+
+# Authz Time Policy Detail
+authz-add-time-policy=Prid\u0117ti laiko taisykl\u0119
+authz-policy-time-not-before.tooltip=Nurodykite laik\u0105 iki kurio \u0161i taisykl\u0117 NETENKINAMA. Teigiamas rezultatas duodamas tik tuo atveju, kuomet dabartin\u0117 data ir laikas yra v\u0117lesn\u0117 arba lygi \u0161iai reik\u0161mei.
+authz-policy-time-not-on-after=Ne v\u0117liau
+authz-policy-time-not-on-after.tooltip=Nurodykite laik\u0105 po kurio \u0161i taisykl\u0117 NETENKINAMA. Teigiamas rezultatas duodamas tik tuo atveju, kuomet dabartin\u0117 data ir laikas yra ankstesni arba lygi \u0161iai reik\u0161mei.
+authz-policy-time-day-month=M\u0117nesio diena
+authz-policy-time-day-month.tooltip=Nurodykite m\u0117nesio dien\u0105 iki kurios \u0161i taisykl\u0117 TENKINAMA. U\u017Epild\u017Eius antr\u0105j\u012F laukel\u012F, taisykl\u0117 bus TENKINAMA jei diena patenka \u012F nurodyt\u0105 interval\u0105. Reik\u0161m\u0117s nurodomos imtinai.
+authz-policy-time-month=M\u0117nesis
+authz-policy-time-month.tooltip=Nurodykite m\u0117nes\u012F iki kurio \u0161i taisykl\u0117 TENKINAMA. U\u017Epild\u017Eius antr\u0105j\u012F laukel\u012F, taisykl\u0117 bus TENKINAMA jei m\u0117nesis patenka \u012F nurodyt\u0105 interval\u0105. Reik\u0161m\u0117s nurodomos imtinai.
+authz-policy-time-year=Metai
+authz-policy-time-year.tooltip=Nurodykite metus iki kuri\u0173 \u0161i taisykl\u0117 TENKINAMA. U\u017Epild\u017Eius antr\u0105j\u012F laukel\u012F, taisykl\u0117 bus TENKINAMA jei metai patenka \u012F nurodyt\u0105 interval\u0105. Reik\u0161m\u0117s nurodomos imtinai.
+authz-policy-time-hour=Valanda
+authz-policy-time-hour.tooltip=Nurodykite valand\u0105 iki kurios \u0161i taisykl\u0117 TENKINAMA. U\u017Epild\u017Eius antr\u0105j\u012F laukel\u012F, taisykl\u0117 bus TENKINAMA jei valanda patenka \u012F nurodyt\u0105 interval\u0105. Reik\u0161m\u0117s nurodomos imtinai.
+authz-policy-time-minute=Minut\u0117
+authz-policy-time-minute.tooltip=Nurodykite minut\u0119 iki kurios \u0161i taisykl\u0117 TENKINAMA. U\u017Epild\u017Eius antr\u0105j\u012F laukel\u012F, taisykl\u0117 bus TENKINAMA jei minut\u0117 patenka \u012F nurodyt\u0105 interval\u0105. Reik\u0161m\u0117s nurodomos imtinai.
+
+# Authz Drools Policy Detail
+authz-add-drools-policy=Prid\u0117ti Drools taisykl\u0119
+authz-policy-drools-maven-artifact-resolve=I\u0161spr\u0119sti
+authz-policy-drools-maven-artifact=Maven taisykl\u0117s artefaktas
+authz-policy-drools-maven-artifact.tooltip=Nuoroda \u012F Maven GAV artifakt\u0105 kuriame apra\u0161ytos taisykl\u0117s. Kai tik nurodysite GAV, galite paspausti *I\u0161spr\u0119sti* tam kad \u012Fkelti *Modulis* ir *Sesija* laukus.
+authz-policy-drools-module=Modulis
+authz-policy-drools-module.tooltip=\u0160ioje taisykl\u0117je naudojamas modulis. Privalote nurodyti modul\u012F tam, kad gal\u0117tum\u0117te pasirinkti specifin\u0119 sesij\u0105 taisykli\u0173 \u012Fk\u0117limui.
+authz-policy-drools-session=Sesija
+authz-policy-drools-session.tooltip=\u0160ioje taisykl\u0117je naudojama sesija. Sesija teikia taisykles reikalingas \u0161ios taisykl\u0117s vykdymui.
+authz-policy-drools-update-period=Atnaujinimo intervalas
+authz-policy-drools-update-period.tooltip=Nurodykite laiko interval\u0105, kas kur\u012F turi b\u016Bti ie\u0161koma artefakto atnaujinim\u0173.
+
+# Authz JS Policy Detail
+authz-add-js-policy=Prid\u0117ti JavaScript taisykl\u0119
+authz-policy-js-code=Programinis kodas
+authz-policy-js-code.tooltip=JavaScript kodas kuriame apra\u0161ytos \u0161ios taisykl\u0117s s\u0105lygos.
+
+
+# Authz Aggregated Policy Detail
+authz-aggregated=Agreguota
+authz-add-aggregated-policy=Prid\u0117ti agreguot\u0105 taisykl\u0119
+
+# Authz Permission List
+authz-no-permissions-available=N\u0117ra galim\u0173 leidim\u0173.
+
+# Authz Permission Detail
+authz-permission-name.tooltip=\u0160io leidimo pavadinimas.
+authz-permission-description.tooltip=\u0160io leidimo apra\u0161ymas.
+
+# Authz Resource Permission Detail
+authz-add-resource-permission=Prid\u0117ti resurso leidim\u0105
+authz-permission-resource-apply-to-resource-type=Pritaikyti resurso tipui
+authz-permission-resource-apply-to-resource-type.tooltip=Nurodykite ar \u0161is leidimas turi b\u016Bti pritaikomas visiems \u0161io tipo resursams. Jei \u012Fgalinta, tuomet leidimo tikrinimas bus atliekamas visiems nurodyto tipo resursams.
+authz-permission-resource-resource.tooltip=Nurodykite, kad \u0161is leidimas turi b\u016Bti taikomas tik tam tikriems resursams.
+authz-permission-resource-type.tooltip=Nurodykite, kad \u0161i taisykl\u0117 turi b\u016Bti taikoma visiems \u0161io tipo resursams.
+
+# Authz Scope Permission Detail
+authz-add-scope-permission=Prid\u0117ti taikymo srities leidim\u0105
+authz-permission-scope-resource.tooltip=Pasirinkdami resur\u0105 apribosite taikymo sri\u010Di\u0173 s\u0105ra\u0161\u0105. Jei nepasirinkta, tuomet matysite visas galimas taikymo sritis.
+authz-permission-scope-scope.tooltip=Nurodo, kad \u0161is leidimas turi b\u016Bti pritaikytas vienai ar daugiau taikymo sri\u010Di\u0173.
+
+# Authz Evaluation
+authz-evaluation-identity-information=Tapatyb\u0117s informacija
+authz-evaluation-identity-information.tooltip=Nurodykite tapatyb\u0117s informacij\u0105, kuri bus naudojama taisykli\u0173 vertinime.
+authz-evaluation-client.tooltip=Nurodykite klient\u0105, kuris atlieka autorizacijos u\u017Eklausas. Nei nenurodyta, tuomet autorizacijos u\u017Eklausa bus vertinama naudojant dabartin\u012F klient\u0105.
+authz-evaluation-user.tooltip=Nurodykite naudotoj\u0105, kurio vardu atliekamas teisi\u0173 serveryje filtravimas.
+authz-evaluation-role.tooltip=Nurodykite pasirinkto naudotojo roles.
+authz-evaluation-new=Papildyti u\u017Eklaus\u0105
+authz-evaluation-re-evaluate=Vertinti pakartotinai
+authz-evaluation-previous=Prie\u0161 tai buv\u0119s bandymas
+
+authz-evaluation-contextual-info=Kontekstin\u0117 informacija
+authz-evaluation-contextual-info.tooltip=Nurodykite kontekstin\u0119 informacij\u0105, kuri bus naudojama taisykli\u0173 vertinime.
+authz-evaluation-contextual-attributes=Kontekstiniai atributai
+authz-evaluation-contextual-attributes.tooltip=Galite pateikti vykdymo aplinkos arba vykdymo konteksto atributus.
+authz-evaluation-permissions.tooltip=Nurodykite leidimus, kuriems bus taikomos taisykl\u0117s.
+authz-evaluation-evaluate=Vertinti
+authz-evaluation-any-resource-with-scopes=Bet kuris resursas su \u0161ia taikymo sritimi (sritimis)
+authz-evaluation-no-result=Vertinant autorizacijos u\u017Eklaus\u0105 rezultat\u0173 nerasta. Patikrinkite ar egzistuoja resursai ar taikymo sritys susietos su taisykl\u0117mis.
+authz-evaluation-no-policies-resource=\u0160iam resursui taisykl\u0117s nerastos.
+authz-evaluation-result.tooltip=Leidim\u0173 u\u017Eklausos bendras rezultatas.
+authz-evaluation-scopes.tooltip=Leid\u017Eiam\u0173 taikymo sri\u010Di\u0173 s\u0105ra\u0161as.
+authz-evaluation-policies.tooltip=Informacija apie vertinime dalyvavusias taisykles ir sprendimus.
+authz-evaluation-authorization-data=Atsakymas
+authz-evaluation-authorization-data.tooltip=Autorizavimo u\u017Eklausos apdorojimo rezultatas su autorizacijos duomenimis. Rezultatas parodo k\u0105 Keycloak gr\u0105\u017Eina klientui pra\u0161an\u010Diam leidimo. Per\u017Ei\u016Br\u0117kite 'authorization' teigin\u012F su leidimais, kurie buvo suteikti \u0161iai autorizacijos u\u017Eklausai.
+authz-show-authorization-data=Rodyti autorizacijos duomenis
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_pt_BR.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_pt_BR.properties
index e69de29..5130658 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_pt_BR.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_pt_BR.properties
@@ -0,0 +1,1094 @@
+#encoding: utf-8
+consoleTitle=Console de Administração do Keycloak
+
+# Common messages
+enabled=Habilitado
+name=Nome
+displayName=Nome de exibição
+displayNameHtml=Nome de exibição HTML
+save=Salvar
+cancel=Cancelar
+onText=Sim
+offText=Não
+client=Cliente
+clients=Clientes
+clear=Limpar
+selectOne=Selecione Um...
+
+true=Sim
+false=Não
+
+endpoints=Endpoints
+
+# Realm settings
+realm-detail.enabled.tooltip=Usuários e clientes somente podem acessar um Realm se ele estiver habilitado
+realm-detail.oidc-endpoints.tooltip=Exibe a configuração dos endpoints do OpenID Connect
+registrationAllowed=Cadastro de usuário
+registrationAllowed.tooltip=Habilita/desabilita a página de cadastro. Um link para a página de cadastro também será exibido na tela de login.
+registrationEmailAsUsername=Email como nome de usuário
+registrationEmailAsUsername.tooltip=Se habilitado o campo 'nome de usuário' será ocultado no formulário de cadastro e o e-mail será usado como nome de usuário para o novo cadastro.
+editUsernameAllowed=Editar nome de usuário
+editUsernameAllowed.tooltip=Se habilitado, o campo nome de usuário é editável, senão será apenas leitura.
+resetPasswordAllowed=Esqueci a senha
+resetPasswordAllowed.tooltip=Exibe um link na página de login para o usuário clicar quando houver esquecido suas credenciais.
+rememberMe=Lembrar me
+rememberMe.tooltip=Exibe um checkbox na página de login para permitir ao usuário continuar logado entre restarts do browser até que a sessão expire.
+verifyEmail=Verificar e-mail
+verifyEmail.tooltip=Requer que o usuário verifique seu endereço de e-mail na primeira vez que efetuar login.
+sslRequired=SSL requerido
+sslRequired.option.all=todas requisições
+sslRequired.option.external=requisições externas
+sslRequired.option.none=nunca
+sslRequired.tooltip=É necessário SSL? 'Nunca' significa que HTTPS não é requerido para nenhum endereço IP cliente. 'Requisições externas' significa que localhost e IPs privados podem acessar sem HTTPS. 'Todas requisições' significa que HTTPS é requerido para todos os endereços IPs.
+publicKey=Chave pública
+privateKey=Chave privada
+gen-new-keys=Gerar novas chaves
+certificate=Certificado
+host=Host
+smtp-host=Host SMTP
+port=Porta
+smtp-port=Porta SMTP (valor padrão: 25)
+from=Remetente
+sender-email-addr=Endereço de e-mail do remetente
+enable-ssl=Habilitar SSL
+enable-start-tls=Habilitar StartTLS
+enable-auth=Habilitar autenticação
+username=Usuário
+login-username=Nome de usuário para login
+password=Senha
+login-password=Senha para login
+login-theme=Tema de login
+login-theme.tooltip=Selecione o tema para páginas de login, TOTP, grant, cadastro e recuperar senha.
+account-theme=Tema para conta
+account-theme.tooltip=Selecione o tema para as páginas de administração de conta do usuário.
+admin-console-theme=Tema para console de administração
+select-theme-admin-console=Selecione o tema para o console de administração.
+email-theme=Tema de e-mail
+select-theme-email=Selecione o tema para os e-mail que são enviados pelo servidor.
+i18n-enabled=Habilitar internacionalização
+supported-locales=Locais disponíveis
+supported-locales.placeholder=Digite um local e pressione Enter
+default-locale=Local padrão
+realm-cache-clear=Realm Cache
+realm-cache-clear.tooltip=Remove todas as entradas do cache de realm (isto irá remover as entradas para todos os realms)
+user-cache-clear=Cache de usuário
+user-cache-clear.tooltip=Remove todas as entradas do cache de usuário (isto irá remover as entradas de todos os realms)
+revoke-refresh-token=Revogar Token de Atualização
+revoke-refresh-token.tooltip=Se habilitado os tokens de atualização podem ser utilizados somente uma vez. Caso contrário os tokens de atualização não são revogados quando utilizados e podem ser utilizados várias vezes.
+sso-session-idle=Sessão SSO inativa
+sso-session-idle.tooltip=Tempo que uma sessão pode ficar inativa antes de expirar. Tokens e sessões de navegador são invalidados quando uma sessão é expirada.
+seconds=Segundos
+minutes=Minutos
+hours=Horas
+days=Dias
+sso-session-max=Sessão SSO Máxima
+sso-session-max.tooltip=Tempo máximo antes que uma sessão seja expirada. Tokens e sessões de navegador são invalidados quando uma sessão é expirada.
+offline-session-idle=Sessão Offline Inativa
+offline-session-idle.tooltip=Tempo que uma sessão offline pode ficar inativa antes de expirar. Você precisa utilizar um token de atualização offline pelo menos uma vez neste período, caso contrário a sessão offline será expirada.
+access-token-lifespan=Duração do Token de Acesso
+access-token-lifespan.tooltip=Tempo máximo antes que um token de acesso expire. Recomenda-se que este valor seja menor em relação ao tempo de inativação do inativação do SSO.
+access-token-lifespan-for-implicit-flow=Duração do token de acesso para fluxos Implícitos
+access-token-lifespan-for-implicit-flow.tooltip=Tempo máximo antes que um token de acesso emitido durante o Fluxo Implícito do OpenID Connect expire. Recomenda-se que este valor seja menor em relação ao tempo de inativação do SSO. Não há posibilidade de atualizar este token durante o fluxo implícito, sendo este o motivo de existir um tempo limite diferente para a 'Duração do Token de Acesso'.
+client-login-timeout=Tempo limite para login do Cliente
+client-login-timeout.tooltip=Tempo máximo que um cliente tem para finalizar o procolo do token de acesso. Normalmente deve ser 1 minuto.
+login-timeout=Tempo máximo do Login
+login-timeout.tooltip=Tempo máximo que um usuário tempo para completar o login. É recomendado que seja relativamente longo - 30 minutos ou mais.
+login-action-timeout=Tempo limite da ação de Login
+login-action-timeout.tooltip=Tempo máximo que um usuário tem para completar as ações relacionadas ao login como atualizar senhas ou configurar totp. É recomendado que seja relativamente longo - 5 minutos ou mais.
+headers=Cabeçalhos
+brute-force-detection=Detecção de ataque de Força Bruta
+x-frame-options=X-Frame-Options
+x-frame-options-tooltip=O valor padrão impede páginas de serem incluídas via non-origin iframes (clique no label para mais informações)
+content-sec-policy=Content-Security-Policy
+content-sec-policy-tooltip=O valor padrão impede páginas de serem incluídas via non-origin iframes (clique no label para mais informações)
+content-type-options=X-Content-Type-Options
+content-type-options-tooltip=O valor padrão impede Internet Explorer and Google Chrome de realizarem MIME-sniffing em uma resposta diferente do content-type declarado (clique no label para mais informações)
+max-login-failures=Falhas de login
+max-login-failures.tooltip=Quantas falhas de login antes que a espera seja habilitada.
+wait-increment=Incremento de Espera
+wait-increment.tooltip=Quando a quantidade de falhas for alcançada, quanto tempo o usuário deve aguardar antes de tentar novamente?
+quick-login-check-millis=Verificação de Quick Login em Milli Seconds
+quick-login-check-millis.tooltip=Se uma falha ocorre concorrentemente neste período, travar a conta do usuário.
+min-quick-login-wait=Espera mínima após Quick Login
+min-quick-login-wait.tooltip=Quanto tempo aguardar após uma falha de quick login.
+max-wait=Espera máxima
+max-wait.tooltip=Tempo máximo que um usuário deverá aguardar após uma falha de quick login.
+failure-reset-time=Tempo para zerar falhas
+failure-reset-time.tooltip=Quando o contador de falhas será resetado?
+realm-tab-login=Login
+realm-tab-keys=Chaves
+realm-tab-email=E-mail
+realm-tab-themes=Temas
+realm-tab-cache=Cache
+realm-tab-tokens=Tokens
+realm-tab-client-initial-access=Tokens de Acesso inicial
+realm-tab-security-defenses=Defesas
+realm-tab-general=Geral
+add-realm=Adicionar realm
+
+#Session settings
+realm-sessions=Sessões do Realm
+revocation=Revogação
+logout-all=Deslogar todos
+active-sessions=Sessões Ativas
+sessions=Sessões
+not-before=Não antes de
+not-before.tooltip=Revogar qualquer token emitido antes desta data.
+set-to-now=Definir como agora
+push=Enviar
+push.tooltip=Para cada cliente que possui uma URL de administrador, notificá-los da nova política de revogação.
+
+#Protocol Mapper
+usermodel.prop.label=Propriedade
+usermodel.attr.label=Atributo do usuário
+userSession.modelNote.label=Nota da sessão de usuário
+multivalued.label=Múltiplos valores
+selectRole.label=Selecione o Role
+tokenClaimName.label=Nome do Token Claim
+jsonType.label=Tipo JSON do Claim
+includeInIdToken.label=Adicionar ao token de ID
+includeInAccessToken.label=Adicionar ao token de acesso
+includeInUserInfo.label=Adicionar à informação do usuário
+usermodel.clientRoleMapping.clientId.label=ID do cliente
+usermodel.clientRoleMapping.rolePrefix.label=Prefixo para o role de Cliente
+usermodel.realmRoleMapping.rolePrefix.label=Prefixo do Realm Role
+
+# client details
+search.placeholder=Pesquisar...
+create=Criar
+import=Importar
+client-id=ID do cliente
+base-url=URL Base
+actions=Ações
+not-defined=Não definido
+edit=Editar
+delete=Excluir
+no-results=Sem resultados
+no-clients-available=Nenhum cliente disponível
+add-client=Adicionar cliente
+select-file=Selecionar arquivo
+view-details=Ver detalhes
+clear-import=Cancelar importação
+client-id.tooltip=Especifica o ID referenciado em URI e tokens. Por exemplo 'meu-cliente'. Para SAML também representa o valor do emissor esperado dos authn requests
+client.name.tooltip=Especifica o nome de exibição do cliente. Por exemplo 'Meu Cliente'. Também aceita chaves para valores localizados. Por exemplo: ${meu_cliente}
+client.description.tooltip=Especifica a descrição do cliente. Por exemplo 'Meu cliente para TimeSheets'. Também aceita chaves para valores localizados. Por exemplo: ${meu_cliente_descricao}
+client.enabled.tooltip=Clientes desabilitados não podem realizar login ou obter tokens de acesso.
+consent-required=Consentimento exigido
+consent-required.tooltip=Se habilitado os usuários devem consentir com o acesso ao cliente.
+client-protocol=Protocolo cliente
+client-protocol.tooltip='OpenID connect' permite aos Clientes verificarem a identidade do usuário final baseado na autenticação realizada por um servidor de Autorização. 'SAML' permite cenários de autenticação e autorização web-based incluindo cross-domain single sign-on (SSO) e utiliza tokens de segurança contendo assertions para trafegar informações.
+access-type=Tipo de acesso
+access-type.tooltip=Clientes 'Confidential' requerem um secret para iniciar o protocolo de login. Clientes 'Public' não necessitam de secret. Clientes 'Bearer-only' são web services que nunca iniciam um login.
+standard-flow-enabled=Fluxo padrão habilitado
+standard-flow-enabled.tooltip=Isto habilita a autenticação baseada em redirecionamento com código de autorização padrão do OpenID Connect. Em termos de especificações OpenID Connect ou OAuth2, isto habilita suporte ao 'Fluxo de Código de Autorização' para este cliente.
+implicit-flow-enabled=Fluxo implícito habilitado
+implicit-flow-enabled.tooltip=Isto habilita suporte a autenticação baseada em redirecionamento sem código de autorização. Em tempos de especificações OpenID Connect ou OAuth2, isto habilita suporte do 'Fluxo Implícito' para este cliente.
+direct-access-grants-enabled=Grants de Acesso direto habilitado
+service-accounts-enabled=Contas de serviço habilitadas
+include-authnstatement=Incluir AuthnStatement
+sign-documents=Assinar documentos
+sign-assertions=Assinar assertions
+signature-algorithm=Algoritmo de assinatura
+canonicalization-method=Método de Canonicalization 
+encrypt-assertions=Encriptar Assertions
+client-signature-required=Assinatura do cliente requerida
+force-post-binding=Forçar Binding via POST
+front-channel-logout=Front Channel Logout
+force-name-id-format=Forçar formato do NameID
+name-id-format=Formato do NameID
+valid-redirect-uris=URIs de redirecionamento válidas
+admin-url=URL do administrador
+master-saml-processing-url=URL de processamento SAML principal
+idp-sso-url-ref=Nome de URL para  SSO iniciado via IDP
+idp-sso-relay-state=Estado de relay para SSO iniciado via IDP
+fine-saml-endpoint-conf=Configuração de endpoint para configuração fina do SAML 
+assertion-consumer-post-binding-url=URL para conexão post para o serviço consumidor de Assertions
+assertion-consumer-redirect-binding-url=URL para conexão de redirecionamento do serviço consumidor de Assertions
+logout-service-post-binding-url=URL de conexão POST para o serviço de logout
+logout-service-post-binding-url.tooltip=URL de conexão POST para o serviço de logout
+logout-service-redir-binding-url=URL de conexão para o redirecionamento do serviço de logout
+
+# client import
+import-client=Importar cliente
+format-option=Formato
+import-file=Importar arquivo
+
+# client tabs
+settings=Configurações
+credentials=Credenciais
+saml-keys=Chaves SAML
+roles=Roles
+mappers=Mapeamentos
+scope=Escopo
+offline-access=Acesso offline
+installation=Instalação
+service-account-roles=Roles de contas de serviço
+
+# client credentials
+client-authenticator=Autenticador do cliente
+no-client-certificate-configured=Nenhum certificado cliente configurado
+gen-new-keys-and-cert=Gerar novas chaves e certificados
+import-certificate=Importar certificado
+gen-client-private-key=Gerar chave privada do cliente
+generate-private-key=Gerar chave privada
+archive-format=Formato do arquivo
+key-alias=Alias da chave
+key-password=Senha da chave
+store-password=Salvar senha
+generate-and-download=Gerar e fazer download
+client-certificate-import=Importar certificado do cliente
+import-client-certificate=Importar certificado do cliente
+secret=Segredo
+regenerate-secret=Recriar segredo
+registrationAccessToken=Token de acesso para registro
+registrationAccessToken.regenerate=Regerar token de acesso para registro
+add-role=Adicionar Role
+role-name=Nome do Role
+composite=Composto
+description=Descrição
+no-client-roles-available=Nenhum role de cliente disponível
+scope-param-required=Parâmetro de escopo requerido
+composite-roles=Roles compostos
+realm-roles=Roles do Realm
+available-roles=Roles disponíveis
+add-selected=Adicionar selecionados
+associated-roles=Roles associados
+remove-selected=Remover selecionados
+client-roles=Roles de clientes
+select-client-to-view-roles=Selecione o cliente para ver os roles do cliente
+add-builtin=Adicionar Builtin
+category=Categoria
+type=Tipo
+no-mappers-available=Nenhum mapeamento disponível
+add-builtin-protocol-mappers=Adicionar mapeamentos de protocolo Builtin
+add-builtin-protocol-mapper=Adicionar mapeamentos de protocolo Builtin
+
+scope-mappings=Mapeamentos do Escopo
+full-scope-allowed=Permitir Escopo completo
+assigned-roles=Roles associados
+effective-roles=Roles efetivos
+basic-configuration=Configuração básica
+node-reregistration-timeout=Tempo limite para re-registro de nó
+registered-cluster-nodes=Nós de cluster registrados
+register-node-manually=Registrar nó manualmente
+test-cluster-availability=Testar disponibilidade do cluster
+last-registration=Último registro
+node-host=Host
+no-registered-cluster-nodes=Nenhum nó registrado disponível
+cluster-nodes=Nós do cluster
+add-node=Adicionar nó
+show-sessions=Exibir sessões
+user=Usuário
+from-ip=Do IP
+session-start=Início da sessão
+first-page=Primeira página
+previous-page=Página anterior
+next-page=Próxima página
+select-a-format=Selecione um formato
+download=Download
+offline-tokens=Tokens offline
+show-offline-tokens=Exibir tokens offline
+token-issued=Token emitido
+last-access=Último acesso
+last-refresh=Último refresh
+key-export=Exportar chave
+key-import=Importar chave
+export-saml-key=Exportar chave SAML
+import-saml-key=Importar chave SAML
+realm-certificate-alias=Alias do certificado do Realm
+signing-key=Chave de assinatura
+saml-signing-key=Chave de assinatura SAML
+private-key=Chave privada
+generate-new-keys=Gerar novas chaves
+export=Exportar
+encryption-key=Chave de encriptação
+service-accounts=Contas de serviço
+service-account-is-not-enabled-for=Contas de serviço não estão habilitadas para {{client}}
+create-protocol-mappers=Criar mapeamentos de protocolo
+create-protocol-mapper=Criar mapeamento de protocolo
+protocol=Protocolo
+protocol.tooltip=Protocolo...
+id=ID
+mapper.name.tooltip=Nome do mapeamento
+consent-text=Texto para consentimento
+mapper-type=Tipo de mapeamento
+# realm identity providers
+identity-providers=Provedores de identificação
+table-of-identity-providers=Tabela de provedores de identidade
+add-provider.placeholder=Adicionar provedor...
+provider=Provedor
+first-broker-login-flow=Fluxo do primeiro login
+post-broker-login-flow=Fluxo pós login
+redirect-uri=URI de redirecionamento
+alias=Alias
+authenticate-by-default=Autenticar por padrão
+store-tokens=Salvar Tokens
+stored-tokens-readable=Leitura de tokens salvos
+trust-email=Confiar no e-mail recebido
+gui-order=Ordem na tela
+gui-order.tooltip=Número definindo a ordem do provedor na GUI (ex na página de Login).
+openid-connect-config=Configuração OpenID Connect
+authorization-url=URL de autorização
+token-url=URL do Token
+logout-url=URL de logout
+backchannel-logout=Backchannel Logout
+user-info-url=URL de informações do usuário
+client-secret=Secret do Cliente
+show-secret=Exibir secret
+hide-secret=Esconder secret
+issuer=Emissor
+default-scopes=Escopos padrão
+prompt=Prompt
+unspecified.option=Não especificado
+none.option=Nenhum
+consent.option=Consentimento
+login.option=Login
+select-account.option=select_account
+validate-signatures=Validar assinaturas
+validating-public-key=Chave pública para validação
+import-external-idp-config=Importar configuração de IDP externo
+import-from-url=Importar de URL
+import-from-file=Importar de arquivo
+saml-config=Configuração SAML
+single-signon-service-url=URL de serviço do Single Sign On
+single-logout-service-url=URL de serviço de Single Logout
+nameid-policy-format=Política de formato NameID
+http-post-binding-response=Responder com HTTP-POST
+http-post-binding-for-authn-request=Utilizar HTTP-POST binding para AuthnRequest
+want-authn-requests-signed=Esperar AuthnRequests assinados
+force-authentication=Forçar autenticação
+validate-signature=Validar assinatura
+validating-x509-certificate=Validar certificados X509
+key=Chave
+
+# User federation
+sync-ldap-roles-to-keycloak=Sincronizar os roles do LDAP para o Keycloak
+sync-keycloak-roles-to-ldap=Sincronizar os roles do Keycloak para o LDAP
+sync-ldap-groups-to-keycloak=Sincronizar os grupos do LDAP para o Keycloak
+sync-keycloak-groups-to-ldap=Sincronizar os grupos do Keycloak para o LDAP
+
+realms=Realms
+realm=Realm
+
+identity-provider-mappers=Mapeamentos de provedores de identificação
+create-identity-provider-mapper=Criar mapeamento de provedores de identificação
+add-identity-provider-mapper=Adicionar mapeamento de provedor de identificação
+
+expires=Expira em
+expiration=Duração
+expiration.tooltip=Especifica por quanto tempo o token deve ser válido
+count=Quantidade
+count.tooltip=Especifica quantos clientes podem ser criados usando o token
+remainingCount=Quantidade restante
+created=Criado em
+back=Voltar
+initial-access-tokens=Tokens de acesso inicial
+add-initial-access-tokens=Adicionar token de acesso inicial
+initial-access-token=Token de acesso inicial
+initial-access.copyPaste.tooltip=Copie/cole o token de acesso inicial antes de sair desta página pois não é possível recuperá-lo depois
+continue=Continuar
+initial-access-token.confirm.title=Copiar o token de acesso inicial
+initial-access-token.confirm.text=Por favor copie e cole o token de acesso inicial antes de confirmar pois não é possível recuperá-lo depois
+
+client-templates=Modelos de cliente
+
+groups=Grupos
+
+default-roles=Roles padrão
+no-realm-roles-available=Nenhum role de realm disponível
+
+users=Usuários
+realm-default-roles=Roles padrão do Realm
+client-default-roles=Roles padrão do Cliente
+partial-import=Importação parcial
+
+file=Arquivo
+exported-json-file=Arquivo json exportado
+import-from-realm=Importar de realm
+import-users=Importar usuários
+import-groups=Importar grupos
+import-clients=Importar clientes
+import-identity-providers=Importar provedores de identificação
+import-realm-roles=Importar roles do realm
+import-client-roles=Importar roles de cliente
+if-resource-exists=Se um recurso já existir
+fail=Falhar
+skip=Pular
+overwrite=Sobrescrever
+
+action=Ações
+role-selector=Seletor de roles
+
+select-a-role=Selecione um role
+select-realm-role=Selecione um role de realm
+select-client-role=Selecione um role de cliente
+
+client-template=Modelos de Cliente
+client-saml-endpoint=Cliente SAML Endpoint
+add-client-template=Adicionar modelo de cliente
+
+manage=Administração
+authentication=Autenticação
+user-federation=Federação de usuários
+events=Eventos
+realm-settings=Configurações do Realm
+configure=Configuração
+select-realm=Selecione um realm
+add=Adicionar
+
+
+add-user-federation-provider=Adicionar provedor de federação de usuários
+required-settings=Configurações obrigatórias
+provider-id=ID do provedor
+console-display-name=Nome de exibição no console
+priority=Prioridade
+sync-settings=Configurações de sincronização
+periodic-full-sync=Syncronização completa periódica
+full-sync-period=Período
+periodic-changed-users-sync=Sincronização periódica de usuários alterados
+changed-users-sync-period=Período
+synchronize-changed-users=Sincronizar usuários alterados
+synchronize-all-users=Sincronizar todos os usuários
+kerberos-realm=Realm do Kerberos
+server-principal=Principal do servidor
+keytab=KeyTab
+debug=Debug
+allow-password-authentication=Permitir autenticação via senha
+edit-mode=Modo de edição
+update-profile-first-login=Atualizar Profile no primeiro login
+sync-registrations=Sincronizar contas
+vendor=Vendor
+username-ldap-attribute=Atributo LDAP para Username
+ldap-attribute-name-for-username=Atributo LDAP para Username
+rdn-ldap-attribute=Atributo LDAP para RDN
+ldap-attribute-name-for-user-rdn=Atributo LDAP para RDN
+uuid-ldap-attribute=Atributo LDAP para UUID
+ldap-attribute-name-for-uuid=Atributo LDAP para UUID
+user-object-classes=Classes do objeto User
+
+ldap-connection-url=URL de conexão ao LDAP
+ldap-users-dn=DN dos usuários no LDAP
+ldap-bind-dn=DN para bind no LDAP
+ldap-bind-credentials=Credenciais para conectar ao LDAP
+ldap-filter=Filtro do LDAP
+
+connection-url=URL de conexão
+test-connection=Testar conexão
+users-dn=Users DN
+authentication-type=Tipo de autenticação
+bind-dn=Bind DN
+bind-credential=Senha para conexão
+test-authentication=Testar autenticação
+custom-user-ldap-filter=Filtro de usuários LDAP customizado
+search-scope=Escopo de pesquisa
+use-truststore-spi=Utilizar Truststore SPI
+connection-pooling=Pooling de conexões
+kerberos-integration=Integração com Kerberos
+allow-kerberos-authentication=Permitir autenticação Kerberos
+use-kerberos-for-password-authentication=Utilizar Kerberos para autenticação via senha
+batch-size=Tamanho do lote
+user-federation-mappers=Mapeamentos de federação de usuário
+create-user-federation-mapper=Criar mapeamento de federação de usuário
+add-user-federation-mapper=Adicionar mapeamento de federação de usuário
+provider-name=Nome do provedor
+no-user-federation-providers-configured=Nenhum federação de usuários configurada.
+add-identity-provider=Adicionar provedor de identificação
+add-identity-provider-link=adicionar link para provedor de identificação
+identity-provider=Provedor de identificação
+identity-provider-user-id=ID de usuário do provedor de identificação
+identity-provider-username=Nome de usuário do provedor de identificação
+pagination=Paginação
+
+browser-flow=Fluxo de browser
+registration-flow=Fluxo de registro
+direct-grant-flow=Fluxo de Direct Grant
+reset-credentials=Reiniciar credenciais
+client-authentication=Autenticação do cliente
+new=Novo
+copy=Copiar
+add-execution=Adicionar execução
+add-flow=Adicionar fluxo
+auth-type=Tipo
+requirement=Condição
+config=Configuração
+no-executions-available=Nenhuma execução disponível
+authentication-flows=Fluxos de autenticação
+create-authenticator-config=Criar configuração de autenticação
+otp-type=Tipo OTP
+time-based=Baseado em tempo
+counter-based=Baseado em contador
+otp-hash-algorithm=Algoritmo de hash OTP
+number-of-digits=Quantidade de dígitos
+look-ahead-window=Look Ahead Window
+initial-counter=Contador inicial
+otp-token-period=Período de token OTP 
+table-of-password-policies=Tabela de política de senhas
+add-policy.placeholder=Adicionar política...
+policy-type=Tipo da política
+policy-value=Valor da política
+admin-events=Eventos de adminstração
+login-events=Eventos de login
+filter=Filtro
+update=Atualizar
+reset=Reiniciar
+operation-types=Tipos de operações
+select-operations.placeholder=Selecionar operações...
+resource-path=Path do recurso
+date-(from)=Data (De)
+date-(to)=Data (Até)
+authentication-details=Detalhes para autenticação
+ip-address=Endereço IP
+time=Tempo
+operation-type=Tipo de operação
+auth=Autenticação
+representation=Representação
+register=Registro
+required-action=Ação requerida
+default-action=Ação padrão
+no-required-actions-configured=Nenhuma ação requerida configurada
+defaults-to-id=ID é o padrão
+flows=Fluxos
+bindings=Ligações
+required-actions=Ações requeridas
+password-policy=Política de senha
+otp-policy=Política OTP
+user-groups=Grupos de usuário
+default-groups=Grupos Padrão
+cut=Recortar
+paste=Colar
+
+create-group=Criar grupo
+create-authenticator-execution=Criar execução de autenticação
+create-form-action-execution=Criar execução de ação de formulário
+create-top-level-form=Criar formulário de nível superior
+top-level-flow-type=Tipo do fluxo de nível superior
+flow.generic=genérico
+flow.client=cliente
+create-execution-flow=Criar fluxo de execução
+flow-type=Flow Type
+flow.form.type=formulário
+flow.generic.type=genérico
+form-provider=Provedor de formulário
+select-a-type.placeholder=selecione um tipo
+available-groups=Grupos disponíveis
+value=Valor
+table-of-group-members=Tabela de membros do grupo
+last-name=Sobrenome
+first-name=Primeiro nome
+email=E-mail
+toggle-navigation=Alternar navegação
+manage-account=Administrar a conta
+sign-out=Sign Out
+server-info=Informação do servidor
+resource-not-found=Recurso <strong>não encontrado</strong>...
+resource-not-found.instruction=Não foi possível encontrar o recurso solicitado. Por favor verifique se a URL solicitada está correta.
+go-to-the-home-page=Ir para a página inicial &raquo;
+page-not-found=Página <strong>não encontrada</strong>...
+page-not-found.instruction=Não foi possível encontrar a página solicitada. Por favor verifique se a URL solicitada está correta.
+select-event-types.placeholder=Selecione os tipos de eventos...
+select-an-action.placeholder=Selecione uma ação...
+admin-events-settings=Configuração de eventos de administração
+save-events=Salvar eventos
+include-representation=Incluir representação
+server-version=Versão do servidor
+info=Informações
+providers=Provedores
+server-time=Hora do servidor
+server-uptime=Uptime do servidor
+memory=Memória
+total-memory=Memória total
+free-memory=Memória livre
+used-memory=Memória utilizada
+system=Sistema
+current-working-directory=Diretório de trabalho atual
+java-version=Versão do Java
+java-vendor=Java Vendor
+java-runtime=Java Runtime
+java-vm=Java VM
+java-vm-version=Versão da Java VM
+java-home=Java Home
+user-name=Usuário
+user-timezone=Zona horária do usuário
+user-locale=Locale do usuário
+system-encoding=Enconding do sistema
+operating-system=Sistema operacional
+os-architecture=Arquitetura do OS
+spi=SPI
+granted-roles=Roles concedidos
+granted-protocol-mappers=Protocol Mappers concedidos
+additional-grants=Concessões adicionais
+revoke=Revogar
+new-password=Nova senha
+password-confirmation=Confirmação de senha
+reset-password=Reiniciar senha
+remove-totp=Remover TOTP
+reset-actions=Ações para reiniciar
+reset-actions-email=Ações para reiniciar e-mail
+send-email=Enviar e-mail
+add-user=Adicionar usuário
+created-at=Criado em
+user-enabled=Usuário ativo
+user-temporarily-locked=Usuário temporariamente desativado
+unlock-user=Liberar usuário
+federation-link=Link para federação
+email-verified=E-mail verificado
+required-user-actions=Ações necessárias do usuário
+locale=Locale
+select-one.placeholder=Selecione um...
+impersonate=Personificar
+impersonate-user=Personificar usuário
+identity-provider-alias=Alias do Provedor de Identificação
+provider-user-id=Provider User ID
+provider-username=Provider Username
+no-identity-provider-links-available=Nenhum link para provedor de identificação disponível
+group-membership=Grupos associados
+leave=Sair
+table-of-realm-users=Tabela de usuários do Realm
+view-all-users=Exibir todos os usuários
+unlock-users=Liberar usuários
+no-users-available=Nenhum usuário disponível
+users.instruction=Por favor faça uma pesquisa, ou clique em Exibir todos os usuários
+consents=Consentimentos
+started=Iniciado
+logout-all-sessions=Logout todas as sessões
+logout=Logout
+new-name=Novo nome
+ok=Ok
+attributes=Atributos
+role-mappings=Mapeamento de roles
+members=Membros
+details=Detalhes
+identity-provider-links=Links de provedores de identificação.
+register-required-action=Registrar ação necessária
+gender=Gênero
+address=Endereço
+phone=Telefone
+profile-url=URL do perfil
+picture-url=URL da foto
+website=Website
+import-keys-and-cert=Importar chave e certificado
+upload-keys=Carregar chaves
+download-keys-and-cert=Download chave e certificado
+no-value-assigned.placeholder=Nenhum valor associado
+remove=Remover
+no-group-members=Nenhum membro
+temporary=Temporária
+join=Participar
+event-type=Tipo de evento
+events-config=Configurar eventos
+event-listeners=Listeners de eventos
+login-events-settings=Configuração de eventos de login
+clear-events=Limpar eventos
+saved-types=Tipos salvos
+clear-admin-events=Limpar eventos administrativos
+clear-changes=Cancelar mudanças
+error=Erro
+
+# Authz
+# Authz Common
+authz-authorization=Autorização
+authz-owner=Proprietário
+authz-uri=URI
+authz-scopes=Escopos
+authz-resource=Recurso
+authz-resource-type=Tipo de recurso
+authz-resources=Recursos
+authz-scope=Escopo
+authz-authz-scopes=Autorização de escopos
+authz-policies=Políticas
+authz-permissions=Permissões
+authz-evaluate=Avaliar
+authz-icon-uri=URI do ícone
+authz-select-scope=Selecione um escopo
+authz-select-resource=Selecione um recurso
+authz-associated-policies=Políticas associadas
+authz-any-resource=Qualquer recurso
+authz-any-scope=Qualquer escopo
+authz-any-role=Qualquer role
+authz-policy-evaluation=Avaliação da política
+authz-select-client=Selecione um cliente
+authz-select-user=Selecione um usuário
+authz-entitlements=Direitos
+authz-no-resources=Nenhum recurso
+authz-result=Resultado
+authz-authorization-services-enabled=Autorização habilitada
+authz-required=Obrigatório
+
+# Authz Settings
+
+authz-policy-enforcement-mode=Modo de execução da política
+authz-policy-enforcement-mode-enforcing=Restritiva
+authz-policy-enforcement-mode-permissive=Permissiva
+authz-policy-enforcement-mode-disabled=Desabilitada
+
+authz-remote-resource-management=Administração remota de recursos
+
+authz-export-settings=Exportar configurações
+
+# Authz Resource List
+authz-no-resources-available=Nenhum recurso disponível.
+authz-no-scopes-assigned=Nenhum escopo associado.
+authz-no-type-defined=Nenhum tipo definido.
+authz-no-permission-assigned=Nenhuma permissão associada.
+authz-no-policy-assigned=Nenhuma política associada.
+authz-create-permission=Criar permissão
+
+# Authz Resource Detail
+authz-add-resource=Adicionar recurso
+
+# Authz Scope List
+authz-add-scope=Adicionar escopo
+authz-no-scopes-available=Nenhum escopo disponível.
+
+# Authz Scope Detail
+
+# Authz Policy List
+authz-all-types=Todos os tipos
+authz-create-policy=Criar política
+authz-no-policies-available=Nenhuma política disponível
+
+# Authz Policy Detail
+authz-policy-logic=Lógica
+authz-policy-logic-positive=Positiva
+authz-policy-logic-negative=Negativa
+authz-policy-apply-policy=Aplicar política
+authz-policy-decision-strategy=Estratégia de decisão
+authz-policy-decision-strategy-affirmative=Afirmativa
+authz-policy-decision-strategy-unanimous=Unânime
+authz-policy-decision-strategy-consensus=Consensual
+authz-select-a-policy=Selecionar uma política
+
+# Authz Role Policy Detail
+authz-add-role-policy=Adicionar política de Role
+authz-no-roles-assigned=Nenhum role associado
+
+# Authz User Policy Detail
+authz-add-user-policy=Adicionar política de usuário
+authz-no-users-assigned=Nenhum usuário associado
+
+# Authz Time Policy Detail
+authz-add-time-policy=Adicionar política de tempo
+authz-policy-time-not-on-after=Não em ou depois
+
+# Authz Drools Policy Detail
+authz-add-drools-policy=Adicionar política Drools
+authz-policy-drools-maven-artifact-resolve=Resolver
+authz-policy-drools-maven-artifact=Artefato maven de política
+authz-policy-drools-module=Módulo
+authz-policy-drools-session=Sessão
+authz-policy-drools-update-period=Atualizar período
+
+# Authz JS Policy Detail
+authz-add-js-policy=Adicionar política Javascript
+authz-policy-js-code=Código
+
+
+# Authz Aggregated Policy Detail
+authz-aggregated=Agregado
+authz-add-aggregated-policy=Adicionar política agregada
+
+# Authz Permission List
+authz-no-permissions-available=Nenhuma permissão disponível
+
+# Authz Permission Detail
+
+# Authz Resource Permission Detail
+authz-add-resource-permission=Adicionar permissão para recurso
+authz-permission-resource-apply-to-resource-type=Aplicar ao tipo de recurso
+
+# Authz Scope Permission Detail
+authz-add-scope-permission=Adicionar permissão de escopo
+
+# Authz Evaluation
+authz-evaluation-identity-information=Informação de identidade
+authz-evaluation-new=Nova avaliação
+authz-evaluation-re-evaluate=Re-avaliar
+authz-evaluation-previous=Avaliação anterior
+authz-evaluation-contextual-info=Informação contextual
+authz-evaluation-contextual-attributes=Atributos contextuais
+authz-evaluation-evaluate=Avaliar
+authz-evaluation-any-resource-with-scopes=Qualquer recurso com escopo(s)
+authz-evaluation-no-result=Não foi possível obter nenhum resultado para o pedido de autorização provida. Verifique os recurso(s) ou escopo(s) providos estão associados com alguma política.
+authz-evaluation-no-policies-resource=Nenhma política foi encontrada para este recurso.
+authz-evaluation-authorization-data=Resposta
+authz-show-authorization-data=Exibir dados da autorização
+
+usermodel.prop.tooltip=Nome do método da propriedade na interface UserModel. Por exemplo, o valor 'email' iria referenciar o método UserModel.getEmail() .
+usermodel.attr.tooltip=Nome do atributo do usuário que é uma chave de atributo no mapa UserModel.attribute.
+userSession.modelNote.tooltip=Nome da nota de sessão do usuário salva no mapa UserSessionModel.note.
+multivalued.tooltip=Indica se um atributo suporta múltiplos valores. Se verdadeiro, então a lista de todos os valores desse atributo será definida como o claim. Se falso, então apenas o primeiro valor será utilizado.
+selectRole.tooltip=Entre com o role na caixa à esquerda, ou clique neste botão para navegar e selecionar o role desejado.
+tokenClaimName.tooltip=Nome do claim para inserir no token. Pode ser um nome completo (fully qualified) como 'address.street'. Neste caso, um objeto json aninhado será criado.
+jsonType.tooltip=Tipo JSON que deve ser utilizado para popular o claim json no token. Os valores válidos são Long, int boolean e String.
+includeInIdToken.tooltip=O claim deve ser adicionado ao token de ID?
+includeInAccessToken.tooltip=O claim deve ser adicionado ao token de acesso?
+includeInUserInfo.tooltip=O claim deve ser adicionado à informação do usuário?
+usermodel.clientRoleMapping.clientId.tooltip=ID do cliente para mapeamentos de roles
+usermodel.clientRoleMapping.rolePrefix.tooltip=Um prefixo para cada role do cliente (opcional)
+usermodel.realmRoleMapping.rolePrefix.tooltip=Um prefixo para cada Realm Role (opcional).
+clients.tooltip=Os clientes são aplicativos de browser e serviços web confiáveis em um realm. Esses clientes podem solicitar login. Você também pode definir roles específicos do cliente.
+authz-policy-role-clients.tooltip= Selecione um cliente a fim de filtrar os roles de cliente que podem ser aplicados a esta política.
+direct-access-grants-enabled.tooltip=Habilita o suporte para concessões de acesso direto (Direct Access Grants), o que significa que o cliente tem acesso ao nome de usuário/senha e negocia diretamente com o servidor Keycloak pelo token de acesso. Em termos de especificações OAuth2, habilita suporte de "Resource Owner Password Credentials Grant" para este cliente.
+service-accounts-enabled.tooltip=Permite autenticar este cliente no Keycloak e recuperar tokens de acesso dedicados para este cliente. Em termos da especificações OAuth2, habilita suporte para 'Client Credentials Grants' para este cliente.
+include-authnstatement.tooltip=Deve ser adicionado um statement especificando o método e timestamp nas respostas de login?
+sign-documents.tooltip=Devem os documentos SAML serem assinados pelo realm?
+sign-assertions.tooltip=Devem as asserções dentro dos documentos SAML serem assinadas? Esta configuração não é necessária se o documento já está sendo assinado.
+signature-algorithm.tooltip=O algoritmo de assinatura a ser utilizado para assinar documentos.
+canonicalization-method.tooltip=Canonicalization Method para assinaturas XML.
+encrypt-assertions.tooltip=Devem as asserções SAML serem encriptadas com a chave pública do cliente usando AES?
+client-signature-required.tooltip=O cliente irá assinar os pedidos e respostas saml? E eles devem ser validados?
+force-post-binding.tooltip=Sempre utilizar POST para respostas.
+front-channel-logout.tooltip=Quando marcado, o logout requer um redirecionamento do browser para o cliente. Caso contrário o servidor executo uma invocação em background para o logout.
+force-name-id-format.tooltip=Ignora o NameID de assunto solicitado e utiliza o configurado no console de administração.
+name-id-format.tooltip=O formato de Name ID para utilizar como assunto.
+root-url.tooltip=URL raiz adicionada à URLs relativas
+valid-redirect-uris.tooltip=Padrão de URI válido para onde um navegador pode redirecionar depois de um login bem-sucedido ou sair. Wildcards simples são permitidos, por exemplo 'http://example.com/*'. Caminhos relativos podem ser especificados também, ex: /my/relative/path/*. Caminhos relativos são relativos à URL raiz do cliente, ou se nenhum for especificado a URL raiz do servidor é usado. Para SAML, é necessário definir padrões de URI válidos se você está contando com a URL do serviço consumidor incorporada com a solicitação de login.
+base-url.tooltip=URL padrão para utilizar quando o servidor de autenticação necessita redirecionar ou linkar para o cliente.
+admin-url.tooltip=URL para a inteface administrativa do cliente. Defina este valor se o cliente suporta a API do adaptador REST. Esta API rest permite que o servidor de autenticação envie políticas de revogação e outras tarefas administrativas. Geralmente este valor é definido apontando para a URL base do cliente.
+master-saml-processing-url.tooltip=Se configurado, esta URL será utilizada para todos os bindings do "SP's Assertion Consumer" e "Single Logout Services". Ela pode ser sobreescriva idnvidualmente para cada ligação e serviço na Configuração Detalhada do Endpoint SAML.
+idp-sso-url-ref.tooltip=Nome do fragmento URL para referenciar o cliente quando você deseja um SSO iniciado por IDP. Deixar este campo vazio irá desabilitar SSO iniciado por IDP. A URL que você irá referenciar do seu browser será: {server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}
+idp-sso-relay-state.tooltip=O estado de Relay que você deseja enviar com um pedido SAML quando você deseja realizar SSO iniciado por IDP.
+web-origins.tooltip=Permitir origens CORS. Para permitir todas as URIs de redirecionamento de origem válidas adicionar '+'. Para permitir todas as origens adicionar '*'.
+fine-saml-endpoint-conf.tooltip=Expanda esta sessão para configurar URLs específics para 'Assertion Consumer' e 'Single Logout Service'.
+assertion-consumer-post-binding-url.tooltip=URL de ligação SAML via post para as asserções de consumidor de serviços do cliente (respostas de login). Você pode deixar este campo em branco se você não tiver uma URL para esta ligação.
+assertion-consumer-redirect-binding-url.tooltip=URL de ligação SAML de redirecionamento para as asserções de consumidor de serviços do cliente (respostas de login). Você pode deixar este campo em branco se você não tiver uma URL para esta ligação.
+logout-service-binding-post-url.tooltip=URL de ligação SAML via post para o serviço de logout único do cliente. Voce pode deixar este campo em branco se estiver usando uma ligação diferente.
+logout-service-redir-binding-url.tooltip=URL de ligação SAML de redirecionamento  para o serviço de logout único do cliente. Voce pode deixar este campo em branco s e estiver usando uma ligação diferente.
+mappers.tooltip=Mapeamentos de protocolo executam transformações em tokens e documentos. Eles podem realizar coisas como mapear dados de usuários para claims de protocolo, ou apenas transformar qualquer solicitação entre o cliente e o servidor de autenticação.
+scope.tooltip=Escopos de mapeamento permitem que você restrinja quais mapeamentos de roles de usuário são inclusos nos tokens de acesso solicitado pelo cliente.
+ldap.search-scope.tooltip=Para um nível nós pesquisamos somente os usuários nos DNs especificados pelo campo User DNs. Para subtree, nós pesquisamos na sub-árvore completa. Verifique a documentação do LDAP para mais detalhes.
+authz-permission-scope-scope.tooltip=Define que esta permissões deve ser aplicada para um ou mais escopos.
+sessions.tooltip=Exibir as sessões ativas para este cliente. Permite que você veja quais usuários estão ativos e quando eles logaram.
+active-sessions.tooltip=Total de sessões de usuário ativas para este cliente.
+show-sessions.tooltip=Atenção, esta é uma operação potencialmente cara dependendo do número de sessões ativas.
+offline-access.tooltip=Exibe as sessões offline para este cliente. Permite que você veja quantos usuários obtém tokens offline e quando eles os obtiveram. PAra revogar todos os tokens do cliente, vá para a aba Revogações e defina o valor do campo 'não antes de' para 'agora'.
+installation.tooltip=Ferramenta de auxílio para gerar vários formatos de adaptadores de cliente que você poderá fazer download depois ou copiar e colar para configurar seus cliente.
+service-account-roles.tooltip=Permite que você autentique mapeamentos de roles para as contas de serviço dedicadas à este cliente.
+client-authenticator.tooltip=Autenticador de Cliente usado para autenticar este cliente ao servidor Keycloak
+certificate.tooltip=Certificado do cliente para validar JWT emitidos pelo cliente e assinados pela chave privada do cliente da sua keystore.
+validating-x509-certificate.tooltip=O certificado em formato PEM que deve ser usado para verificar assinaturas.
+archive-format.tooltip=Keystore Java ou arquivo em formato PKCS12.
+key-alias.tooltip=Alias do arquivo para sua chave privada e certificado.
+key-password.tooltip=Senha para acessar a chave privada no certificado.
+store-password.tooltip=Senha para acessar o arquivo em si.
+jwt-import.key-alias.tooltip=Alias do arquivo para o seu certificado.
+registrationAccessToken.tooltip=O token de acesso para registro provê acesso aos cliente para o serviço de registro cliente.
+scope-param-required.tooltip=Este role somente será concedido se os parâmetros de escopo com os nomes dos roles forem utilizados durante a autorização/solicitação de token.
+composite-roles.tooltip=Quando este role é associado/removido de um usuário, qualquer role associado com ele também será adicionado/removido implicitamente.
+composite.associated-realm-roles.tooltip=Roles de nível de realm associados com este role composto.
+composite.available-realm-roles.tooltip=Roles de nível de realm disponíveis para este role composto.
+available-roles.tooltip=Roles para este cliente que você pode associar a este role composto.
+scope.available-roles.tooltip=Roles do Realm que podem ser associados a este escopo.
+service-account.available-roles.tooltip=Roles do Realm que podem ser associados a contas de serviço.
+client.associated-roles.tooltip=Roles do Cliente associados a este role composto.
+full-scope-allowed.tooltip=Permite a você desabilitar todas as restrições.
+assigned-roles.tooltip=Roles do Realm associados ao escopo.
+service-account.assigned-roles.tooltip=Roles do Realm associados a conta de serviço.
+group.assigned-roles.tooltip=Roles do Realm mapeados ao grupo.
+realm.effective-roles.tooltip=Roles do Realm associados que podem ter sido herdados de um role composto.
+select-client-roles.tooltip=Selecione o cliente para visualizar os roles de cliente.
+assign.available-roles.tooltip=Roles de Cliente disponíveis para associação.
+client.assigned-roles.tooltip=Roles de Cliente associados.
+client.effective-roles.tooltip=Roles de cliente associados que podem ter sido herdados de um role composto.
+node-reregistration-timeout.tooltip=Intervalo para especificar o tempo máximo para nós clientes de cluster registrados se re-registrarem. Se os nós do cluster não enviarem solicitações de re-registro dentro deste intervalo eles serão deregistrados do Keycloak.
+client-revoke.not-before.tooltip=Revocar qualquer token emitido antes desta data para este cliente.
+client-revoke.push.tooltip=Se a URL de administração estiver configurada para este cliente, envie esta política para este cliente.
+offline-tokens.tooltip=Número total de tokens offline para este cliente.
+show-offline-tokens.tooltip=Atenção, esta é uma operação potencialmente cara dependendo do número de tokens offline.
+realm-certificate-alias.tooltip=O certificado do Realm também é guardado em arquivo. Este é o alias para ele.
+saml-encryption-key.tooltip=Chave de encriptação SAML.
+mapper.consent-required.tooltip=Ao conceder acesso temporário, deve o usuário consentir em prover esta informação para o cliente?
+consent-text.tooltip=Texto para exibir na página de consentimento
+mapper-type.tooltip=Tipo do mapeamento
+redirect-uri.tooltip=A url de redirecionamento para usar quando da configuração do provedor de identidade.
+identity-provider.alias.tooltip=O alias é o identificador único de um provedor de identidade e também é utilizado para construir a uri de redirecionamento.
+identity-provider.enabled.tooltip=Habilita/Desabilita este provedor de identidade.
+identity-provider.authenticate-by-default.tooltip=Indica se este provedor deve ser tentado por padrão para a autenticação mesmo ante de exibir a tela de login.
+identity-provider.store-tokens.tooltip=Habilita/desabilita se os tokens deve ser guardados depois de autenticar os usuários.
+identity-provider.stored-tokens-readable.tooltip=Habilita/desabilita se novos usuários podem ler quaisquer tokens salvo. Isto irá adicionar o role broker.read-token.
+update-profile-on-first-login.tooltip=Define condições onde um usuário precisa atualizar o seu perfil durante o primeiro login.
+trust-email.tooltip=Se habilitado então o e-mail provido por este provedor não será verificado mesmo que a verificação esteja habilitada para este realm.
+first-broker-login-flow.tooltip=Alias do fluxo de autenticação que será invocado depois do primeiro login com este provedor de identificação. O termo 'Primeiro Login' significa que ainda não existe uma conta no Keycloak ligada a esta conta autenticada neste provedor.
+post-broker-login-flow.tooltip=Alias do fluxo de autenticação que será invocado depois de cada login com esse provedor de identificação. É útil se você pretende adicionar verificações adicionais de cada usuário autenticado com este provedor (por exemplo OTP). Deixa vazio se você não deseja que nenhum autenticador adicionar seja invocado depois do login com este provedor de identificação. Note também que as implementações de autenticação devem assumir que o usuários já está definido na ClientSessioncom e com o provedor de identidade já definido.
+openid-connect-config.tooltip=OIDC SP e configuração externa IDP.
+authorization-url.tooltip=A URL de autorização.
+token-url.tooltip=A URL do Token.
+identity-provider.logout-url.tooltip='End session endpoint' para utilizar para realizar logour dos usuários do IDP externo.
+backchannel-logout.tooltip=O IDP externo suporta logou via backchannel?
+user-info-url.tooltip=A Url de informações de usuário. Opcional.
+identity-provider.client-id.tooltip=O cliente ou identificador do cliente registrado junto ao provedor de identificação.
+client-secret.tooltip=O cliente ou senha do cliente registrado junto ao provedor de identificação.
+social.client-secret.tooltip=A senha do cliente registrado junto ao provedor de identificação.
+issuer.tooltip=O identificador de emissor para o emissor da resposta. Se não for provido nenhuma validação será realizada.
+identity-provider.default-scopes.tooltip=Os escopos que serão enviados ao solicitar autorização. Pode ser uma lista de escopos separadas por espaço. Valor padrão é 'openid'.
+prompt.tooltip=Especifica se o Servidor de Autorização solicita ao Usuário Final reautenticação e consentimento.
+identity-provider.validate-signatures.tooltip=Habilita/Desabilita a validação de assinatura de IDP externo.
+identity-provider.validating-public-key.tooltip=A chave pública em formato PEM que deve ser usada para verificar assinaturas de IDP externos.
+import-external-idp-config.tooltip=Permite que vocÊ carregue metadata de IDP externos de um arquivo de configuração ou baixando a partir de uma URL.
+identity-provider.import-from-url.tooltip=Importar metadata de um descritor de descoberta remoto do IDP.
+identity-provider.import-from-file.tooltip=Importar metadata fr um descritor de descoberta baixado do IDP.
+identity-provider.saml-config.tooltip=SAML SP e configuração de IDP externo.
+saml.single-signon-service-url.tooltip=A Url que deve ser utilizada para enviar solicitações de autenticação (SAML AuthnRequest).
+saml.single-logout-service-url.tooltip=A Url que deve ser utilizada para enviar solicitações de logout.
+nameid-policy-format.tooltip=Especifica a referência de URI correspondente a um formato de nome identificador. O padrão é urn:oasis:names:tc:SAML:2.0:nameid-format:persistent.
+http-post-binding-response.tooltip=Indica se deve se responder a solicitações utilizando HTTP-POST. Se falso, HTTP-REDIRECT será utilizado.
+http-post-binding-for-authn-request.tooltip=Indica se o AuthnRequest deve ser enviado utilizando HTTP-POST. Se falso, HTTP-REDIRECT será utilizado.
+want-authn-requests-signed.tooltip=Indicate se um provedor de identificação deve experar um AuthnRequest assinado.
+identity-provider.force-authentication.tooltip=Indica se um provedor de identificação deve autenticar o apresentador diretamente ao invés de confiar em um contexto de segurança anterior.
+saml.validate-signature.tooltip=Habilita/Desabilita validação de assinaturas de respostas SAML.
+saml.import-from-url.tooltip=Importar metadata de um descritor de entidade IDP SAML remoto.
+social.client-id.tooltip=O identificador do cliente registrado com o provedor de identificação.
+social.default-scopes.tooltip=Os escopos que serão enviados ao solicitar autorização. Veja a documentação para valores possíveis, separador e valores padrão.
+stackoverflow.key.tooltip=A chave de cliente obtida do registro no Stack Overflow.
+client-templates.tooltip=Modelos de cliente permitem que você defina configurações comuns que serão compartilhadas entre múltiplos clientes.
+group.add-selected.tooltip=Roles do Realm que serão associadas ao grupo.
+group.effective-roles.tooltip=Todos os mapeamentos de roles do Realm. Alguns roles exibidos podem ter sido herdados de um role composto mapeado.
+group.available-roles.tooltip=Roles associáveis deste cliente.
+group.assigned-roles-client.tooltip=Mapeamentos de roles para este cliente.
+group.effective-roles-client.tooltip=Mapeamentos de roles para este cliente. Alguns roles exibidos podem ter sido herdados de um role composto mapeado.
+user.add-selected.tooltip=Roles do Realm que podem ser associados ao usuário.
+user.assigned-roles.tooltip=Roles do Realm mapeados para o usuário.
+user.effective-roles.tooltip=Todos os mapeamentos de roles do Realm. Alguns roles exibidos podem ter sido herdados de um role composto mapeado.
+user.available-roles.tooltip=Roles associáveis deste cliente.
+user.assigned-roles-client.tooltip=Mapeamentos de roles para este cliente.
+user.effective-roles-client.tooltip=Mapeamentos de Role para este cliente. Alguns roles exibidos podem ter sido herdados de um role composto mapeado.
+default.available-roles.tooltip=Roles do nível de Realm que podem ser associados.
+realm-default-roles.tooltip=Roles do nível de Realm associados a novos usuários.
+default.available-roles-client.tooltip=Roles para este cliente que são associáveis por padrão.
+client-default-roles.tooltip=Roles para este cliente que são associados como roles padrão.
+composite.available-roles.tooltip=Roles do nível de Realm associáveis com este role composto.
+composite.associated-roles.tooltip=Roles do nível de Realm associados com este role composto.
+composite.available-roles-client.tooltip=Roles para este cliente que podem ser associados com este role composto.
+composite.associated-roles-client.tooltip=Roles do cliente associados com este role composto.
+partial-import.tooltip=Importação parcial permite que você importe usuários, clientes, e outros recursos de um arquivo json previamente exportado.
+if-resource-exists.tooltip=Especifica o que deve ser feito se você tentar importar um recurso já existente.
+realm-roles.tooltip=Roles do Realm que podem ser selecionados.
+authz-policy-role-realm-roles.tooltip=Especifica quais role(s) de *realm* são permitidos por esta política.
+client-roles.tooltip=Roles do cliente que podem ser selecionados.
+authz-policy-role-client-roles.tooltip=Especifica quais role(s) do *cliente* são permitidos por esta política.
+client-template.tooltip=Modelo de cliente do qual ete cliente herda as configurações.
+client-template.name.tooltip=Nome do modelo de cliente. Deve ser único neste Realm.
+client-template.description.tooltip=Descrição do modelo de cliente.
+client-template.protocol.tooltip=Qual configuração de protocolo SSO será provida por este modelo de cliente.
+console-display-name.tooltip=Nome de exibição do provedor quando linkado no console de administração.
+priority.tooltip=Prioridade do provedor quando da busca de usuários. Valores mais baixos são utilizados primeiro.
+periodic-full-sync.tooltip=Habilitar ou não a sincronização completa periódica dos usuários deste provedor.
+ldap.periodic-full-sync.tooltip=Habilitar ou não a sincronização completa dos usuários do LDAP para o Keycloak.
+full-sync-period.tooltip=Intervalo para a sincronização completa em segundos.
+periodic-changed-users-sync.tooltip=Habilitar ou não a sincronização de usuários novos ou alterados do provedor para o Keycloak.
+ldap.periodic-changed-users-sync.tooltip=Habilitar ou não a sincronização de usuários novos ou alterados do LDAP para o Keycloak.
+changed-users-sync-period.tooltip=Intervalo para sincronização dos usuários alterados ou novos do provedor em segundos.
+ldap.changed-users-sync-period.tooltip=Intervalo para sincronização dos usuários alterados ou novos do LDAP em segundos.
+kerberos-realm.tooltip=Nome do realm kerberos. Por exemplo FOO.ORG
+server-principal.tooltip=Nome completo do principal do servidor para o serviço HTTP incluindo o servidor e nome do domínio. Por exemplo HTTP/host.foo.org@FOO.ORG
+keytab.tooltip=Localização do arquivo KeyTab do Kerberos contendo as credenciais do principal do servidor.  Por exemplo /etc/krb5.keytab
+debug.tooltip=Habilita/Desabilita log de nível debug para a saída padrão para Krb5LoginModule.
+allow-password-authentication.tooltip=Habilita/Desabilita a possibilidade de autenticação via usuário/senha contra o banco Kerberos
+edit-mode.tooltip=READ_ONLY significa que atualizações de senhas não são permitidas e o usuário sempre autenticará com a senha do Kerberos. UNSYNCED significa que o usuário pode alterar a senha no banco do Keycloak e essa senha será utilizda ao invés da senha do Kerberos.
+ldap.edit-mode.tooltip=READ_ONLY é um LDAP somente leitura. WRITABLE significa que os dados serão sicronizados de volta para o LDAP on demand. UNSYNCED significa que os dados do usuário serão importados, mas não sicronizados de volta para o LDAP.
+update-profile-first-login.tooltip=Atualizar o perfil no primeiro login
+ldap.sync-registrations.tooltip=Os novos usuários criados devem ser criados no LDAP? A prioridade afeta qual provedor é utilizado para sincronizar o novo usuário.
+ldap.vendor.tooltip=LDAP vendor (provedor)
+username-ldap-attribute.tooltip=Nome do atributo do LDAP que será mapeado como nome do usuário no Keycloak. Para muitos servidores LDAP este valor deve ser 'uid'. Para o Active Directory pode ser 'sAMAccountName' ou 'cn'. O atributo deve ser preenchido para todos os registros de usuários do LDAP que você deseja importar do LDAP para o Keycloak.
+rdn-ldap-attribute.tooltip=Nome do atributo LDAP que é utilizado como RDN (atributo topo) do DN do usuário típico. Geralmente é o mesmo que o atributo do nome do usuário, mas isto não é obrigatório. Por exemplo para o Active Directory é comum utilizar 'cn' como atributo RDN quando o atributo do nome de usuário pode ser 'sAMAccountName',
+uuid-ldap-attribute.tooltip=Nome do atributo LDAP que é utilizado como identificador único do objeto(UUID) para objetos no LDAP. Para muitos servidores LDAP o valor é 'entryUUID', porém alguns são diferentes. Por exemplo para o Active Directory este valor para objetos no LDAP deve ser 'objectGUID'. Se o seu servidor LDAP realmente não suporta a noção de UUID, vocÊ pode usar qualquer outro atributo que seja único na árvore de usuários do LDAP. Por exemplo 'uid' ou 'entryDN'.
+ldap.user-object-classes.tooltip=Todos os valores de objectClass para usuários no LDAP separados por vírgula. Por exemplo: 'inetOrgPerson, organizationalPerson'. Usuários criados no Keycloak serão enviados para o LDAP com todas essas classes de objetos associadas e dados de usuários do LDAP somente serão localizados se ele contiverem todas estas classes de objeto.
+ldap.connection-url.tooltip=Conexão URL para o seu servidor LDAP
+ldap.users-dn.tooltip=DN completo da árvore LDAP onde os usuários estão. Este DN é o pai dos usuários do LDAP. Por exemplo pode ser 'ou=users,dc=example,dc=com' entendendo que o usuário típico irá ter um DN como 'uid=john,ou=users,dc=example,dc=com'.
+ldap.authentication-type.tooltip=Tipo de autenticação no LDAP. No momento apenas os mecanismos 'none' (anonymous LDAP authentication) ou 'simple' (Credencial de bind + senha para bind) estão disponíveis.
+ldap.bind-dn.tooltip=DN do administrador do LDAP, que será utilizado pelo Keycloak para acessar o servidor LDAP.
+ldap.bind-credential.tooltip=Senha do administrador do LDAP
+ldap.custom-user-ldap-filter.tooltip=Additional LDAP Filter for filtering searched users. Leave this empty if you don't need additional filter. Make sure that it starts with '(' and ends with ')'
+ldap.use-truststore-spi.tooltip=Specifies whether LDAP connection will use the truststore SPI with the truststore configured in keycloak-server.json. 'Always' means that it will always use it. 'Never' means that it won't use it. 'Only for ldaps' means that it will use if your connection URL use ldaps. Note even if keycloak-server.json is not configured, the default Java cacerts or certificate specified by 'javax.net.ssl.trustStore' property will be used.
+ldap.connection-pooling.tooltip=Does Keycloak should use connection pooling for accessing LDAP server
+ldap.pagination.tooltip=Does the LDAP server support pagination.
+ldap.allow-kerberos-authentication.tooltip=Enable/disable HTTP authentication of users with SPNEGO/Kerberos tokens. The data about authenticated users will be provisioned from this LDAP server
+ldap.use-kerberos-for-password-authentication.tooltip=Use Kerberos login module for authenticate username/password against Kerberos server instead of authenticating against LDAP server with Directory Service API
+ldap.batch-size.tooltip=Count of LDAP users to be imported from LDAP to Keycloak within single transaction.
+identity-provider-user-id.tooltip=Unique ID of the user on the Identity Provider side
+identity-provider-username.tooltip=Username on the Identity Provider side
+browser-flow.tooltip=Select the flow you want to use for browser authentication.
+registration-flow.tooltip=Select the flow you want to use for registration.
+direct-grant-flow.tooltip=Select the flow you want to use for direct grant authentication.
+reset-credentials.tooltip=Select the flow you want to use when the user has forgotten their credentials.
+client-authentication.tooltip=Select the flow you want to use for authentication of clients.
+authenticator.alias.tooltip=Name of the configuration
+otp-type.tooltip=totp is Time-Based One Time Password. 'hotp' is a counter base one time password in which the server keeps a counter to hash against.
+otp-hash-algorithm.tooltip=What hashing algorithm should be used to generate the OTP.
+otp.number-of-digits.tooltip=How many digits should the OTP have?
+otp.look-ahead-window.tooltip=How far ahead should the server look just in case the token generator and server are out of time sync or counter sync?
+otp.initial-counter.tooltip=What should the initial counter value be?
+otp-token-period.tooltip=How many seconds should an OTP token be valid? Defaults to 30 seconds.
+admin-events.tooltip=Displays saved admin events for the realm. Events are related to admin account, for example a realm creation. To enable persisted events go to config.
+clear-admin-events.tooltip=Deletes all admin events in the database.
+resource-path.tooltip=Filter by resource path. Supports wildcards '*' to match a single part of the path and '**' matches multiple parts. For example 'realms/*/clients/asbc' matches client with id asbc in any realm, while or 'realms/master/**' matches anything in the master realm.
+auth.default-action.tooltip=If enabled, any new user will have this required action assigned to it.
+groups.default-groups.tooltip=Set of groups that new users will automatically join.
+flow.alias.tooltip=Specifies display name for the flow.
+top-level-flow-type.tooltip=What kind of top level flow is it? Type 'client' is used for authentication of clients (applications) when generic is for users and everything else
+flow-type.tooltip=What kind of form is it
+default-groups.tooltip=Newly created or registered users will automatically be added to these groups
+available-groups.tooltip=Select a group you want to add as a default.
+membership.available-groups.tooltip=Groups a user can join. Select a group and click the join button.
+events.tooltip=Displays saved events for the realm. Events are related to user accounts, for example a user login. To enable persisted events go to config.
+login.save-events.tooltip=If enabled login events are saved to the database which makes events available to the admin and account management consoles.
+admin.save-events.tooltip=If enabled admin events are saved to the database which makes events available to the admin console.
+events-config.tooltip=Displays configuration options to enable persistence of user and admin events.
+event-listeners.tooltip=Configure what listeners receive events for the realm.
+clear-events.tooltip=Deletes all events in the database.
+events.expiration.tooltip=Sets the expiration for events. Expired events are periodically deleted from the database.
+saved-types.tooltip=Configure what event types are saved.
+include-representation.tooltip=Include JSON representation for create and update requests.
+credentials.temporary.tooltip=If enabled user is required to change password on next login
+credentials.remove-totp.tooltip=Remove one time password generator for user.
+credentials.reset-actions.tooltip=Set of actions to execute when sending the user a Reset Actions Email. 'Verify email' sends an email to the user to verify their email address. 'Update profile' requires user to enter in new personal information. 'Update password' requires user to enter in a new password. 'Configure TOTP' requires setup of a mobile password generator.
+credentials.reset-actions-email.tooltip=Sends an email to user with an embedded link. Clicking on link will allow the user to execute the reset actions. They will not have to login prior to this. For example, set the action to update password, click this button, and the user will be able to change their password without logging in.
+user-enabled.tooltip=A disabled user cannot login.
+user-temporarily-locked.tooltip=The user may have been locked due to failing to login too many times.
+email-verified.tooltip=Has the user's email been verified?
+required-user-actions.tooltip=Require an action when the user logs in. 'Verify email' sends an email to the user to verify their email address. 'Update profile' requires user to enter in new personal information. 'Update password' requires user to enter in a new password. 'Configure TOTP' requires setup of a mobile password generator.
+impersonate-user.tooltip=Login as this user. If user is in same realm as you, your current login session will be logged out before you are logged in as this user.
+group-membership.tooltip=Groups user is a member of. Select a listed group and click the Leave button to leave the group.
+import-keys-and-cert.tooltip=Upload the client's key pair and cert.
+authz-icon-uri.tooltip=An URI pointing to an icon.
+authz-authorization-services-enabled.tooltip=Enable/Disable fine-grained authorization support for a client
+authz-import-config.tooltip=Import a JSON file containing authorization settings for this resource server.
+authz-policy-enforcement-mode.tooltip=The policy enforcement mode dictates how policies are enforced when evaluating authorization requests. 'Enforcing' means requests are denied by default even when there is no policy associated with a given resource. 'Permissive' means requests are allowed even when there is no policy associated with a given resource. 'Disabled' completely disables the evaluation of policies and allow access to any resource.
+authz-remote-resource-management.tooltip=Should resources be managed remotely by the resource server? If false, resources can only be managed from this admin console.
+authz-export-settings.tooltip=Export and download all authorization settings for this resource server.
+authz-resource-name.tooltip=An unique name for this resource. The name can be used to uniquely identify a resource, useful when querying for a specific resource.
+authz-resource-owner.tooltip=The owner of this resource.
+authz-resource-type.tooltip=The type of this resource. It can be used to group different resource instances with the same type.
+authz-resource-uri.tooltip=An URI that can also be used to uniquely identify this resource.
+authz-resource-scopes.tooltip=The scopes associated with this resource.
+authz-scope-name.tooltip=An unique name for this scope. The name can be used to uniquely identify a scope, useful when querying for a specific scope.
+authz-policy-name.tooltip=The name of this policy.
+authz-policy-description.tooltip=A description for this policy.
+authz-policy-logic.tooltip=The logic dictates how the policy decision should be made. If 'Positive', the resulting effect (permit or deny) obtained during the evaluation of this policy will be used to perform a decision. If 'Negative', the resulting effect will be negated, in other words, a permit becomes a deny and vice-versa.
+authz-policy-apply-policy.tooltip=Specifies all the policies that must be applied to the scopes defined by this policy or permission.
+authz-policy-decision-strategy.tooltip=The decision strategy dictates how the policies associated with a given policy are evaluated and how a final decision is obtained. 'Affirmative' means that at least one policy must evaluate to a positive decision in order to the overall decision be also positive. 'Unanimous' means that all policies must evaluate to a positive decision in order to the overall decision be also positive. 'Consensus' means that the number of positive decisions must be greater than the number of negative decisions. If the number of positive and negative is the same, the final decision will be negative.
+authz-policy-user-users.tooltip=Specifies which user(s) are allowed by this policy.
+authz-policy-time-not-before.tooltip=Defines the time before which the policy MUST NOT be granted. Only granted if current date/time is after or equal to this value.
+authz-policy-time-not-on-after.tooltip=Defines the time after which the policy MUST NOT be granted. Only granted if current date/time is before or equal to this value.
+authz-policy-drools-maven-artifact.tooltip=A Maven GAV pointing to an artifact from where the rules would be loaded from. Once you have provided the GAV, you can click *Resolve* to load both *Module* and *Session* fields.
+authz-policy-drools-module.tooltip=The module used by this policy. You must provide a module in order to select a specific session from where rules will be loaded from.
+authz-policy-drools-session.tooltip=The session used by this policy. The session provides all the rules to evaluate when processing the policy.
+authz-policy-drools-update-period.tooltip=Specifies an interval for scanning for artifact updates.
+authz-policy-js-code.tooltip=The JavaScript code providing the conditions for this policy.
+authz-permission-name.tooltip=The name of this permission.
+authz-permission-description.tooltip=A description for this permission.
+authz-permission-resource-apply-to-resource-type.tooltip=Specifies if this permission would be applied to all resources with a given type. In this case, this permission will be evaluated for all instances of a given resource type.
+authz-permission-resource-resource.tooltip=Specifies that this permission must be applied to a specific resource instance.
+authz-permission-resource-type.tooltip=Specifies that this permission must be applied to all resources instances of a given type.
+authz-permission-scope-resource.tooltip=Restrict the scopes to those associated with the selected resource. If not selected all scopes would be available.
+authz-evaluation-identity-information.tooltip=The available options to configure the identity information that will be used when evaluating policies.
+authz-evaluation-client.tooltip=Select the client making this authorization request. If not provided, authorization requests would be done based on the client you are in.
+authz-evaluation-user.tooltip=Select an user whose identity is going to be used to query permissions from the server.
+authz-evaluation-role.tooltip=Select the roles you want to associate with the selected user.
+authz-evaluation-contextual-info.tooltip=The available options to configure any contextual information that will be used when evaluating policies.
+authz-evaluation-contextual-attributes.tooltip=Any attribute provided by a running environment or execution context.
+authz-evaluation-permissions.tooltip=The available options to configure the permissions to which policies will be applied.
+authz-evaluation-result.tooltip=The overall result for this permission request.
+authz-evaluation-scopes.tooltip=The list of allowed scopes.
+authz-evaluation-policies.tooltip=Details about which policies were evaluated and their decisions.
+authz-evaluation-authorization-data.tooltip=Represents a token carrying authorization data as a result of the processing of an authorization request. This representation is basically what Keycloak issues to clients asking for permissions. Check the 'authorization' claim for the permissions that were granted based on the current authorization request.
diff --git a/themes/src/main/resources/theme/base/admin/messages/messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/messages_en.properties
index 345cb25..f4044ab 100644
--- a/themes/src/main/resources/theme/base/admin/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/messages_en.properties
@@ -14,4 +14,11 @@ ldapErrorCantWriteOnlyForReadOnlyLdap=Can't set write only when LDAP provider mo
 ldapErrorCantWriteOnlyAndReadOnly=Can't set write-only and read-only together
 
 clientRedirectURIsFragmentError=Redirect URIs must not contain an URI fragment
-clientRootURLFragmentError=Root URL must not contain an URL fragment
\ No newline at end of file
+clientRootURLFragmentError=Root URL must not contain an URL fragment
+
+pairwiseMalformedClientRedirectURI=Client contained an invalid redirect URI.
+pairwiseClientRedirectURIsMissingHost=Client redirect URIs must contain a valid host component.
+pairwiseClientRedirectURIsMultipleHosts=Without a configured Sector Identifier URI, client redirect URIs must not contain multiple host components.
+pairwiseMalformedSectorIdentifierURI=Malformed Sector Identifier URI.
+pairwiseFailedToGetRedirectURIs=Failed to get redirect URIs from the Sector Identifier URI.
+pairwiseRedirectURIsMismatch=Client redirect URIs does not match redirect URIs fetched from the Sector Identifier URI.
diff --git a/themes/src/main/resources/theme/base/admin/messages/messages_lt.properties b/themes/src/main/resources/theme/base/admin/messages/messages_lt.properties
new file mode 100644
index 0000000..4908925
--- /dev/null
+++ b/themes/src/main/resources/theme/base/admin/messages/messages_lt.properties
@@ -0,0 +1,17 @@
+invalidPasswordMinLengthMessage=Per trumpas slapta\u00c5\u00beodis: ma\u00c5\u00beiausias ilgis {0}.
+invalidPasswordMinLowerCaseCharsMessage=Neteisingas slapta\u00c5\u00beodis: privaloma \u00c4\u00c6vesti {0} ma\u00c5\u00be\u00c4\u2026j\u00c4\u2026 raid\u00c4\u2122.
+invalidPasswordMinDigitsMessage=Neteisingas slapta\u00c5\u00beodis: privaloma \u00c4\u00c6vesti {0} skaitmen\u00c4\u00c6.
+invalidPasswordMinUpperCaseCharsMessage=Neteisingas slapta\u00c5\u00beodis: privaloma \u00c4\u00c6vesti {0} did\u00c5\u00bei\u00c4\u2026j\u00c4\u2026 raid\u00c4\u2122.
+invalidPasswordMinSpecialCharsMessage=Neteisingas slapta\u00c5\u00beodis: privaloma \u00c4\u00c6vesti {0} special\u00c5\u00b3 simbol\u00c4\u00c6.
+invalidPasswordNotUsernameMessage=Neteisingas slapta\u00c5\u00beodis: slapta\u00c5\u00beodis negali sutapti su naudotojo vardu.
+invalidPasswordRegexPatternMessage=Neteisingas slapta\u00c5\u00beodis: slapta\u00c5\u00beodis netenkina regex taisykl\u00c4\u2014s(i\u00c5\u00b3).
+invalidPasswordHistoryMessage=Neteisingas slapta\u00c5\u00beodis: slapta\u00c5\u00beodis negali sutapti su prie\u00c5\ufffd tai buvusiais {0} slapta\u00c5\u00beod\u00c5\u00beiais.
+
+ldapErrorInvalidCustomFilter=Sukonfig\u016Bruotas LDAP filtras neprasideda "(" ir nesibaigia ")" simboliais.
+ldapErrorMissingClientId=Privaloma nurodyti kliento ID kai srities roli\u0173 susiejimas n\u0117ra nenaudojamas.
+ldapErrorCantPreserveGroupInheritanceWithUIDMembershipType=Grupi\u0173 paveld\u0117jimo ir UID naryst\u0117s tipas kartu negali b\u016Bti naudojami.
+ldapErrorCantWriteOnlyForReadOnlyLdap=Negalima nustatyti ra\u0161ymo r\u0117\u017Eimo kuomet LDAP teik\u0117jo r\u0117\u017Eimas ne WRITABLE
+ldapErrorCantWriteOnlyAndReadOnly=Negalima nustatyti tik ra\u0161yti ir tik skaityti kartu
+
+clientRedirectURIsFragmentError=Nurodykite URI fragment\u0105, kurio negali b\u016Bti peradresuojamuose URI adresuose
+clientRootURLFragmentError=Nurodykite URL fragment\u0105, kurio negali b\u016Bti \u0161akniniame URL adrese
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/messages/messages_pt_BR.properties b/themes/src/main/resources/theme/base/admin/messages/messages_pt_BR.properties
index e69de29..b26e465 100644
--- a/themes/src/main/resources/theme/base/admin/messages/messages_pt_BR.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/messages_pt_BR.properties
@@ -0,0 +1,18 @@
+#encoding: utf-8
+invalidPasswordMinLengthMessage=Senha inválida: deve conter ao menos {0} caracteres.
+invalidPasswordMinLowerCaseCharsMessage=Senha inválida: deve conter ao menos {0} caracteres minúsculos.
+invalidPasswordMinDigitsMessage=Senha inválida: deve conter ao menos {0} digitos numéricos.
+invalidPasswordMinUpperCaseCharsMessage=Senha inválida: deve conter ao menos {0} caracteres maiúsculos.
+invalidPasswordMinSpecialCharsMessage=Senha inválida: deve conter ao menos {0} caracteres especiais.
+invalidPasswordNotUsernameMessage=Senha inválida: não deve ser igual ao nome de usuário.
+invalidPasswordRegexPatternMessage=Senha inválida: falha ao passar por padrões.
+invalidPasswordHistoryMessage=Senha inválida: não deve ser igual às últimas {0} senhas.
+
+ldapErrorInvalidCustomFilter=Filtro LDAP não inicia com "(" ou não termina com ")".
+ldapErrorMissingClientId=ID do cliente precisa ser definido na configuração quando mapeamentos de Roles do Realm não é utilizado.
+ldapErrorCantPreserveGroupInheritanceWithUIDMembershipType=Não é possível preservar herança de grupos e usar tipo de associação de UID ao mesmo tempo.
+ldapErrorCantWriteOnlyForReadOnlyLdap=Não é possível definir modo de somente escrita quando o provedor LDAP não suporta escrita
+ldapErrorCantWriteOnlyAndReadOnly=Não é possível definir somente escrita e somente leitura ao mesmo tempo
+
+clientRedirectURIsFragmentError=URIs de redirecionamento não podem conter fragmentos
+clientRootURLFragmentError=URL raiz não pode conter fragmentos
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index 3bbd471..12af561 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -812,6 +812,7 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, templates,
     $scope.samlEncrypt = false;
     $scope.samlForcePostBinding = false;
     $scope.samlForceNameIdFormat = false;
+    $scope.disableAuthorizationTab = !client.authorizationServicesEnabled;
 
     function updateProperties() {
         if (!$scope.client.attributes) {
@@ -1702,6 +1703,12 @@ module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo
             mapper = angular.copy($scope.mapper);
             $location.url("/realms/" + realm.realm + '/clients/' + client.id + "/mappers/" + $scope.model.mapper.id);
             Notifications.success("Your changes have been saved.");
+        }, function(error) {
+            if (error.status == 400 && error.data.error_description) {
+                Notifications.error(error.data.error_description);
+            } else {
+                Notifications.error('Unexpected error when updating protocol mapper');
+            }
         });
     };
 
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/services.js b/themes/src/main/resources/theme/base/admin/resources/js/services.js
index 6d8fdcd..a063143 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -274,7 +274,7 @@ module.service('ServerInfo', function($resource, $q, $http) {
     var delay = $q.defer();
 
     $http.get(authUrl + '/admin/serverinfo').success(function(data) {
-        info = data;
+        angular.copy(data, info);
         delay.resolve(info);
     });
 
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
index d8f0d24..9fb3a2d 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
@@ -110,7 +110,7 @@
                     <input ng-model="client.serviceAccountsEnabled" name="serviceAccountsEnabled" id="serviceAccountsEnabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
                 </div>
             </div>
-            <div class="form-group" data-ng-show="protocol == 'openid-connect'">
+            <div class="form-group" data-ng-show="serverInfo.profileInfo.previewEnabled && protocol == 'openid-connect'">
                 <label class="col-md-2 control-label" for="authorizationServicesEnabled">{{:: 'authz-authorization-services-enabled' | translate}}</label>
                 <kc-tooltip>{{:: 'authz-authorization-services-enabled.tooltip' | translate}}</kc-tooltip>
                 <div class="col-md-6">
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
index 1b1ae96..2f5ed40 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
@@ -1,7 +1,32 @@
 <div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
     <h1>{{:: 'identity-providers' | translate}}</h1>
+    <div class="blank-slate-pf" data-ng-hide="configuredProviders.length > 0">
+        <div class="blank-slate-pf-icon">
+            <span class="fa fa-exchange"></span>
+        </div>
+    <h1>
+        Identity Providers
+    </h1>
+    <p class="">
+        Through Identity Brokering it's easy to allow users to authenticate to Keycloak using external Identity Providers or Social Networks.<br> We have built-in support for OpenID Connect and SAML 2.0 as well as a number of social networks such as Google, GitHub, Facebook and Twitter.
+    </p>
+    <p>To get started select a provider from the dropdown below:</p>
+    <div class="blank-slate-pf-main-action">
+        <div class="row" data-ng-show="access.manageIdentityProviders">
+          <div class="col-sm-4 col-sm-offset-4">
+            <div class="form-group">
+            <select class="selectpicker form-control" ng-model="provider"
+              ng-options="p.name group by p.groupName for p in allProviders track by p.id"
+              data-ng-change="addProvider(provider); provider = null">
+              <option value="" disabled selected>{{:: 'add-provider.placeholder' | translate}}</option>
+          </select>
+      </div>
+  </div>
+</div>
+</div>
 
-    <form name="realmForm" novalidate class="form-horizontal">
+</div>
+    <form name="realmForm" novalidate class="form-horizontal" ng-show="configuredProviders.length > 0">
         <fieldset>
             <div>
                 <table class="table table-striped table-bordered">
@@ -18,7 +43,7 @@
                             </div>
                         </th>
                     </tr>
-                    <tr ng-show="configuredProviders.length > 0">
+                    <tr>
                         <th>{{:: 'name' | translate}}</th>
                         <th>{{:: 'provider' | translate}}</th>
                         <th>{{:: 'enabled' | translate}}</th>
@@ -26,7 +51,7 @@
                         <th colspan="2">{{:: 'actions' | translate}}</th>
                     </tr>
                     </thead>
-                    <tbody ng-show="configuredProviders.length > 0">
+                    <tbody>
                     <tr ng-repeat="identityProvider in configuredProviders">
                         <td>
                             <a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">{{identityProvider.alias}}</a>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
index 81690be..bbbf9b9 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
@@ -35,13 +35,6 @@
                 <kc-tooltip>{{:: 'identity-provider.enabled.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group">
-                <label class="col-md-2 control-label" for="authenticateByDefault">{{:: 'authenticate-by-default' | translate}}</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
-                </div>
-                <kc-tooltip>{{:: 'identity-provider.authenticate-by-default.tooltip' | translate}}</kc-tooltip>
-            </div>
-            <div class="form-group">
                 <label class="col-md-2 control-label" for="storeToken">{{:: 'store-tokens' | translate}}</label>
                 <div class="col-md-6">
                     <input ng-model="identityProvider.storeToken" id="storeToken" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
index f9b8c74..eaf4439 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
@@ -32,13 +32,6 @@
                 <kc-tooltip>{{:: 'identity-provider.enabled.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group">
-                <label class="col-md-2 control-label" for="authenticateByDefault">{{:: 'authenticate-by-default' | translate}}</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
-                </div>
-                <kc-tooltip>{{:: 'identity-provider.authenticate-by-default.tooltip' | translate}}</kc-tooltip>
-            </div>
-            <div class="form-group">
                 <label class="col-md-2 control-label" for="storeToken">{{:: 'store-tokens' | translate}}</label>
                 <div class="col-md-6">
                     <input ng-model="identityProvider.storeToken" id="storeToken" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
index 9599d98..6c7ceb7 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
@@ -71,13 +71,6 @@
                 <kc-tooltip>{{:: 'trust-email.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group">
-                <label class="col-md-2 control-label" for="authenticateByDefault">{{:: 'authenticate-by-default' | translate}}</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
-                </div>
-                <kc-tooltip>{{:: 'identity-provider.authenticate-by-default.tooltip' | translate}}</kc-tooltip>
-            </div>
-            <div class="form-group">
                 <label class="col-md-2 control-label" for="guiOrder">{{:: 'gui-order' | translate}}</label>
                 <div class="col-md-6">
                     <input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/server-info.html b/themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
index 0607250..299a93b 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
@@ -15,6 +15,10 @@
             <td>{{serverInfo.systemInfo.version}}</td>
         </tr>
         <tr>
+            <td width="20%">{{:: 'server-profile' | translate}}</td>
+            <td>{{serverInfo.profileInfo.name}}</td>
+        </tr>
+        <tr>
             <td>{{:: 'server-time' | translate}}</td>
             <td>{{serverInfo.systemInfo.serverTime}}</td>
         </tr>
diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html
index a0d88c6..e2d5db2 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html
@@ -19,7 +19,7 @@
             <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/scope-mappings">{{:: 'scope' | translate}}</a>
             <kc-tooltip>{{:: 'scope.tooltip' | translate}}</kc-tooltip>
         </li>
-        <li ng-class="{active: path[4] == 'authz'}" data-ng-show="client.authorizationServicesEnabled"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server">{{:: 'authz-authorization' | translate}}</a></li>
+        <li ng-class="{active: path[4] == 'authz'}" data-ng-show="serverInfo.profileInfo.previewEnabled && !disableAuthorizationTab && client.authorizationServicesEnabled"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server">{{:: 'authz-authorization' | translate}}</a></li>
         <li ng-class="{active: path[4] == 'revocation'}"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/revocation">{{:: 'revocation' | translate}}</a></li>
     <!--    <li ng-class="{active: path[4] == 'identity-provider'}" data-ng-show="realm.identityFederationEnabled"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/identity-provider">Identity Provider</a></li> -->
         <li ng-class="{active: path[4] == 'sessions'}" data-ng-show="!client.bearerOnly">
diff --git a/themes/src/main/resources/theme/base/admin/theme.properties b/themes/src/main/resources/theme/base/admin/theme.properties
index 0533ca8..46cee85 100644
--- a/themes/src/main/resources/theme/base/admin/theme.properties
+++ b/themes/src/main/resources/theme/base/admin/theme.properties
@@ -1,2 +1,2 @@
 import=common/keycloak
-locales=ca,de,en,es,fr,it,ja,pt-BR,ru,no
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,lt,no,pt-BR,ru
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/email/messages/messages_lt.properties b/themes/src/main/resources/theme/base/email/messages/messages_lt.properties
new file mode 100644
index 0000000..f0eb51c
--- /dev/null
+++ b/themes/src/main/resources/theme/base/email/messages/messages_lt.properties
@@ -0,0 +1,24 @@
+emailVerificationSubject=El. pa\u0161to patvirtinimas
+emailVerificationBody=Paskyra {2} sukurta naudojant \u0161\u012F el. pa\u0161to adres\u0105. Jei tau buvote J\u016Bs, tuomet paspauskite \u017Eemiau esan\u010Di\u0105 nuorod\u0105\n\n{0}\n\n\u0160i nuoroda galioja {1} min.\n\nJei paskyros nek\u016Br\u0117te, tuomet ignuoruokite \u0161\u012F lai\u0161k\u0105. 
+emailVerificationBodyHtml=<p>Paskyra {2} sukurta naudojant \u0161\u012F el. pa\u0161to adres\u0105. Jei tau buvote J\u016Bs, tuomet paspauskite \u017Eemiau esan\u010Di\u0105 nuorod\u0105</p><p><a href=LT"{0}">{0}</a></p><p>\u0160i nuoroda galioja {1} min.</p><p>nJei paskyros nek\u016Br\u0117te, tuomet ignuoruokite \u0161\u012F lai\u0161k\u0105.</p>
+identityProviderLinkSubject=S\u0105saja {0}
+identityProviderLinkBody=Ka\u017Eas pageidauja susieti J\u016Bs\u0173 "{1}" paskyr\u0105 su "{0}" {2} naudotojo paskyr\u0105. Jei tai buvote J\u016Bs, tuomet paspauskite \u017Eemiau esan\u010Di\u0105 nuorod\u0105 nor\u0117dami susieti paskyras\n\n{3}\n\n\u0160i nuoroda galioja {4} min.\n\nJei paskyr\u0173 susieti nenorite, tuomet ignoruokite \u0161\u012F lai\u0161k\u0105. Jei paskyras susiesite, tuomet prie {1} gal\u0117siste prisijungti per {0}.
+identityProviderLinkBodyHtml=<p>\u017Eas pageidauja susieti J\u016Bs\u0173 <b>{1}</b> paskyr\u0105 su <b>{0}</b> {2} naudotojo paskyr\u0105. Jei tai buvote J\u016Bs, tuomet paspauskite \u017Eemiau esan\u010Di\u0105 nuorod\u0105 nor\u0117dami susieti paskyras</p><p><a href=LT"{3}">{3}</a></p><p>\u0160i nuoroda galioja {4} min.</p><p>Jei paskyr\u0173 susieti nenorite, tuomet ignoruokite \u0161\u012F lai\u0161k\u0105. Jei paskyras susiesite, tuomet prie {1} gal\u0117siste prisijungti per {0}.</p>
+passwordResetSubject=Slapta\u017Eod\u017Eio atk\u016Brimas
+passwordResetBody=Ka\u017Ekas pageidauja pakeisti J\u016Bs\u0173 paskyros {2} slapta\u017Eod\u012F. Jei tai buvote J\u016Bs, tuomet paspauskite \u017Eemiau esan\u010Di\u0105 nuorod\u0105 slapta\u017Eod\u017Eio pakeitimui.\n\n{0}\n\n\u0160i nuoroda ir kodas galioja {1} min.\n\nJei nepageidajate keisti slapta\u017Eod\u017Eio, tuomet ignoruokite \u0161\u012F lai\u0161k\u0105 ir niekas nebus pakeista.
+passwordResetBodyHtml=<p>Ka\u017Ekas pageidauja pakeisti J\u016Bs\u0173 paskyros {2} slapta\u017Eod\u012F. Jei tai buvote J\u016Bs, tuomet paspauskite \u017Eemiau esan\u010Di\u0105 nuorod\u0105 slapta\u017Eod\u017Eio pakeitimui.</p><p><a href=LT"{0}">{0}</a></p><p>\u0160i nuoroda ir kodas galioja {1} min.</p><p>Jei nepageidajate keisti slapta\u017Eod\u017Eio, tuomet ignoruokite \u0161\u012F lai\u0161k\u0105 ir niekas nebus pakeista.</p>
+executeActionsSubject=Atnaujinkite savo paskyr\u0105
+executeActionsBody=Sistemos administratorius pageidauja, kad J\u016Bs atnaujintum\u0117te savo {2} paskyr\u0105. Paspauskite \u017Eemiau esan\u010Di\u0105 nuorod\u0105 paskyros duomen\u0173 atnaujinimui.\n\n{0}\n\n\u0160i nuoroda galioja {1} min.\n\nJei J\u016Bs neasate tikri, kad tai administratoriaus pageidavimas, tuomet ignoruokite \u0161\u012F lai\u0161k\u0105 ir niekas nebus pakeista.
+executeActionsBodyHtml=<p>Sistemos administratorius pageidauja, kad J\u016Bs atnaujintum\u0117te savo {2} paskyr\u0105. Paspauskite \u017Eemiau esan\u010Di\u0105 nuorod\u0105 paskyros duomen\u0173 atnaujinimui.</p><p><a href=LT"{0}">{0}</a></p><p>\u0160i nuoroda galioja {1} min.</p><p>Jei J\u016Bs neasate tikri, kad tai administratoriaus pageidavimas, tuomet ignoruokite \u0161\u012F lai\u0161k\u0105 ir niekas nebus pakeista.</p>
+eventLoginErrorSubject=Bandymas prisijungti prie J\u016Bs\u0173 paskyros
+eventLoginErrorBody=Bandymas prisijungti prie J\u016Bs\u0173 paskyros {0} i\u0161 {1} nes\u012Fkmingas. Jei tai nebuvote J\u016Bs, tuomet susisiekite su administratoriumi
+eventLoginErrorBodyHtml=<p>Bandymas prisijungti prie J\u016Bs\u0173 paskyros {0} i\u0161 {1} nes\u012Fkmingas. Jei tai nebuvote J\u016Bs, tuomet susisiekite su administratoriumi</p>
+eventRemoveTotpSubject=TOTP pa\u0161alinimas
+eventRemoveTotpBody=Ka\u017Ekas pageidauja atsieti TOPT J\u016Bs\u0173 {1} paskyroje su {0}. Jei tai nebuvote J\u016Bs, tuomet susisiekite su administratoriumi
+eventRemoveTotpBodyHtml=<p>Ka\u017Ekas pageidauja atsieti TOPT J\u016Bs\u0173 <b>{1}</b> paskyroje su <b>{0}</b>. Jei tai nebuvote J\u016Bs, tuomet susisiekite su administratoriumi</p>
+eventUpdatePasswordSubject=Slapta\u017Eod\u017Eio atnaujinimas
+eventUpdatePasswordBody=J\u016Bs\u0173 slapta\u017Eodis J\u016Bs\u0173 {1} paskyroje su {0} buvo pakeisas. Jei tai nebuvote J\u016Bs, tuomet susisiekite su administratoriumi
+eventUpdatePasswordBodyHtml=<p>J\u016Bs\u0173 {1} paskyroje su {0. Jei tai nebuvote J\u016Bs, tuomet susisiekite su administratoriumi</p>
+eventUpdateTotpSubject=TOTP atnaujinimas
+eventUpdateTotpBody=TOTP J\u016Bs\u0173 {1} paskyroje su {0} buvo atnaujintas. Jei tai nebuvote J\u016Bs, tuomet susisiekite su administratoriumi
+eventUpdateTotpBodyHtml=<p>TOTP J\u016Bs\u0173 {1} paskyroje su {0} buvo atnaujintas. Jei tai nebuvote J\u016Bs, tuomet susisiekite su administratoriumi</p>
diff --git a/themes/src/main/resources/theme/base/email/theme.properties b/themes/src/main/resources/theme/base/email/theme.properties
index deb2dc9..2cf724d 100644
--- a/themes/src/main/resources/theme/base/email/theme.properties
+++ b/themes/src/main/resources/theme/base/email/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,ja,pt-BR,ru,no
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,lt,no,pt-BR,ru
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/login/messages/messages_en.properties b/themes/src/main/resources/theme/base/login/messages/messages_en.properties
index b07446b..f69733a 100755
--- a/themes/src/main/resources/theme/base/login/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/login/messages/messages_en.properties
@@ -219,6 +219,7 @@ locale_no=Norsk
 locale_pt_BR=Portugu\u00EAs (Brasil)
 locale_pt-BR=Portugu\u00EAs (Brasil)
 locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439
+locale_lt=Lietuvi\u0173
 
 backToApplication=&laquo; Back to Application
 missingParameterMessage=Missing parameters\: {0}
diff --git a/themes/src/main/resources/theme/base/login/messages/messages_lt.properties b/themes/src/main/resources/theme/base/login/messages/messages_lt.properties
new file mode 100644
index 0000000..bffd8ed
--- /dev/null
+++ b/themes/src/main/resources/theme/base/login/messages/messages_lt.properties
@@ -0,0 +1,218 @@
+doLogIn=Prisijungti
+doRegister=Registruotis
+doCancel=At\u0161aukti
+doSubmit=Patvirtinti
+doYes=Taip
+doNo=Ne
+doContinue=T\u0119sti
+doAccept=Patvirtinti
+doDecline=At\u0161aukti
+doForgotPassword=Pamir\u0161ote slapta\u017Eod\u012F?
+doClickHere=Spauskite \u010Dia
+doImpersonate=Apsimesti kaip
+kerberosNotConfigured=Kerberos nesukonfig\u016Bruotas
+kerberosNotConfiguredTitle=Kerberos nesukonfig\u016Bruotas
+bypassKerberosDetail=J\u016Bs neprisijung\u0119s per Kerberos arba J\u016Bs\u0173 nar\u0161ykl\u0117 nesukonfig\u016Bruota Kerberos prisijungimui.  T\u0119skite ir pasirinkite kit\u0105 prisijungimo b\u016Bd\u0105
+kerberosNotSetUp=Kerberos nesukonfig\u016Bruotas.  J\u016Bs negalite prisijungti.
+registerWithTitle=Registruotis su {0}
+registerWithTitleHtml={0}
+loginTitle=Prisijungti su {0}
+loginTitleHtml={0}
+impersonateTitle=Apsimesti kaip naudotojas {0} 
+impersonateTitleHtml=Apsimesti kaip <strong>{0}</strong>
+realmChoice=Sritis
+unknownUser=Ne\u017Einomas naudotojas
+loginTotpTitle=Mobilaus autentifikatoriaus nustatymas
+loginProfileTitle=Atnaujinti paskyros informacij\u0105
+loginTimeout=U\u017Etrukote per ilgai. Prisijungimo procesas pradedamas i\u0161 naujo.
+oauthGrantTitle=Suteitikti prieig\u0105
+oauthGrantTitleHtml={0}
+errorTitle=Atsipra\u0161ome ...
+errorTitleHtml=<strong>Atsipra\u0161ome</strong> ...
+emailVerifyTitle=El. pa\u0161to adreso patvirtinimas
+emailForgotTitle=Pamir\u0161ote slapta\u017Eod\u012F?
+updatePasswordTitle=Atnaujinti slapta\u017Eod\u012F
+codeSuccessTitle=S\u0117km\u0117
+codeErrorTitle=Klaidos kodas\: {0}
+
+termsTitle=Naudojimo s\u0105lygos
+termsTitleHtml=Naudojimo s\u0105lygos
+termsText=<p>Naudojimo s\u0105lygos nenurodytos</p>
+
+recaptchaFailed=Recaptcha neteisingas
+recaptchaNotConfigured=Reikalingas Recaptcha nesukonfig\u016Bruotas
+consentDenied=Prieiga draud\u017Eiama.
+
+noAccount=Dar neturite paskyros?
+username=Naudotojo vardas
+usernameOrEmail=Naudotojo vardas arba el. pa\u0161to adresas
+firstName=Vardas
+givenName=Vardas
+fullName=Pavard\u0117
+lastName=Pavard\u0117
+familyName=Pavard\u0117
+email=El. pa\u0161tas
+password=Slapta\u017Eodis
+passwordConfirm=Pakartotas slapta\u017Eodis
+passwordNew=Naujas slapta\u017Eodis
+passwordNewConfirm=Pakartotas naujas slapta\u017Eodis
+rememberMe=Prisiminti mane
+authenticatorCode=Vienkartinis kodas
+address=Adresas
+street=Gatv\u0117
+locality=Miestas arba vietov\u0117
+region=Rajonas
+postal_code=Pa\u0161to kodas
+country=\u0160alis
+emailVerified=El. pa\u0161to adresas patvirtintas
+gssDelegationCredential=GSS prisijungimo duomen\u0173 delegavimas
+
+loginTotpStep1=\u012Ediekite <a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> arba Google Authenticator savo \u012Frenginyje. Program\u0117l\u0117s prieinamos <a href="https://play.google.com">Google Play</a> ir Apple App Store.
+loginTotpStep2=Atidarykite program\u0117l\u0119 ir nuskenuokite barkod\u0105 arba \u012Fveskite kod\u0105.
+loginTotpStep3=\u012Eveskite program\u0117l\u0117je sugeneruot\u0105 vien\u0105 kart\u0105 galiojant\u012F kod\u0105 ir paspauskite Saugoti nor\u0117dami prisijungti.
+loginTotpOneTime=Vienkartinis kodas
+
+oauthGrantRequest=Ar J\u016Bs suteikiate \u0161ias prieigos teises?
+inResource=\u012F
+
+emailVerifyInstruction1=El. pa\u0161tas su instrukcijomis ir patvirtinimo nuoroda nusi\u0173sti \u012F J\u016Bs\u0173 el. pa\u0161t\u0105.
+emailVerifyInstruction2=El. pa\u0161tu negavote patvirtinimo kodo?
+emailVerifyInstruction3=pakartotoinai si\u0173sti el. lai\u0161k\u0105.
+
+emailLinkIdpTitle=Susieti {0}
+emailLinkIdp1=El. pa\u0161to lai\u0161kas su instrukcijomis susieti {0} paskyr\u0105 {1} su {2} buvo nusi\u0173stas.
+emailLinkIdp2=Negavote patvirtinimo kodo el. pa\u0161tu?
+emailLinkIdp3=pakartotoinai si\u0173sti el. lai\u0161k\u0105.
+
+backToLogin=&laquo; Gr\u012F\u017Eti \u012F prisijungimo lang\u0105
+
+emailInstruction=\u012Eveskite naudotojo vard\u0105 arba slapta\u017Eod\u012F ir slapta\u017Eod\u017Eio pakeitimo instrukcijos bus atsi\u0173stos Jums el. pa\u0161tu 
+
+copyCodeInstruction=Nukopijuokite \u0161\u012F kod\u0105 \u012F J\u016Bs\u0173 program\u0105:
+
+personalInfo=Asmenin\u0117 informacija:
+role_admin=Administratorius
+role_realm-admin=Srities administravimas
+role_create-realm=Kurti srit\u012F
+role_create-client=Kurti program\u0105
+role_view-realm=Per\u017Ei\u016Br\u0117ti srit\u012F
+role_view-users=Per\u017Ei\u016Br\u0117ti naudotojus
+role_view-applications=Per\u017Ei\u016Br\u0117ti programas
+role_view-clients=Per\u017Ei\u016Br\u0117ti klientines programas
+role_view-events=Per\u017Ei\u016Br\u0117ti \u012Fvyki\u0173 \u017Eurnal\u0105
+role_view-identity-providers=Per\u017Ei\u016Br\u0117ti tapatyb\u0117s teik\u0117jus
+role_manage-realm=Valdyti sritis
+role_manage-users=Valdyti naudotojus
+role_manage-applications=Valdyti programas
+role_manage-identity-providers=Valdyti tapatyb\u0117s teik\u0117jus
+role_manage-clients=Valdyti programas
+role_manage-events=Valdyti \u012Fvykius
+role_view-profile=Per\u017Ei\u016Br\u0117ti paskyr\u0105
+role_manage-account=Valdyti paskyr\u0105
+role_read-token=Skaityti prieigos rak\u0161\u0105
+role_offline-access=Darbas neprisijungus
+client_account=Paskyra
+client_security-admin-console=Saugumo administravimo konsol\u0117
+client_admin-cli=Administravimo CLI
+client_realm-management=Srities valdymas
+client_broker=Tarpininkas
+
+invalidUserMessage=Neteisingas naudotojo vardas arba slapta\u017Eodis.
+invalidEmailMessage=Neteisingas el. pa\u0161to adresas.
+accountDisabledMessage=Paskyros galiojimas sustabdytas, kreipkit\u0117s \u012F administratori\u0173.
+accountTemporarilyDisabledMessage=Paskyros galiojimas laikinai sustabdytas. Kreipkit\u0117s \u012F administratori\u0173 arba pabandykite v\u0117liau.
+expiredCodeMessage=Prisijungimo laikas baig\u0117si. Bandykite dar kart\u0105.
+
+missingFirstNameMessage=Pra\u0161ome \u012Fvesti vard\u0105.
+missingLastNameMessage=Pra\u0161ome \u012Fvesti pavard\u0119.
+missingEmailMessage=Pra\u0161ome \u012Fvesti el. pa\u0161to adres\u0105.
+missingUsernameMessage=Pra\u0161ome \u012Fvesti naudotojo vard\u0105.
+missingPasswordMessage=Pra\u0161ome \u012Fvesti slapta\u017Eod\u012F.
+missingTotpMessage=Pra\u0161ome \u012Fvesti autentifikacijos kod\u0105.
+notMatchPasswordMessage=Slapta\u017Eod\u017Eiai nesutampa.
+
+invalidPasswordExistingMessage=Neteisingas dabartinis slapta\u017Eodis.
+invalidPasswordConfirmMessage=Pakartotas slapta\u017Eodis nesutampa.
+invalidTotpMessage=Neteisingas autentifikacijos kodas.
+
+usernameExistsMessage=Toks naudotojas jau egzistuoja.
+emailExistsMessage=El. pa\u0161to adresas jau egzistuoja.
+
+federatedIdentityExistsMessage=Naudotojas {0} {1} jau egzistuoja. Pra\u0161ome prsijungti prie naudotoj\u0173 valdymo posistem\u0117s paskyr\u0173 susiejimui.
+
+confirmLinkIdpTitle=Paskyra jau egzistuoja
+federatedIdentityConfirmLinkMessage=Naudotojas {0} {1} jau egzistuoja. Ar t\u0119sti?
+federatedIdentityConfirmReauthenticateMessage=Prisijunkite prie {0} nor\u0117dami susieti paskyr\u0105 su  {1}
+confirmLinkIdpReviewProfile=Per\u017Ei\u016Br\u0117ti naudotojo profilio informacij\u0105
+confirmLinkIdpContinue=Susieti su egzistuojan\u010Dia paskyra
+
+configureTotpMessage=Paskyros aktyvavimui Jums reikalingas Mobilus autentifikatorius.
+updateProfileMessage=Paskyros aktyvavimui Jums reikia atnaujinti profilio informacij\u0105.
+updatePasswordMessage=Paskyros aktyvavimui Jums reikia pakeisti slapta\u017Eod\u012F.
+verifyEmailMessage=Paskyros aktyvavimui Jums reikia patvirtinti el. pa\u0161to adres\u0105.
+linkIdpMessage=El. pa\u0161to adreso susiejimui su J\u016Bsu paskyra {0} reikalingas patvirtinimas.
+
+emailSentMessage=Netrukus tur\u0117tum\u0117te gauti el. pa\u0161to adres\u0105 su instrukcijomis.
+emailSendErrorMessage=Klaida siun\u010Diant el. pa\u0161t\u0105, bandykite v\u0117liau.
+
+accountUpdatedMessage=J\u0173s\u0173 paskyros informacija atnaujinta.
+accountPasswordUpdatedMessage=J\u016Bs\u0173 slapta\u017Eodis pakeistas.
+
+noAccessMessage=Prieiga negalima
+
+invalidPasswordMinLengthMessage=Neteisingas slapta\u017Eodis: privalomi bent {0} simboliai.
+invalidPasswordMinDigitsMessage=Neteisingas slapta\u017Eodis: privalomi bent {0} skaitmenys.
+invalidPasswordMinLowerCaseCharsMessage=Neteisingas slapta\u017Eodis: privalomos bent {0} ma\u017Eosios raid\u0117s.
+invalidPasswordMinUpperCaseCharsMessage=Neteisingas slapta\u017Eodis: privalomos bent {0} did\u017Eiosios raid\u0117s.
+invalidPasswordMinSpecialCharsMessage=Neteisingas slapta\u017Eodis: privalomi bent {0} special\u016Bs simboliai.
+invalidPasswordNotUsernameMessage=Neteisingas slapta\u017Eodis: negali sutapti su naudotojo vardu.
+invalidPasswordRegexPatternMessage=Neteisingas slapta\u017Eodis: neatitinka regexp taisykl\u0117s.
+invalidPasswordHistoryMessage=Neteisingas slapta\u017Eodis: negali sutapti su prie\u0161 tai naudotais {0} slapta\u017Eod\u017Eiais.
+
+failedToProcessResponseMessage=Klaida apdorojant atsakym\u0105
+httpsRequiredMessage=Privalomas HTTPS
+realmNotEnabledMessage=Srities galiojimas i\u0161jungtas
+invalidRequestMessage=Neteisinga u\u017Eklausa
+failedLogout=Nepavyko u\u017Ebaigti sesijos
+unknownLoginRequesterMessage=Ne\u017Einomas prisijungimo pra\u0161ytojas
+loginRequesterNotEnabledMessage=Prisijungimo pra\u0161ytojo galiojimas i\u0161jungtas
+bearerOnlyMessage=Programos, sukonfig\u016Bruotos tik kaip perdav\u0117jai, negali inicijuoti prisijungim\u0105 per nar\u0161ykl\u0119.
+standardFlowDisabledMessage=Su pateiktu atsakymo tipu prisijungimas per nar\u0161ykl\u0119 \u0161iam klientui negalimas. \u0160iam klientui ne\u012Fgalinta standartin\u0117 seka.
+implicitFlowDisabledMessage=Su pateiktu atsakymo tipu prisijungimas per nar\u0161ykl\u0119 \u0161iam klientui negalimas. \u0160iam klientui ne\u012Fgalinta i\u0161reik\u0161tin\u0117 seka.
+invalidRedirectUriMessage=Neteisinga nukreipimo nuoroda
+unsupportedNameIdFormatMessage=Nepalaikomas NameIDFormat
+invalidRequesterMessage=Neteisingas pra\u0161ytojas
+registrationNotAllowedMessage=Registracija negalima
+resetCredentialNotAllowedMessage=Prisijungimo duomen\u0173 atk\u016Brimas negalimas
+
+permissionNotApprovedMessage=Teis\u012F nepatvirtinta.
+noRelayStateInResponseMessage=Tapatyb\u0117s teik\u0117jo atsakyme tr\u016Bksta perdavimo b\u016Bsenos.
+insufficientPermissionMessage=Tr\u016Bksta teisi\u0173 tapatybi\u0173 susiejimui.
+couldNotProceedWithAuthenticationRequestMessage=Nepavyksta prad\u0117ti tapatyb\u0117s teik\u0117jo autentifikacijos u\u017Eklausos.
+couldNotObtainTokenMessage=Negaunamas prieigos raktas i\u0161 tapatyb\u0117s teik\u0117jo.
+unexpectedErrorRetrievingTokenMessage=Prieigos rak\u0161o gavimo i\u0161 tapatyb\u0117s teik\u0117jo metu \u012Fvyko netik\u0117ta klaida.
+unexpectedErrorHandlingResponseMessage=Tapatyb\u0117s teik\u0117jo atsakymo apdorojimo metu \u012Fvyko netik\u0117ta klaida.
+identityProviderAuthenticationFailedMessage=Autentifikacijos klaida. Nepavyksta autentifikacija su tapatyb\u0117s teik\u0117ju.
+identityProviderDifferentUserMessage=Autentifikuota kaip {0}, nors buvo tikimasi {1}
+couldNotSendAuthenticationRequestMessage=Tapatyb\u0117s teik\u0117jui nepavyksta nusi\u0173sti autentifikacijos u\u017Eklausos.
+unexpectedErrorHandlingRequestMessage=U\u017Eklausos tapatyb\u0117s teik\u0117jui formavimo metu \u012Fvyko netik\u0117ta klaida.
+invalidAccessCodeMessage=Neteisingas prieigos kodas.
+sessionNotActiveMessage=Sesija neaktyvi.
+invalidCodeMessage=\u012Evyko klaida. Pra\u0161ome bandyti prisijungti dar kart\u0105.
+identityProviderUnexpectedErrorMessage=Autentifikavimo su i\u0161oriniu tapatyb\u0117s teik\u0117ju metu \u012Fvyko netik\u0117ta klaida.
+identityProviderNotFoundMessage=Su nurodytu identifikatoriumi nerastas tapatyb\u0117s teik\u0117jas.
+identityProviderLinkSuccess=J\u016Bs\u0173 naudotojo paskyra buvo s\u0117kmingai susieta su {0} paskyra {1} .
+staleCodeMessage=\u0160is puslapis nebegalioja. Pra\u0161ome gr\u012F\u017Eti \u012F program\u0105 ir bandyti prisijungti i\u0161 naujo.
+realmSupportsNoCredentialsMessage=Sritis nepalaiko prisijungim\u0173 naudojant prisijungimo duomenis.
+identityProviderNotUniqueMessage=Sritis palaiko daugiau nei vien\u0105 tapatyb\u0117s teik\u0117j\u0105. Negalima nustatyti kuris tapatyb\u0117s teik\u0117jas turi b\u016Bti naudojamas autentifikacijai.
+emailVerifiedMessage=J\u016Bs\u0173 el. pa\u0161to adresas patvirtintas.
+staleEmailVerificationLink=Nuoroda, kuri\u0105 paspaud\u0117te nebegalioja? Galb\u016Bt J\u016Bs jau patvirtinote el. pa\u0161to adres\u0105?
+
+backToApplication=&laquo; Gr\u012F\u017Eti \u012F program\u0105
+missingParameterMessage=Nenurodytas parametras\: {0}
+clientNotFoundMessage=Nenurodytas klientas.
+clientDisabledMessage=Kliento galiojimas i\u0161jungtas.
+invalidParameterMessage=Neteisingas parametras\: {0}
+alreadyLoggedIn=J\u016Bs jau esate prisijung\u0119.
+
+p3pPolicy=CP="Nurodyta reik\u0161m\u0117 n\u0117ra P3P taisykl\u0117!"
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/login/theme.properties b/themes/src/main/resources/theme/base/login/theme.properties
index deb2dc9..2cf724d 100644
--- a/themes/src/main/resources/theme/base/login/theme.properties
+++ b/themes/src/main/resources/theme/base/login/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,ja,pt-BR,ru,no
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,lt,no,pt-BR,ru
\ No newline at end of file