composite roles 2
This commit is contained in:
parent
bb5991239b
commit
6a5994c3e2
6 changed files with 98 additions and 41 deletions
|
@ -30,4 +30,5 @@ public interface RoleModel {
|
|||
RoleContainerModel getContainer();
|
||||
|
||||
|
||||
boolean hasRole(RoleModel role);
|
||||
}
|
||||
|
|
|
@ -261,4 +261,11 @@ public class ApplicationAdapter implements ApplicationModel {
|
|||
public void addScope(RoleModel role) {
|
||||
realm.addScopeMapping(getApplicationUser(), role);
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof ApplicationAdapter)) return false;
|
||||
ApplicationAdapter app = (ApplicationAdapter)o;
|
||||
return app.getId().equals(getId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -897,28 +897,13 @@ public class RealmAdapter implements RealmModel {
|
|||
return new RoleAdapter(this, em, entity);
|
||||
}
|
||||
|
||||
protected boolean searchCompositeFor(RoleModel role, RoleModel composite, Set<RoleModel> visited) {
|
||||
if (visited.contains(composite)) return false;
|
||||
visited.add(composite);
|
||||
Set<RoleModel> composites = composite.getComposites();
|
||||
if (composites.contains(role)) return true;
|
||||
for (RoleModel contained : composites) {
|
||||
if (!contained.isComposite()) continue;
|
||||
if (searchCompositeFor(role, contained, visited)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRole(UserModel user, RoleModel role) {
|
||||
Set<RoleModel> roles = getRoleMappings(user);
|
||||
if (roles.contains(role)) return true;
|
||||
|
||||
Set<RoleModel> visited = new HashSet<RoleModel>();
|
||||
for (RoleModel mapping : roles) {
|
||||
if (!mapping.isComposite()) continue;
|
||||
if (searchCompositeFor(role, mapping, visited)) return true;
|
||||
|
||||
if (mapping.hasRole(role)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1104,4 +1089,12 @@ public class RealmAdapter implements RealmModel {
|
|||
realm.setPasswordPolicy(policy.toString());
|
||||
em.flush();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof RealmAdapter)) return false;
|
||||
RealmAdapter r = (RealmAdapter)o;
|
||||
return r.getId().equals(getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.keycloak.models.jpa;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.jpa.entities.ApplicationRoleEntity;
|
||||
import org.keycloak.models.jpa.entities.RealmRoleEntity;
|
||||
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||
|
@ -97,6 +98,27 @@ public class RoleAdapter implements RoleModel {
|
|||
return set;
|
||||
}
|
||||
|
||||
public static boolean searchCompositeFor(RoleModel role, RoleModel composite, Set<RoleModel> visited) {
|
||||
if (visited.contains(composite)) return false;
|
||||
visited.add(composite);
|
||||
Set<RoleModel> composites = composite.getComposites();
|
||||
if (composites.contains(role)) return true;
|
||||
for (RoleModel contained : composites) {
|
||||
if (!contained.isComposite()) continue;
|
||||
if (searchCompositeFor(role, contained, visited)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRole(RoleModel role) {
|
||||
if (this.equals(role)) return true;
|
||||
if (!isComposite()) return false;
|
||||
|
||||
Set<RoleModel> visited = new HashSet<RoleModel>();
|
||||
return searchCompositeFor(role, this, visited);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleContainerModel getContainer() {
|
||||
if (role instanceof ApplicationRoleEntity) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import javax.ws.rs.core.MultivaluedMap;
|
|||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -69,31 +70,34 @@ public class TokenManager {
|
|||
List<RoleModel> realmRolesRequested = code.getRealmRolesRequested();
|
||||
MultivaluedMap<String, RoleModel> resourceRolesRequested = code.getResourceRolesRequested();
|
||||
|
||||
Set<RoleModel> realmScopeMappings = realm.getRealmScopeMappings(client);
|
||||
for (RoleModel desiredRole : realmScopeMappings) {
|
||||
if (!realm.hasRole(user, desiredRole)) continue;
|
||||
if (desiresScope(scopeMap, "realm", desiredRole.getName())) {
|
||||
realmRolesRequested.add(desiredRole);
|
||||
|
||||
Set<RoleModel> roleMappings = realm.getRoleMappings(user);
|
||||
Set<RoleModel> scopeMappings = realm.getScopeMappings(client);
|
||||
Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
|
||||
|
||||
for (RoleModel role : roleMappings) {
|
||||
for (RoleModel desiredRole : scopeMappings) {
|
||||
if (desiredRole.equals(role)) {
|
||||
requestedRoles.add(role);
|
||||
} else if (desiredRole.hasRole(role)) {
|
||||
requestedRoles.add(role);
|
||||
} else if (role.hasRole(desiredRole)) {
|
||||
requestedRoles.add(desiredRole);
|
||||
} else if (role.getContainer() instanceof ApplicationModel) {
|
||||
if (((ApplicationModel)role.getContainer()).getApplicationUser().getLoginName().equals(client.getLoginName())) {
|
||||
requestedRoles.add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ApplicationModel application : realm.getApplications()) {
|
||||
if (!desiresScopeGroup(scopeMap, application.getName())) continue;
|
||||
Set<RoleModel> desiredRoles = application.getApplicationScopeMappings(client);
|
||||
if (desiredRoles.isEmpty()) {
|
||||
if (application.getApplicationUser().getLoginName().equals(client.getLoginName())) {
|
||||
Set<RoleModel> appRoleMappings = application.getApplicationRoleMappings(user);
|
||||
for (RoleModel desiredAppRole : appRoleMappings) {
|
||||
if (desiresScope(scopeMap, application.getName(), desiredAppRole.getName())) {
|
||||
resourceRolesRequested.add(application.getName(), desiredAppRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (RoleModel desiredAppRole : desiredRoles) {
|
||||
if (realm.hasRole(user, desiredAppRole) && desiresScope(scopeMap, application.getName(), desiredAppRole.getName())) {
|
||||
resourceRolesRequested.add(application.getName(), desiredAppRole);
|
||||
}
|
||||
for (RoleModel role : requestedRoles) {
|
||||
if (role.getContainer() instanceof RealmModel && desiresScope(scopeMap, "realm", role.getName())) {
|
||||
realmRolesRequested.add(role);
|
||||
} else if (role.getContainer() instanceof ApplicationModel) {
|
||||
ApplicationModel app = (ApplicationModel)role.getContainer();
|
||||
if (desiresScope(scopeMap, app.getName(), role.getName())) {
|
||||
resourceRolesRequested.add(app.getName(), role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +170,6 @@ public class TokenManager {
|
|||
SkeletonKeyToken token = initToken(realm, client, user);
|
||||
|
||||
if (accessCodeEntry.getRealmRolesRequested().size() > 0) {
|
||||
SkeletonKeyToken.Access access = new SkeletonKeyToken.Access();
|
||||
for (RoleModel role : accessCodeEntry.getRealmRolesRequested()) {
|
||||
addComposites(token, role);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ public class CompositeRoleTest {
|
|||
manager.generateRealmKeys(realm);
|
||||
realmPublicKey = realm.getPublicKey();
|
||||
realm.setTokenLifespan(10000);
|
||||
realm.setAccessCodeLifespanUserAction(1000);
|
||||
realm.setAccessCodeLifespan(1000);
|
||||
realm.setSslNotRequired(true);
|
||||
realm.setEnabled(true);
|
||||
realm.addRequiredResourceCredential(UserCredentialModel.PASSWORD);
|
||||
|
@ -75,6 +77,11 @@ public class CompositeRoleTest {
|
|||
realm.updateCredential(realmComposite1User, UserCredentialModel.password("password"));
|
||||
realm.grantRole(realmComposite1User, realmComposite1);
|
||||
|
||||
final UserModel realmRole1User = realm.addUser("REALM_ROLE_1_USER");
|
||||
realmRole1User.setEnabled(true);
|
||||
realm.updateCredential(realmRole1User, UserCredentialModel.password("password"));
|
||||
realm.grantRole(realmRole1User, realmRole1);
|
||||
|
||||
final ApplicationModel realmComposite1Application = new ApplicationManager(manager).createApplication(realm, "REALM_COMPOSITE_1_APPLICATION");
|
||||
realmComposite1Application.setEnabled(true);
|
||||
realmComposite1Application.addScope(realmComposite1);
|
||||
|
@ -109,7 +116,7 @@ public class CompositeRoleTest {
|
|||
protected LoginPage loginPage;
|
||||
|
||||
@Test
|
||||
public void testRealmOnlyCompositeWithUserCompositeAppComposite() throws Exception {
|
||||
public void testRealmOnlyWithUserCompositeAppComposite() throws Exception {
|
||||
oauth.realm("Test");
|
||||
oauth.realmPublicKey(realmPublicKey);
|
||||
oauth.clientId("REALM_COMPOSITE_1_APPLICATION");
|
||||
|
@ -132,7 +139,7 @@ public class CompositeRoleTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testRealmOnlyCompositeWithUserCompositeAppRole() throws Exception {
|
||||
public void testRealmOnlyWithUserCompositeAppRole() throws Exception {
|
||||
oauth.realm("Test");
|
||||
oauth.realmPublicKey(realmPublicKey);
|
||||
oauth.clientId("REALM_ROLE_1_APPLICATION");
|
||||
|
@ -153,5 +160,29 @@ public class CompositeRoleTest {
|
|||
Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRealmOnlyWithUserRoleAppComposite() throws Exception {
|
||||
oauth.realm("Test");
|
||||
oauth.realmPublicKey(realmPublicKey);
|
||||
oauth.clientId("REALM_COMPOSITE_1_APPLICATION");
|
||||
oauth.doLogin("REALM_ROLE_1_USER", "password");
|
||||
|
||||
String code = oauth.getCurrentQuery().get("code");
|
||||
AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
|
||||
|
||||
Assert.assertEquals(200, response.getStatusCode());
|
||||
|
||||
Assert.assertEquals("bearer", response.getTokenType());
|
||||
|
||||
SkeletonKeyToken token = oauth.verifyToken(response.getAccessToken());
|
||||
|
||||
Assert.assertEquals("REALM_ROLE_1_USER", token.getSubject());
|
||||
|
||||
Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
|
||||
Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue