keycloak-memoizeit

Added support for default application roles. Added authz to

11/4/2013 3:21:46 PM

Changes

Details

diff --git a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
index 878092e..59347ca 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
@@ -18,6 +18,7 @@ public class ApplicationRepresentation {
     protected boolean enabled;
     protected List<CredentialRepresentation> credentials;
     protected List<RoleRepresentation> roles;
+    protected String[] defaultRoles;
     protected List<UserRoleMappingRepresentation> roleMappings;
     protected List<ScopeMappingRepresentation> scopeMappings;
     protected List<String> redirectUris;
@@ -164,4 +165,12 @@ public class ApplicationRepresentation {
     public void setWebOrigins(List<String> webOrigins) {
         this.webOrigins = webOrigins;
     }
+
+    public String[] getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(String[] defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
 }
diff --git a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java b/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
index 05dedaf..9a346f2 100755
--- a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ApplicationModel.java
@@ -34,4 +34,9 @@ public interface ApplicationModel extends RoleContainerModel, RoleMapperModel, S
 
     void setBaseUrl(String url);
 
+    List<String> getDefaultRoles();
+
+    void addDefaultRole(String name);
+
+    void updateDefaultRoles(String[] defaultRoles);
 }
diff --git a/model/api/src/main/java/org/keycloak/models/Constants.java b/model/api/src/main/java/org/keycloak/models/Constants.java
index 57002e5..18adf63 100755
--- a/model/api/src/main/java/org/keycloak/models/Constants.java
+++ b/model/api/src/main/java/org/keycloak/models/Constants.java
@@ -13,6 +13,6 @@ public interface Constants {
     String WILDCARD_ROLE = "*";
 
     String ACCOUNT_APPLICATION = "Account";
-    String ACCOUNT_PROFILE_ROLE = "KEYCLOAK_ACCOUNT_PROFILE";
-    String ACCOUNT_MANAGE_ROLE = "KEYCLOAK_ACCOUNT_MANAGE";
+    String ACCOUNT_PROFILE_ROLE = "view-profile";
+    String ACCOUNT_MANAGE_ROLE = "manage-account";
 }
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 5c1b468..2de3e58 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -85,7 +85,7 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
 
     UserModel addUser(String username);
 
-    List<RoleModel> getDefaultRoles();
+    List<String> getDefaultRoles();
     
     void addDefaultRole(String name);
     
diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/ApplicationAdapter.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/ApplicationAdapter.java
index 8ad09eb..436b23c 100755
--- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/ApplicationAdapter.java
+++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/ApplicationAdapter.java
@@ -15,10 +15,7 @@ import org.picketlink.idm.model.sample.SampleModel;
 import org.picketlink.idm.query.IdentityQuery;
 import org.picketlink.idm.query.RelationshipQuery;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -257,4 +254,44 @@ public class ApplicationAdapter implements ApplicationModel {
         return roles;
     }
 
+    @Override
+    public List<String> getDefaultRoles() {
+        if ( applicationData.getDefaultRoles() != null) {
+            return Arrays.asList(applicationData.getDefaultRoles());
+        }
+        else {
+            return Collections.emptyList();
+        }
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        if (getRole(name) == null) {
+            addRole(name);
+        }
+
+        String[] defaultRoles = applicationData.getDefaultRoles();
+        if (defaultRoles == null) {
+            defaultRoles = new String[1];
+        } else {
+            defaultRoles = Arrays.copyOf(defaultRoles, defaultRoles.length + 1);
+        }
+        defaultRoles[defaultRoles.length - 1] = name;
+
+        applicationData.setDefaultRoles(defaultRoles);
+        updateApplication();
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        for (String name : defaultRoles) {
+            if (getRole(name) == null) {
+                addRole(name);
+            }
+        }
+
+        applicationData.setDefaultRoles(defaultRoles);
+        updateApplication();
+    }
+
 }
diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationData.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationData.java
index 8d5594a..5ce4aca 100755
--- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationData.java
+++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationData.java
@@ -15,6 +15,7 @@ public class ApplicationData extends AbstractPartition {
     private String managementUrl;
     private String baseUrl;
     private User resourceUser;
+    private String[] defaultRoles;
 
     public ApplicationData() {
         super(null);
@@ -76,4 +77,13 @@ public class ApplicationData extends AbstractPartition {
         this.baseUrl = baseUrl;
     }
 
+    @AttributeProperty
+    public String[] getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(String[] defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
+
 }
diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationEntity.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationEntity.java
index 0eddf7e..0e8d23b 100755
--- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationEntity.java
+++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/mappings/ApplicationEntity.java
@@ -34,6 +34,9 @@ public class ApplicationEntity implements Serializable {
     @AttributeValue
     private String baseUrl;
 
+    @AttributeValue
+    private String[] defaultRoles;
+
     @OneToOne
     @AttributeValue
     AccountTypeEntity resourceUser;
@@ -94,4 +97,13 @@ public class ApplicationEntity implements Serializable {
     public void setResourceUser(AccountTypeEntity resourceUser) {
         this.resourceUser = resourceUser;
     }
+
+    public String[] getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(String[] defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
+
 }
diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java
index d3268d2..58c44b4 100755
--- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java
+++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java
@@ -29,13 +29,7 @@ import java.io.StringWriter;
 import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * Meant to be a per-request object
@@ -754,17 +748,13 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public List<RoleModel> getDefaultRoles() {
-        List<RoleModel> defaultRoleModels = new ArrayList<RoleModel>();
+    public List<String> getDefaultRoles() {
         if (realm.getDefaultRoles() != null) {
-            for (String name : realm.getDefaultRoles()) {
-                RoleAdapter role = getRole(name);
-                if (role != null) {
-                    defaultRoleModels.add(role);
-                }
-            }
+            return Arrays.asList(realm.getDefaultRoles());
+        }
+        else {
+            return Collections.emptyList();
         }
-        return defaultRoleModels;
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
index 886f0dc..fc854a3 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
@@ -61,6 +61,11 @@ public class ApplicationManager {
                 if (roleRep.getDescription() != null) role.setDescription(roleRep.getDescription());
             }
         }
+
+        if (resourceRep.getDefaultRoles() != null) {
+            applicationModel.updateDefaultRoles(resourceRep.getDefaultRoles());
+        }
+
         if (resourceRep.getRoleMappings() != null) {
             for (UserRoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
                 UserModel user = realm.getUser(mapping.getUsername());
@@ -102,6 +107,10 @@ public class ApplicationManager {
         resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
         resource.updateApplication();
 
+        if (rep.getDefaultRoles() != null) {
+            resource.updateDefaultRoles(rep.getDefaultRoles());
+        }
+
         List<String> redirectUris = rep.getRedirectUris();
         if (redirectUris != null) {
             resource.getApplicationUser().setRedirectUris(new HashSet<String>(redirectUris));
@@ -132,6 +141,10 @@ public class ApplicationManager {
             rep.setWebOrigins(new LinkedList<String>(webOrigins));
         }
 
+        if (!applicationModel.getDefaultRoles().isEmpty()) {
+            rep.setDefaultRoles((String[]) applicationModel.getDefaultRoles().toArray());
+        }
+
         return rep;
 
     }
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 52f88f1..017a08c 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -110,8 +110,8 @@ public class RealmManager {
         ApplicationModel application = realm.getApplicationById(Constants.ACCOUNT_APPLICATION);
         if (application == null) {
             application = realm.addApplication(Constants.ACCOUNT_APPLICATION);
-            application.addRole(Constants.ACCOUNT_PROFILE_ROLE);
-            application.addRole(Constants.ACCOUNT_MANAGE_ROLE);
+            application.addDefaultRole(Constants.ACCOUNT_PROFILE_ROLE);
+            application.addDefaultRole(Constants.ACCOUNT_MANAGE_ROLE);
 
             UserCredentialModel password = new UserCredentialModel();
             password.setType(UserCredentialModel.PASSWORD);
@@ -429,13 +429,9 @@ public class RealmManager {
         ApplicationModel accountManagementApplication = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
         rep.setAccountManagement(accountManagementApplication != null && accountManagementApplication.isEnabled());
 
-        List<RoleModel> defaultRoles = realm.getDefaultRoles();
-        if (defaultRoles.size() > 0) {
-            String[] d = new String[defaultRoles.size()];
-            for (int i = 0; i < d.length; i++) {
-                d[i] = defaultRoles.get(i).getName();
-            }
-            rep.setDefaultRoles(d);
+        List<String> defaultRoles = realm.getDefaultRoles();
+        if (!defaultRoles.isEmpty()) {
+            rep.setDefaultRoles((String[]) realm.getDefaultRoles().toArray());
         }
 
         List<RequiredCredentialModel> requiredCredentialModels = realm.getRequiredCredentials();
diff --git a/services/src/main/java/org/keycloak/services/managers/TokenManager.java b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
index 4b6f79e..e7cb2ff 100755
--- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
@@ -45,6 +45,7 @@ public class TokenManager {
         List<RoleModel> realmRolesRequested = code.getRealmRolesRequested();
         MultivaluedMap<String, RoleModel> resourceRolesRequested = code.getResourceRolesRequested();
         Set<String> realmMapping = realm.getRoleMappingValues(user);
+        realmMapping.addAll(realm.getDefaultRoles());
 
         if (realmMapping != null && realmMapping.size() > 0 && (scopeMap == null || scopeMap.containsKey("realm"))) {
             Set<String> scope = realm.getScopeMappingValues(client);
@@ -68,6 +69,8 @@ public class TokenManager {
         }
         for (ApplicationModel resource : realm.getApplications()) {
             Set<String> mapping = resource.getRoleMappingValues(user);
+            mapping.addAll(resource.getDefaultRoles());
+
             if (mapping != null && mapping.size() > 0 && (scopeMap == null || scopeMap.containsKey(resource.getName()))) {
                 Set<String> scope = resource.getScopeMappingValues(client);
                 if (scope.size() > 0) {
@@ -185,6 +188,7 @@ public class TokenManager {
         }
 
         Set<String> realmMapping = realm.getRoleMappingValues(user);
+        realmMapping.addAll(realm.getDefaultRoles());
 
         if (realmMapping != null && realmMapping.size() > 0) {
             SkeletonKeyToken.Access access = new SkeletonKeyToken.Access();
@@ -196,6 +200,8 @@ public class TokenManager {
         if (resources != null) {
             for (ApplicationModel resource : resources) {
                 Set<String> mapping = resource.getRoleMappingValues(user);
+                mapping.addAll(resource.getDefaultRoles());
+
                 if (mapping == null) continue;
                 SkeletonKeyToken.Access access = token.addAccess(resource.getName())
                         .verifyCaller(resource.isSurrogateAuthRequired());
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 2abcf99..799b101 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -21,13 +21,6 @@
  */
 package org.keycloak.services.resources;
 
-import java.net.URI;
-import java.util.List;
-
-import javax.ws.rs.*;
-import javax.ws.rs.core.*;
-import javax.ws.rs.ext.Providers;
-
 import org.jboss.resteasy.jose.jws.JWSInput;
 import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
 import org.jboss.resteasy.logging.Logger;
@@ -49,6 +42,12 @@ import org.keycloak.services.resources.flows.Urls;
 import org.keycloak.services.validation.Validation;
 import org.picketlink.idm.credential.util.TimeBasedOTP;
 
+import javax.ws.rs.*;
+import javax.ws.rs.core.*;
+import javax.ws.rs.ext.Providers;
+import java.net.URI;
+import java.util.List;
+
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
@@ -87,12 +86,19 @@ public class AccountService {
     private Response forwardToPage(String path, String template) {
         AuthenticationManager.Auth auth = getAuth(false);
         if (auth != null) {
+            if (!hasAccess(auth)) {
+                return noAccess();
+            }
             return Flows.forms(realm, request, uriInfo).setUser(auth.getUser()).forwardToForm(template);
         } else {
             return login(path);
         }
     }
 
+    private Response noAccess() {
+        return Flows.forms(realm, request, uriInfo).setError("No access").forwardToErrorPage();
+    }
+
     @Path("/")
     @OPTIONS
     public Response accountPreflight() {
@@ -108,9 +114,8 @@ public class AccountService {
         } else if (types.contains(MediaType.APPLICATION_JSON_TYPE)) {
             AuthenticationManager.Auth auth = getAuth(true);
             if (!hasAccess(auth, Constants.ACCOUNT_PROFILE_ROLE)) {
-                throw new ForbiddenException();
+                return Response.status(Response.Status.FORBIDDEN).build();
             }
-
             return Cors.add(request, Response.ok(RealmManager.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getClient()).build();
         } else {
             return Response.notAcceptable(Variant.VariantListBuilder.newInstance().mediaTypes(MediaType.TEXT_HTML_TYPE, MediaType.APPLICATION_JSON_TYPE).build()).build();
@@ -146,6 +151,10 @@ public class AccountService {
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response processAccountUpdate(final MultivaluedMap<String, String> formData) {
         AuthenticationManager.Auth auth = getAuth(true);
+        if (!hasAccess(auth)) {
+            return noAccess();
+        }
+
         UserModel user = auth.getUser();
 
         String error = Validation.validateUpdateProfileForm(formData);
@@ -165,6 +174,10 @@ public class AccountService {
     @GET
     public Response processTotpRemove() {
         AuthenticationManager.Auth auth = getAuth(true);
+        if (!hasAccess(auth)) {
+            return noAccess();
+        }
+
         UserModel user = auth.getUser();
 
         user.setTotp(false);
@@ -177,6 +190,10 @@ public class AccountService {
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response processTotpUpdate(final MultivaluedMap<String, String> formData) {
         AuthenticationManager.Auth auth = getAuth(true);
+        if (!hasAccess(auth)) {
+            return noAccess();
+        }
+
         UserModel user = auth.getUser();
 
         String totp = formData.getFirst("totp");
@@ -205,6 +222,10 @@ public class AccountService {
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) {
         AuthenticationManager.Auth auth = getAuth(true);
+        if (!hasAccess(auth)) {
+            return noAccess();
+        }
+
         UserModel user = auth.getUser();
 
         FormFlows forms = Flows.forms(realm, request, uriInfo).setUser(user);
@@ -336,30 +357,30 @@ public class AccountService {
         return oauth.redirect(uriInfo, accountUri.toString(), path);
     }
 
-    private AuthenticationManager.Auth getAuth(boolean required) {
+    private AuthenticationManager.Auth getAuth(boolean error) {
         AuthenticationManager.Auth auth = authManager.authenticateAccountIdentity(realm, uriInfo, headers);
-        if (auth == null && required) {
+        if (auth == null && error) {
             throw new ForbiddenException();
         }
         return auth;
     }
 
-    private boolean hasAccess(AuthenticationManager.Auth auth, String requiredRole) {
-        UserModel client = auth.getClient();
+    private boolean hasAccess(AuthenticationManager.Auth auth) {
+        return hasAccess(auth, null);
+    }
 
+    private boolean hasAccess(AuthenticationManager.Auth auth, String role) {
+        UserModel client = auth.getClient();
         if (realm.hasRole(client, Constants.APPLICATION_ROLE)) {
-            return true;
-        }
-
-        SkeletonKeyToken token = auth.getToken();
-        SkeletonKeyToken.Access access = token.getResourceAccess(application.getName());
-
-        if (access != null) {
-            if (access.isUserInRole(Constants.ACCOUNT_MANAGE_ROLE)) {
+            // Tokens from cookies don't have roles
+            if (hasRole(client, Constants.ACCOUNT_MANAGE_ROLE) || (role != null && hasRole(client, role))) {
                 return true;
             }
+        }
 
-            if (access.isUserInRole(Constants.ACCOUNT_PROFILE_ROLE)) {
+        SkeletonKeyToken.Access access = auth.getToken().getResourceAccess(application.getName());
+        if (access != null) {
+            if (access.isUserInRole(Constants.ACCOUNT_MANAGE_ROLE) || (role != null && access.isUserInRole(role))) {
                 return true;
             }
         }
@@ -367,4 +388,11 @@ public class AccountService {
         return false;
     }
 
+    private boolean hasRole(UserModel user, String role) {
+        if (application.getDefaultRoles().contains(role)) {
+            return true;
+        }
+        return application.hasRole(user, role);
+    }
+
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/SocialResource.java b/services/src/main/java/org/keycloak/services/resources/SocialResource.java
index 4a2ab82..573da77 100755
--- a/services/src/main/java/org/keycloak/services/resources/SocialResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/SocialResource.java
@@ -176,10 +176,6 @@ public class SocialResource {
                 }
 
                 realm.addSocialLink(user, socialLink);
-
-                for (RoleModel role : realm.getDefaultRoles()) {
-                    realm.grantRole(user, role);
-                }
             }  else {
                 // Redirect user to registration screen with prefilled data from social provider
                 MultivaluedMap<String, String> formData = fillRegistrationFormWithSocialData(socialUser);
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 7388b61..c825004 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -309,10 +309,6 @@ public class TokenService {
             realm.updateCredential(user, credentials);
         }
 
-        for (RoleModel role : realm.getDefaultRoles()) {
-            realm.grantRole(user, role);
-        }
-
         return null;
     }
 
diff --git a/services/src/test/java/org/keycloak/test/AdapterTest.java b/services/src/test/java/org/keycloak/test/AdapterTest.java
index 22c38b3..d6b178a 100755
--- a/services/src/test/java/org/keycloak/test/AdapterTest.java
+++ b/services/src/test/java/org/keycloak/test/AdapterTest.java
@@ -73,7 +73,7 @@ public class AdapterTest extends AbstractKeycloakTest {
         Assert.assertEquals(realmModel.getPublicKeyPem(), "0234234");
         Assert.assertEquals(realmModel.isAutomaticRegistrationAfterSocialLogin(), true);
         Assert.assertEquals(1, realmModel.getDefaultRoles().size());
-        Assert.assertEquals("foo", realmModel.getDefaultRoles().get(0).getName());
+        Assert.assertEquals("foo", realmModel.getDefaultRoles().get(0));
     }
 
     @Test
@@ -102,7 +102,7 @@ public class AdapterTest extends AbstractKeycloakTest {
         Assert.assertEquals(realmModel.getPublicKeyPem(), "0234234");
         Assert.assertEquals(realmModel.isAutomaticRegistrationAfterSocialLogin(), true);
         Assert.assertEquals(1, realmModel.getDefaultRoles().size());
-        Assert.assertEquals("foo", realmModel.getDefaultRoles().get(0).getName());
+        Assert.assertEquals("foo", realmModel.getDefaultRoles().get(0));
 
         String id = realmModel.getId();
         System.out.println("id: " + id);
diff --git a/services/src/test/java/org/keycloak/test/ApplicationModelTest.java b/services/src/test/java/org/keycloak/test/ApplicationModelTest.java
index 57c3ba5..5d0de1a 100644
--- a/services/src/test/java/org/keycloak/test/ApplicationModelTest.java
+++ b/services/src/test/java/org/keycloak/test/ApplicationModelTest.java
@@ -42,6 +42,8 @@ public class ApplicationModelTest extends AbstractKeycloakServerTest {
         application.setName("app-name");
         application.addRole("role-1");
         application.addRole("role-2");
+        application.addDefaultRole("role-1");
+        application.addDefaultRole("role-2");
 
         application.getApplicationUser().addRedirectUri("redirect-1");
         application.getApplicationUser().addRedirectUri("redirect-2");
@@ -80,6 +82,7 @@ public class ApplicationModelTest extends AbstractKeycloakServerTest {
         Assert.assertEquals(expected.getName(), actual.getName());
         Assert.assertEquals(expected.getBaseUrl(), actual.getBaseUrl());
         Assert.assertEquals(expected.getManagementUrl(), actual.getManagementUrl());
+        Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles());
 
         UserModel auser = actual.getApplicationUser();
         UserModel euser = expected.getApplicationUser();
diff --git a/services/src/test/java/org/keycloak/test/ModelTest.java b/services/src/test/java/org/keycloak/test/ModelTest.java
index 9f9400c..9b244be 100755
--- a/services/src/test/java/org/keycloak/test/ModelTest.java
+++ b/services/src/test/java/org/keycloak/test/ModelTest.java
@@ -86,7 +86,7 @@ public class ModelTest extends AbstractKeycloakServerTest {
         Assert.assertEquals(expected.getPublicKeyPem(), actual.getPublicKeyPem());
         Assert.assertEquals(expected.getPrivateKeyPem(), actual.getPrivateKeyPem());
 
-        assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles());
+        Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles());
 
         Assert.assertEquals(expected.getSmtpConfig(), actual.getSmtpConfig());
         Assert.assertEquals(expected.getSocialConfig(), actual.getSocialConfig());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
index cc5144d..9891af0 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
@@ -29,6 +29,8 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.UriBuilder;
 import java.io.IOException;
 import java.net.URI;
+import java.util.Collections;
+import java.util.List;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -51,17 +53,13 @@ public class ProfileTest {
 
             ApplicationModel accountApp = appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_APPLICATION);
 
-            accountApp.grantRole(user, accountApp.getRole(org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE));
-            accountApp.grantRole(user, accountApp.getRole(org.keycloak.models.Constants.ACCOUNT_MANAGE_ROLE));
+            ApplicationModel app = appRealm.getApplicationNameMap().get("test-app");
+            accountApp.addScopeMapping(app.getApplicationUser(), org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE);
+
+            app.getApplicationUser().addWebOrigin("http://localtest.me:8081");
 
             UserModel thirdParty = appRealm.getUser("third-party");
             accountApp.addScopeMapping(thirdParty, org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE);
-
-            for (ApplicationModel app : appRealm.getApplications()) {
-                if (app.getName().equals("test-app")) {
-                    app.getApplicationUser().addWebOrigin("http://localtest.me:8081");
-                }
-            }
         }
     });
 
@@ -83,6 +81,8 @@ public class ProfileTest {
     @WebResource
     protected OAuthGrantPage grantPage;
 
+    private List<String> defaultRoles;
+
     @Test
     public void getProfile() throws Exception {
         oauth.doLogin("test-user@localhost", "password");
@@ -119,7 +119,7 @@ public class ProfileTest {
     }
 
     @Test
-     public void getProfileCorsInvalidOrigin() throws Exception {
+    public void getProfileCorsInvalidOrigin() throws Exception {
         oauth.doLogin("test-user@localhost", "password");
 
         String code = oauth.getCurrentQuery().get("code");
@@ -153,6 +153,35 @@ public class ProfileTest {
     }
 
     @Test
+    public void getProfileNoAccess() throws Exception {
+        try {
+            keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
+                @Override
+                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                    ApplicationModel app = appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_APPLICATION);
+                    defaultRoles = app.getDefaultRoles();
+                    app.updateDefaultRoles(new String[0]);
+                }
+            });
+
+            oauth.doLogin("test-user@localhost", "password");
+
+            String code = oauth.getCurrentQuery().get("code");
+            String token = oauth.doAccessTokenRequest(code, "password").getAccessToken();
+
+            HttpResponse response = doGetProfile(token, null);
+            assertEquals(403, response.getStatusLine().getStatusCode());
+        } finally {
+            keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
+                @Override
+                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                    appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_APPLICATION).updateDefaultRoles((String[]) defaultRoles.toArray());
+                }
+            });
+        }
+    }
+
+    @Test
     public void getProfileOAuthClient() throws Exception {
         oauth.addScope(org.keycloak.models.Constants.ACCOUNT_APPLICATION, org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE);
         oauth.clientId("third-party");
@@ -209,7 +238,7 @@ public class ProfileTest {
         sb.append("req.send(null);\n");
         sb.append("return req.status + '///' + req.responseText;\n");
 
-        JavascriptExecutor js  = (JavascriptExecutor) driver;
+        JavascriptExecutor js = (JavascriptExecutor) driver;
         String response = (String) js.executeScript(sb.toString());
         return response.split("///");
     }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java
index 5b1a827..f7bc811 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AccountTest.java
@@ -21,19 +21,14 @@
  */
 package org.keycloak.testsuite.forms;
 
+import org.apache.http.HttpResponse;
 import org.junit.*;
+import org.keycloak.models.*;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.managers.RealmManager;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
 import org.keycloak.testsuite.OAuthClient;
-import org.keycloak.testsuite.pages.AccountPasswordPage;
-import org.keycloak.testsuite.pages.AccountTotpPage;
-import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
-import org.keycloak.testsuite.pages.AppPage;
+import org.keycloak.testsuite.pages.*;
 import org.keycloak.testsuite.pages.AppPage.RequestType;
-import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.rule.KeycloakRule;
 import org.keycloak.testsuite.rule.KeycloakRule.KeycloakSetup;
 import org.keycloak.testsuite.rule.WebResource;
@@ -43,6 +38,10 @@ import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
 import org.picketlink.idm.credential.util.TimeBasedOTP;
 
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
@@ -75,8 +74,13 @@ public class AccountTest {
     @WebResource
     protected AccountTotpPage totpPage;
 
+    @WebResource
+    protected ErrorPage errorPage;
+
     private TimeBasedOTP totp = new TimeBasedOTP();
 
+    private List<String> defaultRoles;
+
     @After
     public void after() {
         keycloakRule.configure(new KeycloakSetup() {
@@ -183,4 +187,31 @@ public class AccountTest {
         Assert.assertTrue(driver.getPageSource().contains("Remove Google"));
     }
 
+    @Test
+    public void changeProfileNoAccess() throws Exception {
+        try {
+            keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
+                @Override
+                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                    ApplicationModel app = appRealm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
+                    defaultRoles = app.getDefaultRoles();
+                    app.updateDefaultRoles(new String[0]);
+                }
+            });
+
+            profilePage.open();
+            loginPage.login("test-user@localhost", "password");
+
+            Assert.assertTrue(errorPage.isCurrent());
+            Assert.assertEquals("No access", errorPage.getError());
+        } finally {
+            keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
+                @Override
+                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                    appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_APPLICATION).updateDefaultRoles((String[]) defaultRoles.toArray());
+                }
+            });
+        }
+    }
+
 }
diff --git a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java
index 29bd33c..67d2ca6 100644
--- a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java
+++ b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java
@@ -78,13 +78,6 @@ public class CreateUsersWorker implements Worker {
             user.setEmail(username + "@email.com");
         }
 
-        // Adding default roles of realm to user
-        if (addDefaultRoles) {
-            for (RoleModel role : realm.getDefaultRoles()) {
-                realm.grantRole(user, role);
-            }
-        }
-
         // Creating password (will be same as username)
         if (addPassword) {
             UserCredentialModel password = new UserCredentialModel();