Support for service accounts when fetch roles is enabled (#30687)
Support for service accounts when fetch roles is enabled Signed-off-by: Romain LABAT <contact@romainlabat.fr> Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Co-authored-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
parent
4be058a3dd
commit
6615691c63
2 changed files with 47 additions and 4 deletions
|
@ -22,6 +22,7 @@ import java.util.function.BiFunction;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.attribute.Attributes.Entry;
|
||||
import org.keycloak.authorization.identity.Identity;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
|
@ -31,6 +32,8 @@ import org.keycloak.models.KeycloakSession;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.representations.JsonWebToken;
|
||||
import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
|
||||
|
||||
/**
|
||||
|
@ -74,9 +77,8 @@ public class RolePolicyProvider implements PolicyProvider {
|
|||
|
||||
private boolean hasRole(Identity identity, RoleModel role, RealmModel realm, AuthorizationProvider authorizationProvider, boolean fetchRoles) {
|
||||
if (fetchRoles) {
|
||||
KeycloakSession session = authorizationProvider.getKeycloakSession();
|
||||
UserModel user = session.users().getUserById(realm, identity.getId());
|
||||
return user.hasRole(role);
|
||||
UserModel subject = getSubject(identity, realm, authorizationProvider);
|
||||
return subject != null && subject.hasRole(role);
|
||||
}
|
||||
String roleName = role.getName();
|
||||
if (role.isClientRole()) {
|
||||
|
@ -86,6 +88,24 @@ public class RolePolicyProvider implements PolicyProvider {
|
|||
return identity.hasRealmRole(roleName);
|
||||
}
|
||||
|
||||
private UserModel getSubject(Identity identity, RealmModel realm, AuthorizationProvider authorizationProvider) {
|
||||
KeycloakSession session = authorizationProvider.getKeycloakSession();
|
||||
UserProvider users = session.users();
|
||||
UserModel user = users.getUserById(realm, identity.getId());
|
||||
|
||||
if (user == null) {
|
||||
Entry sub = identity.getAttributes().getValue(JsonWebToken.SUBJECT);
|
||||
|
||||
if (sub == null || sub.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return users.getUserById(realm, sub.asString(0));
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
|
|
|
@ -192,6 +192,29 @@ public class RolePolicyTest extends AbstractAuthzTest {
|
|||
assertNotNull(authzClient.authorization("kolo", "password").authorize(new AuthorizationRequest(ticket)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchRolesUsingServiceAccount() {
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
RealmResource realm = getRealm();
|
||||
ClientsResource clients = realm.clients();
|
||||
ClientRepresentation client = clients.findByClientId(authzClient.getConfiguration().getResource()).get(0);
|
||||
ClientScopeRepresentation rolesScope = ApiUtil.findClientScopeByName(realm, OIDCLoginProtocolFactory.ROLES_SCOPE).toRepresentation();
|
||||
ClientResource clientResource = clients.get(client.getId());
|
||||
clientResource.removeDefaultClientScope(rolesScope.getId());
|
||||
UserRepresentation serviceAccountUser = clientResource.getServiceAccountUser();
|
||||
RoleRepresentation roleB = realm.roles().get("Role B").toRepresentation();
|
||||
realm.users().get(serviceAccountUser.getId()).roles().realmLevel().add(List.of(roleB));
|
||||
RolePolicyRepresentation roleRep = clientResource.authorization().policies().role().findByName("Role B Policy");
|
||||
roleRep.setFetchRoles(true);
|
||||
clientResource.authorization().policies().role().findById(roleRep.getId()).update(roleRep);
|
||||
getCleanup().addCleanup(() -> {
|
||||
clientResource.addDefaultClientScope(rolesScope.getId());
|
||||
roleRep.setFetchRoles(false);
|
||||
clientResource.authorization().policies().role().findById(roleRep.getId()).update(roleRep);
|
||||
});
|
||||
assertNotNull(authzClient.authorization().authorize(new AuthorizationRequest()));
|
||||
}
|
||||
|
||||
private void createRealmRolePolicy(String name, String... roles) {
|
||||
RolePolicyRepresentation policy = new RolePolicyRepresentation();
|
||||
|
||||
|
|
Loading…
Reference in a new issue