keycloak-uncached

Details

diff --git a/audit/mongo/src/main/java/org/keycloak/audit/mongo/MongoAuditProviderFactory.java b/audit/mongo/src/main/java/org/keycloak/audit/mongo/MongoAuditProviderFactory.java
index 4ffcda1..09cb6fd 100644
--- a/audit/mongo/src/main/java/org/keycloak/audit/mongo/MongoAuditProviderFactory.java
+++ b/audit/mongo/src/main/java/org/keycloak/audit/mongo/MongoAuditProviderFactory.java
@@ -18,10 +18,6 @@ import java.util.Collections;
  */
 public class MongoAuditProviderFactory implements AuditProviderFactory {
 
-    private static final String MONGO_HOST = "keycloak.audit.mongo.host";
-    private static final String MONGO_PORT = "keycloak.audit.mongo.port";
-    private static final String MONGO_DB_NAME = "keycloak.audit.mongo.db";
-
     public static final String ID = "mongo";
     private MongoClient client;
     private DB db;
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 9c43eb6..68ba134 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -20,6 +20,7 @@ public class RealmRepresentation {
     protected Integer accessCodeLifespanUserAction;
     protected Boolean enabled;
     protected Boolean sslNotRequired;
+    protected Boolean passwordCredentialGrantAllowed;
     protected Boolean registrationAllowed;
     protected Boolean rememberMe;
     protected Boolean verifyEmail;
@@ -57,6 +58,7 @@ public class RealmRepresentation {
     protected String loginTheme;
     protected String accountTheme;
     protected String adminTheme;
+    protected String emailTheme;
     protected boolean auditEnabled;
     protected long auditExpiration;
     protected List<String> auditListeners;
@@ -241,6 +243,14 @@ public class RealmRepresentation {
         this.publicKey = publicKey;
     }
 
+    public Boolean isPasswordCredentialGrantAllowed() {
+        return passwordCredentialGrantAllowed;
+    }
+
+    public void setPasswordCredentialGrantAllowed(Boolean passwordCredentialGrantAllowed) {
+        this.passwordCredentialGrantAllowed = passwordCredentialGrantAllowed;
+    }
+
     public Boolean isRegistrationAllowed() {
         return registrationAllowed;
     }
@@ -377,6 +387,14 @@ public class RealmRepresentation {
         this.adminTheme = adminTheme;
     }
 
+    public String getEmailTheme() {
+        return emailTheme;
+    }
+
+    public void setEmailTheme(String emailTheme) {
+        this.emailTheme = emailTheme;
+    }
+
     public Integer getNotBefore() {
         return notBefore;
     }
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-detail.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-detail.html
index d2e60f5..089b190 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-detail.html
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-detail.html
@@ -67,6 +67,12 @@
                         </div>
                     </div>
                     <div class="form-group">
+                        <label for="passwordCredentialGrantAllowed" class="col-sm-2 control-label">Password Credential Grant</label>
+                        <div class="col-sm-4">
+                            <input ng-model="realm.passwordCredentialGrantAllowedpasswordCredentialGrantAllowed" name="passwordCredentialGrantAllowed" id="passwordCredentialGrantAllowed" onoffswitch />
+                        </div>
+                    </div>
+                    <div class="form-group">
                         <label for="requireSsl" class="col-sm-2 control-label">Require SSL</label>
                         <div class="col-sm-4">
                             <input ng-model="realm.requireSsl" name="requireSsl" id="requireSsl" onoffswitch />
@@ -111,6 +117,18 @@
                             </div>
                         </div>
                     </div>
+                    <div class="form-group">
+                        <label class="col-sm-2 control-label" for="emailTheme">Email Theme</label>
+                        <div class="col-sm-4">
+                            <div class="select-kc">
+                                <select id="emailTheme"
+                                        ng-model="realm.emailTheme"
+                                        ng-options="o as o for o in serverInfo.themes.email">
+                                    <option value="" disabled selected>Select one...</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
                 </fieldset>
 
                 <div class="pull-right form-actions" data-ng-show="createRealm && access.manageRealm">
diff --git a/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java b/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java
index 9590a9c..e4e8c52 100644
--- a/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java
+++ b/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java
@@ -68,7 +68,7 @@ public class FreeMarkerEmailProvider implements EmailProvider {
     private void send(String subjectKey, String template, Map<String, Object> attributes) throws EmailException {
         try {
             ExtendingThemeManager themeManager = new ExtendingThemeManager(session);
-            Theme theme = themeManager.createTheme(realm.getAccountTheme(), Theme.Type.EMAIL);
+            Theme theme = themeManager.createTheme(realm.getEmailTheme(), Theme.Type.EMAIL);
 
             String subject =  theme.getMessages().getProperty(subjectKey);
             String body = FreeMarkerUtil.processTemplate(attributes, template, theme);
diff --git a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
index d19ca09..f364503 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
@@ -16,6 +16,7 @@ public class RealmEntity extends AbstractIdentifiableEntity {
     private boolean registrationAllowed;
     private boolean rememberMe;
     private boolean verifyEmail;
+    private boolean passwordCredentialGrantAllowed;
     private boolean resetPasswordAllowed;
     private boolean social;
     private boolean updateProfileOnInitialSocialLogin;
@@ -43,6 +44,7 @@ public class RealmEntity extends AbstractIdentifiableEntity {
     private String loginTheme;
     private String accountTheme;
     private String adminTheme;
+    private String emailTheme;
 
     // We are using names of defaultRoles (not ids)
     private List<String> defaultRoles = new ArrayList<String>();
@@ -84,6 +86,14 @@ public class RealmEntity extends AbstractIdentifiableEntity {
         this.sslNotRequired = sslNotRequired;
     }
 
+    public boolean isPasswordCredentialGrantAllowed() {
+        return passwordCredentialGrantAllowed;
+    }
+
+    public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
+        this.passwordCredentialGrantAllowed = passwordCredentialGrantAllowed;
+    }
+
     public boolean isRegistrationAllowed() {
         return registrationAllowed;
     }
@@ -284,6 +294,14 @@ public class RealmEntity extends AbstractIdentifiableEntity {
         this.adminTheme = adminTheme;
     }
 
+    public String getEmailTheme() {
+        return emailTheme;
+    }
+
+    public void setEmailTheme(String emailTheme) {
+        this.emailTheme = emailTheme;
+    }
+
     public List<String> getDefaultRoles() {
         return defaultRoles;
     }
diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java
index 68a89ea..c2ec9f3 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -29,6 +29,11 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
     boolean isRegistrationAllowed();
 
     void setRegistrationAllowed(boolean registrationAllowed);
+
+    boolean isPasswordCredentialGrantAllowed();
+
+    void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed);
+
     boolean isRememberMe();
 
     void setRememberMe(boolean rememberMe);
@@ -222,6 +227,10 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
 
     void setAdminTheme(String name);
 
+    String getEmailTheme();
+
+    void setEmailTheme(String name);
+
     boolean hasScope(ClientModel client, RoleModel role);
 
     /**
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
index c5bf40c..62804eb 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
@@ -41,6 +41,7 @@ public class RealmEntity {
     protected boolean enabled;
     protected boolean sslNotRequired;
     protected boolean registrationAllowed;
+    protected boolean passwordCredentialGrantAllowed;
     protected boolean verifyEmail;
     protected boolean resetPasswordAllowed;
     protected boolean social;
@@ -75,6 +76,7 @@ public class RealmEntity {
     protected String loginTheme;
     protected String accountTheme;
     protected String adminTheme;
+    protected String emailTheme;
 
     @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
     @JoinTable(name="User_RequiredCreds")
@@ -153,6 +155,14 @@ public class RealmEntity {
         this.sslNotRequired = sslNotRequired;
     }
 
+    public boolean isPasswordCredentialGrantAllowed() {
+        return passwordCredentialGrantAllowed;
+    }
+
+    public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
+        this.passwordCredentialGrantAllowed = passwordCredentialGrantAllowed;
+    }
+
     public boolean isRegistrationAllowed() {
         return registrationAllowed;
     }
@@ -360,6 +370,14 @@ public class RealmEntity {
         this.adminTheme = adminTheme;
     }
 
+    public String getEmailTheme() {
+        return emailTheme;
+    }
+
+    public void setEmailTheme(String emailTheme) {
+        this.emailTheme = emailTheme;
+    }
+
     public int getNotBefore() {
         return notBefore;
     }
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 b3eb12f..339a270 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
@@ -115,6 +115,17 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public boolean isPasswordCredentialGrantAllowed() {
+        return realm.isPasswordCredentialGrantAllowed();
+    }
+
+    @Override
+    public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
+        realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
+        em.flush();
+    }
+
+    @Override
     public boolean isRegistrationAllowed() {
         return realm.isRegistrationAllowed();
     }
@@ -1352,6 +1363,17 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public String getEmailTheme() {
+        return realm.getEmailTheme();
+    }
+
+    @Override
+    public void setEmailTheme(String name) {
+        realm.setEmailTheme(name);
+        em.flush();
+    }
+
+    @Override
     public boolean isAuditEnabled() {
         return realm.isAuditEnabled();
     }
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 f7e82ec..da01022 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
@@ -109,6 +109,17 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     }
 
     @Override
+    public boolean isPasswordCredentialGrantAllowed() {
+        return realm.isPasswordCredentialGrantAllowed();
+    }
+
+    @Override
+    public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
+        realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
+        updateRealm();
+    }
+
+    @Override
     public boolean isRegistrationAllowed() {
         return realm.isRegistrationAllowed();
     }
@@ -421,6 +432,17 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     }
 
     @Override
+    public String getEmailTheme() {
+        return realm.getEmailTheme();
+    }
+
+    @Override
+    public void setEmailTheme(String name) {
+        realm.setEmailTheme(name);
+        updateRealm();
+    }
+
+    @Override
     public UserAdapter getUser(String name) {
         DBObject query = new QueryBuilder()
                 .and("loginName").is(name)
diff --git a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
index 1f4665c..49ca015 100755
--- a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
+++ b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
@@ -81,6 +81,7 @@ public class ModelToRepresentation {
         rep.setSslNotRequired(realm.isSslNotRequired());
         rep.setPublicKey(realm.getPublicKeyPem());
         rep.setPrivateKey(realm.getPrivateKeyPem());
+        rep.setPasswordCredentialGrantAllowed(realm.isPasswordCredentialGrantAllowed());
         rep.setRegistrationAllowed(realm.isRegistrationAllowed());
         rep.setRememberMe(realm.isRememberMe());
         rep.setBruteForceProtected(realm.isBruteForceProtected());
@@ -103,6 +104,7 @@ public class ModelToRepresentation {
         rep.setAccountTheme(realm.getAccountTheme());
         rep.setLoginTheme(realm.getLoginTheme());
         rep.setAdminTheme(realm.getAdminTheme());
+        rep.setEmailTheme(realm.getEmailTheme());
         if (realm.getPasswordPolicy() != null) {
             rep.setPasswordPolicy(realm.getPasswordPolicy().toString());
         }
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 15648c8..1543087 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -174,6 +174,7 @@ public class RealmManager {
         if (rep.getQuickLoginCheckMilliSeconds() != null) realm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
         if (rep.getMaxDeltaTimeSeconds() != null) realm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
         if (rep.getFailureFactor() != null) realm.setFailureFactor(rep.getFailureFactor());
+        if (rep.isPasswordCredentialGrantAllowed() != null) realm.setPasswordCredentialGrantAllowed(rep.isPasswordCredentialGrantAllowed());
         if (rep.isRegistrationAllowed() != null) realm.setRegistrationAllowed(rep.isRegistrationAllowed());
         if (rep.isRememberMe() != null) realm.setRememberMe(rep.isRememberMe());
         if (rep.isVerifyEmail() != null) realm.setVerifyEmail(rep.isVerifyEmail());
@@ -194,6 +195,7 @@ public class RealmManager {
         if (rep.getLoginTheme() != null) realm.setLoginTheme(rep.getLoginTheme());
         if (rep.getAccountTheme() != null) realm.setAccountTheme(rep.getAccountTheme());
         if (rep.getAdminTheme() != null) realm.setAdminTheme(rep.getAdminTheme());
+        if (rep.getEmailTheme() != null) realm.setEmailTheme(rep.getEmailTheme());
 
         if (rep.getPasswordPolicy() != null) realm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
 
@@ -330,6 +332,7 @@ public class RealmManager {
         else newRealm.setAccessCodeLifespanUserAction(300);
 
         if (rep.isSslNotRequired() != null) newRealm.setSslNotRequired(rep.isSslNotRequired());
+        if (rep.isPasswordCredentialGrantAllowed() != null) newRealm.setPasswordCredentialGrantAllowed(rep.isPasswordCredentialGrantAllowed());
         if (rep.isRegistrationAllowed() != null) newRealm.setRegistrationAllowed(rep.isRegistrationAllowed());
         if (rep.isRememberMe() != null) newRealm.setRememberMe(rep.isRememberMe());
         if (rep.isVerifyEmail() != null) newRealm.setVerifyEmail(rep.isVerifyEmail());
@@ -344,7 +347,8 @@ public class RealmManager {
         }
         if (rep.getLoginTheme() != null) newRealm.setLoginTheme(rep.getLoginTheme());
         if (rep.getAccountTheme() != null) newRealm.setAccountTheme(rep.getAccountTheme());
-        if (rep.getAdminTheme() != null) newRealm.setAdminTheme(rep.getAccountTheme());
+        if (rep.getAdminTheme() != null) newRealm.setAdminTheme(rep.getAdminTheme());
+        if (rep.getEmailTheme() != null) newRealm.setEmailTheme(rep.getEmailTheme());
 
         Map<String, UserModel> userMap = new HashMap<String, UserModel>();
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
index b617266..028f198 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
@@ -37,11 +37,11 @@ public class ServerInfoAdminResource {
     }
 
     private void setThemes(ServerInfoRepresentation info) {
-        Iterable<ThemeProvider> providers = ProviderLoader.load(ThemeProvider.class);
+        Set<ThemeProvider> themeProviders = providers.getAllProviders(ThemeProvider.class);
         info.themes = new HashMap<String, List<String>>();
         for (Theme.Type type : Theme.Type.values()) {
             List<String> themes = new LinkedList<String>();
-            for (ThemeProvider p : providers) {
+            for (ThemeProvider p : themeProviders) {
                 themes.addAll(p.nameSet(type));
             }
             Collections.sort(themes);
diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java
index 1d92234..77e470a 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -205,7 +205,11 @@ public class TokenService {
     public Response grantAccessToken(final @HeaderParam(HttpHeaders.AUTHORIZATION) String authorizationHeader,
                                      final MultivaluedMap<String, String> form) {
         if (!checkSsl()) {
-            throw new NotAcceptableException("HTTPS required");
+            return createError("https_required", "HTTPS required", Response.Status.FORBIDDEN);
+        }
+
+        if (!realm.isPasswordCredentialGrantAllowed()) {
+            return createError("not_enabled", "Resource Owner Password Credentials Grant not enabled", Response.Status.FORBIDDEN);
         }
 
         audit.event(Events.LOGIN).detail(Details.AUTH_METHOD, "oauth_credentials").detail(Details.RESPONSE_TYPE, "token");
@@ -224,12 +228,12 @@ public class TokenService {
 
         if ( (client instanceof ApplicationModel) && ((ApplicationModel)client).isBearerOnly()) {
             audit.error(Errors.NOT_ALLOWED);
-            throw new ForbiddenException("Bearer-only applications are not allowed to invoke grants/access");
+            return createError("not_allowed", "Bearer-only applications are not allowed to invoke grants/access", Response.Status.FORBIDDEN);
         }
 
         if (!realm.isEnabled()) {
             audit.error(Errors.REALM_DISABLED);
-            throw new UnauthorizedException("Disabled realm");
+            return createError("realm_disabled", "Realm is disabled", Response.Status.UNAUTHORIZED);
         }
 
         AuthenticationStatus authenticationStatus = authManager.authenticateForm(clientConnection, realm, form);
@@ -1014,4 +1018,13 @@ public class TokenService {
         return realm.isSslNotRequired() || uriInfo.getBaseUri().getScheme().equals("https");
     }
 
+    private Response createError(String error, String errorDescription, Response.Status status) {
+        Map<String, String> e = new HashMap<String, String>();
+        e.put(OAuth2Constants.ERROR, error);
+        if (errorDescription != null) {
+            e.put(OAuth2Constants.ERROR_DESCRIPTION, errorDescription);
+        }
+        return Response.status(status).entity(e).type("application/json").build();
+    }
+
 }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java
index 15a3f23..282bf5b 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java
@@ -1,21 +1,11 @@
 package org.keycloak.testsuite.oauth;
 
-import net.iharder.Base64;
 import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.message.BasicNameValuePair;
-import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
-import org.keycloak.OAuth2Constants;
 import org.keycloak.audit.Details;
 import org.keycloak.audit.Errors;
-import org.keycloak.audit.Event;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.representations.AccessToken;
@@ -28,11 +18,6 @@ import org.keycloak.testsuite.rule.WebResource;
 import org.keycloak.testsuite.rule.WebRule;
 import org.openqa.selenium.WebDriver;
 
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.LinkedList;
-import java.util.List;
-
 import static org.junit.Assert.assertEquals;
 
 /**
@@ -46,6 +31,7 @@ public class ResourceOwnerPasswordCredentialsGrantTest {
         public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
             ApplicationModel app = appRealm.addApplication("resource-owner");
             app.setSecret("secret");
+            appRealm.setPasswordCredentialGrantAllowed(true);
         }
     });
 
@@ -97,6 +83,33 @@ public class ResourceOwnerPasswordCredentialsGrantTest {
     }
 
     @Test
+    public void grantAccessTokenNotEnabled() throws Exception {
+        try {
+            keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
+                @Override
+                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                    appRealm.setPasswordCredentialGrantAllowed(false);
+                }
+            });
+
+            oauth.clientId("resource-owner");
+
+            OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("secret", "test-user@localhost", "password");
+
+            assertEquals(403, response.getStatusCode());
+            assertEquals("not_enabled", response.getError());
+
+        } finally {
+            keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
+                @Override
+                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                    appRealm.setPasswordCredentialGrantAllowed(true);
+                }
+            });
+        }
+    }
+
+    @Test
     public void grantAccessTokenLogout() throws Exception {
         oauth.clientId("resource-owner");
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
index 77bd97e..1a4bf74 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
@@ -404,7 +404,8 @@ public class OAuthClient {
                 Assert.fail("Invalid content type");
             }
 
-            JSONObject responseJson = new JSONObject(IOUtils.toString(response.getEntity().getContent()));
+            String s = IOUtils.toString(response.getEntity().getContent());
+            JSONObject responseJson = new JSONObject(s);
 
             if (statusCode == 200) {
                 accessToken = responseJson.getString("access_token");