From 0301094fc97742fb0d34b86d54d013a66118b0ad Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Thu, 15 Aug 2013 16:19:17 +0100 Subject: [PATCH 1/2] KEYCLOAK-40 Add default role to realm --- .../idm/RealmRepresentation.java | 9 ++++ .../example/demo/DemoApplication.java | 1 + .../main/resources/META-INF/testrealm.json | 1 + .../services/managers/RealmManager.java | 12 +++-- .../keycloak/services/models/RealmModel.java | 6 +++ .../models/jpa/entities/RealmEntity.java | 1 + .../models/picketlink/RealmAdapter.java | 45 +++++++++++++++++++ .../models/picketlink/mappings/RealmData.java | 10 +++++ .../picketlink/mappings/RealmEntity.java | 2 + .../services/resources/SaasService.java | 7 ++- .../services/resources/SocialResource.java | 7 ++- .../services/resources/TokenService.java | 7 ++- .../java/org/keycloak/test/AdapterTest.java | 5 ++- .../java/org/keycloak/test/ImportTest.java | 4 ++ .../keycloak/test/InstallationManager.java | 1 + services/src/test/resources/testrealm.json | 1 + 16 files changed, 105 insertions(+), 14 deletions(-) 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 8ef7c4ac55..e365a6147b 100755 --- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java @@ -22,6 +22,7 @@ public class RealmRepresentation { protected String privateKey; protected String publicKey; protected List roles; + protected String[] defaultRoles; protected Set requiredCredentials; protected Set requiredApplicationCredentials; protected Set requiredOAuthClientCredentials; @@ -183,6 +184,14 @@ public class RealmRepresentation { this.roles = roles; } + public String[] getDefaultRoles() { + return defaultRoles; + } + + public void setDefaultRoles(String[] defaultRoles) { + this.defaultRoles = defaultRoles; + } + public String getPrivateKey() { return privateKey; } diff --git a/examples/as7-eap-demo/server/src/main/java/org/keycloak/example/demo/DemoApplication.java b/examples/as7-eap-demo/server/src/main/java/org/keycloak/example/demo/DemoApplication.java index faf899e60b..29045058d7 100755 --- a/examples/as7-eap-demo/server/src/main/java/org/keycloak/example/demo/DemoApplication.java +++ b/examples/as7-eap-demo/server/src/main/java/org/keycloak/example/demo/DemoApplication.java @@ -43,6 +43,7 @@ public class DemoApplication extends KeycloakApplication { manager.generateRealmKeys(defaultRealm); defaultRealm.addRequiredCredential(CredentialRepresentation.PASSWORD); defaultRealm.addRole(SaasService.REALM_CREATOR_ROLE); + defaultRealm.addDefaultRole(SaasService.REALM_CREATOR_ROLE); RealmRepresentation rep = loadJson("META-INF/testrealm.json"); RealmModel realm = manager.createRealm("demo", rep.getRealm()); diff --git a/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json b/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json index 2a711d09ac..f92e34c199 100755 --- a/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json +++ b/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json @@ -11,6 +11,7 @@ "requiredCredentials": [ "password" ], "requiredApplicationCredentials": [ "password" ], "requiredOAuthClientCredentials": [ "password" ], + "defaultRoles": [ "user" ], "users" : [ { "username" : "bburke@redhat.com", 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 1586236a8d..47675588ff 100755 --- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java +++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java @@ -2,7 +2,6 @@ package org.keycloak.services.managers; import org.jboss.resteasy.logging.Logger; import org.keycloak.representations.idm.*; -import org.keycloak.representations.idm.ApplicationRepresentation; import org.keycloak.services.models.*; import java.security.KeyPair; @@ -84,6 +83,9 @@ public class RealmManager { if (rep.getRequiredApplicationCredentials() != null) { realm.updateRequiredApplicationCredentials(rep.getRequiredApplicationCredentials()); } + if (rep.getDefaultRoles() != null) { + realm.updateDefaultRoles(rep.getDefaultRoles()); + } } public RealmModel importRealm(RealmRepresentation rep, UserModel realmCreator) { @@ -131,8 +133,6 @@ public class RealmManager { } } - - if (rep.getUsers() != null) { for (UserRepresentation userRep : rep.getUsers()) { UserModel user = createUser(newRealm, userRep); @@ -146,6 +146,12 @@ public class RealmManager { } } + if (rep.getDefaultRoles() != null) { + for (String roleString : rep.getDefaultRoles()) { + newRealm.addDefaultRole(roleString.trim()); + } + } + if (rep.getApplications() != null) { createResources(rep, newRealm); } diff --git a/services/src/main/java/org/keycloak/services/models/RealmModel.java b/services/src/main/java/org/keycloak/services/models/RealmModel.java index 605de11220..408df1b80b 100755 --- a/services/src/main/java/org/keycloak/services/models/RealmModel.java +++ b/services/src/main/java/org/keycloak/services/models/RealmModel.java @@ -78,6 +78,12 @@ public interface RealmModel { RoleModel addRole(String name); List getRoles(); + + List getDefaultRoles(); + + void addDefaultRole(String name); + + void updateDefaultRoles(String[] defaultRoles); Map getResourceNameMap(); diff --git a/services/src/main/java/org/keycloak/services/models/jpa/entities/RealmEntity.java b/services/src/main/java/org/keycloak/services/models/jpa/entities/RealmEntity.java index 7f6c5eee09..bb55046c0c 100755 --- a/services/src/main/java/org/keycloak/services/models/jpa/entities/RealmEntity.java +++ b/services/src/main/java/org/keycloak/services/models/jpa/entities/RealmEntity.java @@ -29,6 +29,7 @@ public class RealmEntity { protected String publicKeyPem; @Column(length = 2048) protected String privateKeyPem; + protected String[] defaultRoles; @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true) Collection requiredCredentials; diff --git a/services/src/main/java/org/keycloak/services/models/picketlink/RealmAdapter.java b/services/src/main/java/org/keycloak/services/models/picketlink/RealmAdapter.java index 2e7371a61c..dc8d6da92d 100755 --- a/services/src/main/java/org/keycloak/services/models/picketlink/RealmAdapter.java +++ b/services/src/main/java/org/keycloak/services/models/picketlink/RealmAdapter.java @@ -40,6 +40,7 @@ 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; @@ -649,4 +650,48 @@ public class RealmAdapter implements RealmModel { relationship.setRealm(realm.getName()); getRelationshipManager().add(relationship); } + + @Override + public List getDefaultRoles() { + List defaultRoleModels = new ArrayList(); + if (realm.getDefaultRoles() != null) { + for (String name : realm.getDefaultRoles()) { + RoleAdapter role = getRole(name); + if (role != null) { + defaultRoleModels.add(role); + } + } + } + return defaultRoleModels; + } + + @Override + public void addDefaultRole(String name) { + if (getRole(name) == null) { + addRole(name); + } + + String[] defaultRoles = realm.getDefaultRoles(); + if (defaultRoles == null) { + defaultRoles = new String[1]; + } else { + defaultRoles = Arrays.copyOf(defaultRoles, defaultRoles.length + 1); + } + defaultRoles[defaultRoles.length - 1] = name; + + realm.setDefaultRoles(defaultRoles); + updateRealm(); + } + + @Override + public void updateDefaultRoles(String[] defaultRoles) { + for (String name : defaultRoles) { + if (getRole(name) == null) { + addRole(name); + } + } + + realm.setDefaultRoles(defaultRoles); + updateRealm(); + } } diff --git a/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmData.java b/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmData.java index 0dc72b978a..1fc6b7f54a 100755 --- a/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmData.java +++ b/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmData.java @@ -19,6 +19,7 @@ public class RealmData extends AbstractPartition { private int accessCodeLifespan; private String publicKeyPem; private String privateKeyPem; + private String[] defaultRoles; public RealmData() { super(null); @@ -116,4 +117,13 @@ public class RealmData extends AbstractPartition { public void setPrivateKeyPem(String privateKeyPem) { this.privateKeyPem = privateKeyPem; } + + @AttributeProperty + public String[] getDefaultRoles() { + return defaultRoles; + } + + public void setDefaultRoles(String[] defaultRoles) { + this.defaultRoles = defaultRoles; + } } diff --git a/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmEntity.java b/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmEntity.java index e4b83c4f7b..e7e0883388 100755 --- a/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmEntity.java +++ b/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmEntity.java @@ -46,6 +46,8 @@ public class RealmEntity implements Serializable { @AttributeValue @Column(length = 2048) private String privateKeyPem; + @AttributeValue + private String[] defaultRoles; public PartitionTypeEntity getPartitionTypeEntity() { diff --git a/services/src/main/java/org/keycloak/services/resources/SaasService.java b/services/src/main/java/org/keycloak/services/resources/SaasService.java index e969d7e05d..ea786cca90 100755 --- a/services/src/main/java/org/keycloak/services/resources/SaasService.java +++ b/services/src/main/java/org/keycloak/services/resources/SaasService.java @@ -376,8 +376,11 @@ public class SaasService { credModel.setValue(cred.getValue()); defaultRealm.updateCredential(user, credModel); } - RoleModel realmCreator = defaultRealm.getRole(REALM_CREATOR_ROLE); - defaultRealm.grantRole(user, realmCreator); + + for (RoleModel role : defaultRealm.getDefaultRoles()) { + defaultRealm.grantRole(user, role); + } + return user; } 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 35d625a57e..4e7f81203e 100644 --- a/services/src/main/java/org/keycloak/services/resources/SocialResource.java +++ b/services/src/main/java/org/keycloak/services/resources/SocialResource.java @@ -147,10 +147,9 @@ public class SocialResource { user = realm.addUser(provider.getId() + "." + socialUser.getId()); user.setAttribute(provider.getId() + ".id", socialUser.getId()); - // TODO Grant default roles for realm when available - RoleModel defaultRole = realm.getRole("user"); - - realm.grantRole(user, defaultRole); + for (RoleModel role : realm.getDefaultRoles()) { + realm.grantRole(user, role); + } } if (!user.isEnabled()) { 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 7488fe1685..8c283108e4 100755 --- a/services/src/main/java/org/keycloak/services/resources/TokenService.java +++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java @@ -296,10 +296,9 @@ public class TokenService { credentials.setValue(formData.getFirst("password")); realm.updateCredential(user, credentials); - // TODO Grant default roles for realm when available - RoleModel defaultRole = realm.getRole("user"); - - realm.grantRole(user, defaultRole); + for (RoleModel role : realm.getDefaultRoles()) { + realm.grantRole(user, role); + } return processLogin(clientId, scopeParam, state, redirect, formData); } diff --git a/services/src/test/java/org/keycloak/test/AdapterTest.java b/services/src/test/java/org/keycloak/test/AdapterTest.java index ad191ddbee..2012264c6e 100755 --- a/services/src/test/java/org/keycloak/test/AdapterTest.java +++ b/services/src/test/java/org/keycloak/test/AdapterTest.java @@ -75,6 +75,7 @@ public class AdapterTest { realmModel.setPrivateKeyPem("0234234"); realmModel.setPublicKeyPem("0234234"); realmModel.setTokenLifespan(1000); + realmModel.addDefaultRole("foo"); System.out.println(realmModel.getId()); realmModel = adapter.getRealm(realmModel.getId()); @@ -85,6 +86,8 @@ public class AdapterTest { Assert.assertEquals(realmModel.getName(), "JUGGLER"); Assert.assertEquals(realmModel.getPrivateKeyPem(), "0234234"); Assert.assertEquals(realmModel.getPublicKeyPem(), "0234234"); + Assert.assertEquals(1, realmModel.getDefaultRoles().size()); + Assert.assertEquals("foo", realmModel.getDefaultRoles().get(0).getName()); } @Test @@ -134,7 +137,7 @@ public class AdapterTest { realmModel.addRole("admin"); realmModel.addRole("user"); List roles = realmModel.getRoles(); - Assert.assertEquals(5, roles.size()); + Assert.assertEquals(6, roles.size()); UserModel user = realmModel.addUser("bburke"); RoleModel role = realmModel.getRole("user"); realmModel.grantRole(user, role); diff --git a/services/src/test/java/org/keycloak/test/ImportTest.java b/services/src/test/java/org/keycloak/test/ImportTest.java index d1534d68ef..dce085fb03 100755 --- a/services/src/test/java/org/keycloak/test/ImportTest.java +++ b/services/src/test/java/org/keycloak/test/ImportTest.java @@ -72,6 +72,10 @@ public class ImportTest { Assert.assertEquals(1, creds.size()); RequiredCredentialModel cred = creds.get(0); Assert.assertEquals("password", cred.getFormLabel()); + Assert.assertEquals(2, realm.getDefaultRoles().size()); + + Assert.assertNotNull(realm.getRole("foo")); + Assert.assertNotNull(realm.getRole("bar")); UserModel user = realm.getUser("loginclient"); Assert.assertNotNull(user); diff --git a/services/src/test/java/org/keycloak/test/InstallationManager.java b/services/src/test/java/org/keycloak/test/InstallationManager.java index 18a2cc4d5f..f18f086a37 100755 --- a/services/src/test/java/org/keycloak/test/InstallationManager.java +++ b/services/src/test/java/org/keycloak/test/InstallationManager.java @@ -24,6 +24,7 @@ public class InstallationManager { manager.generateRealmKeys(defaultRealm); defaultRealm.addRequiredCredential(CredentialRepresentation.PASSWORD); defaultRealm.addRole(SaasService.REALM_CREATOR_ROLE); + defaultRealm.addDefaultRole(SaasService.REALM_CREATOR_ROLE); } public boolean isInstalled(RealmManager manager) { diff --git a/services/src/test/resources/testrealm.json b/services/src/test/resources/testrealm.json index 6ec29bfe93..b1e3e39d05 100755 --- a/services/src/test/resources/testrealm.json +++ b/services/src/test/resources/testrealm.json @@ -6,6 +6,7 @@ "requiredCredentials": [ "password" ], "requiredApplicationCredentials": [ "password" ], "requiredOAuthClientCredentials": [ "password" ], + "defaultRoles": [ "foo", "bar" ], "users": [ { "username": "wburke", From a65c8695d78a2d99fdc1ccd5affcb76d143a5917 Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Thu, 15 Aug 2013 16:34:44 +0100 Subject: [PATCH 2/2] If registration is not allowed for a realm it should not be possible to login with social login unless the user already exists --- .../java/org/keycloak/services/resources/SocialResource.java | 4 ++++ 1 file changed, 4 insertions(+) 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 4e7f81203e..73e139cf8e 100644 --- a/services/src/main/java/org/keycloak/services/resources/SocialResource.java +++ b/services/src/main/java/org/keycloak/services/resources/SocialResource.java @@ -144,6 +144,10 @@ public class SocialResource { UserModel user = realm.getUser(provider.getId() + "." + socialUser.getId()); if (user == null) { + if (!realm.isRegistrationAllowed()) { + return oauth.forwardToSecurityFailure("Registration not allowed"); + } + user = realm.addUser(provider.getId() + "." + socialUser.getId()); user.setAttribute(provider.getId() + ".id", socialUser.getId());