From 29d5c73464a24d9c9292b4bf59d30455a9cf3c3c Mon Sep 17 00:00:00 2001 From: Thanuja Date: Mon, 11 Dec 2023 14:35:22 +0530 Subject: [PATCH 1/2] Add new conditional functions based on Role V2 --- .../user/AssignUserRolesV2Function.java | 2 + .../user/AssignUserRolesV2FunctionImpl.java | 2 + .../user/HasAnyOfTheRolesV2Function.java | 42 +++++++++++++++++++ .../user/HasAnyOfTheRolesV2FunctionImpl.java | 2 + .../user/RemoveUserRolesV2Function.java | 2 + .../user/RemoveUserRolesV2FunctionImpl.java | 2 + 6 files changed, 52 insertions(+) create mode 100644 components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2Function.java create mode 100644 components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java create mode 100644 components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2Function.java create mode 100644 components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java create mode 100644 components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2Function.java create mode 100644 components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2Function.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2Function.java new file mode 100644 index 00000000..63418229 --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2Function.java @@ -0,0 +1,2 @@ +package org.wso2.carbon.identity.conditional.auth.functions.user;public interface AssignUserRolesV2Function { +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java new file mode 100644 index 00000000..17ad099a --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java @@ -0,0 +1,2 @@ +package org.wso2.carbon.identity.conditional.auth.functions.user;public class AssignUserRolesV2FunctionImpl { +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2Function.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2Function.java new file mode 100644 index 00000000..c76cfade --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2Function.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user; + +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; + +import java.util.List; + +/** + * Function to check if the given user has at least one of the given roles(v2). + * The purpose is to perform dynamic authentication selection based on user role(v2). + */ +@FunctionalInterface +public interface HasAnyOfTheRolesV2Function { + + + /** + * Checks if the given user has the given roleName + * + * @param user Authenticated user. Ideally from a given step. + * @param roleNames Role to be checked + * @return true if the user has at least one of the given roles. false for any other + * case. + */ + boolean hasAnyOfTheRolesV2(JsAuthenticatedUser user, List roleNames); +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java new file mode 100644 index 00000000..e437ba7a --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java @@ -0,0 +1,2 @@ +package org.wso2.carbon.identity.conditional.auth.functions.user;public class HasAnyOfTheRolesV2FunctionImpl { +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2Function.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2Function.java new file mode 100644 index 00000000..b76577cd --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2Function.java @@ -0,0 +1,2 @@ +package org.wso2.carbon.identity.conditional.auth.functions.user;public interface RemoveUserRolesV2Function { +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java new file mode 100644 index 00000000..fc6fbaee --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java @@ -0,0 +1,2 @@ +package org.wso2.carbon.identity.conditional.auth.functions.user;public class RemoveUserRolesV2FunctionImpl { +} From 36471df4bcf9dbeb446321d77e4e413b90fb300d Mon Sep 17 00:00:00 2001 From: Thanuja Date: Mon, 11 Dec 2023 14:35:34 +0530 Subject: [PATCH 2/2] Add new conditional functions based on Role V2 --- .../pom.xml | 4 + .../user/AssignUserRolesV2Function.java | 40 ++++++- .../user/AssignUserRolesV2FunctionImpl.java | 103 ++++++++++++++++- .../user/HasAnyOfTheRolesV2Function.java | 9 +- .../user/HasAnyOfTheRolesV2FunctionImpl.java | 108 +++++++++++++++++- .../user/RemoveUserRolesV2Function.java | 40 ++++++- .../user/RemoveUserRolesV2FunctionImpl.java | 103 ++++++++++++++++- .../UserFunctionsServiceComponent.java | 61 ++++++++++ .../internal/UserFunctionsServiceHolder.java | 24 ++++ 9 files changed, 482 insertions(+), 10 deletions(-) diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/pom.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.user/pom.xml index cbb0de46..64cd8061 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/pom.xml +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/pom.xml @@ -172,12 +172,16 @@ version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.application.authentication.framework.dao; version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.application.mgt; + version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.base.*; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.core.util.*; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.core.model.*; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.user.profile.mgt; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.user.profile.mgt.dao; version="${carbon.identity.package.import.version.range}", org.apache.commons.collections, + org.wso2.carbon.identity.role.v2.mgt.core.*; + version="${carbon.identity.package.import.version.range}", org.wso2.carbon.user.api; version="${carbon.user.package.import.version.range}", org.wso2.carbon.user.core; version="${carbon.kernel.package.import.version.range}", org.wso2.carbon.user.core.util; version="${carbon.kernel.package.import.version.range}", diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2Function.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2Function.java index 63418229..21302516 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2Function.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2Function.java @@ -1,2 +1,40 @@ -package org.wso2.carbon.identity.conditional.auth.functions.user;public interface AssignUserRolesV2Function { +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user; + +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; + +import java.util.List; + +/** + * Function to update given roles(v2) for a given user. + * The purpose is to perform role(v2) assigning during dynamic authentication. + */ +@FunctionalInterface +public interface AssignUserRolesV2Function { + + /** + * Add roles for a given user + * + * @param context authentication context + * @param roleListToAssign Roles to be assigned. + * @return true If the role assigning is successfully completed. false for any other case. + */ + boolean assignUserRolesV2(JsAuthenticationContext context, List roleListToAssign); } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java index 17ad099a..9c23fac3 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java @@ -1,2 +1,103 @@ -package org.wso2.carbon.identity.conditional.auth.functions.user;public class AssignUserRolesV2FunctionImpl { +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; +import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException; +import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.common.model.AssociatedRolesConfig; +import org.wso2.carbon.identity.application.common.model.RoleV2; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.conditional.auth.functions.user.internal.UserFunctionsServiceHolder; +import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * Implementation of the function to assign given roles for a given user. + */ +public class AssignUserRolesV2FunctionImpl implements AssignUserRolesV2Function { + + private static final Log LOG = LogFactory.getLog(AssignUserRolesV2FunctionImpl.class); + + @Override + public boolean assignUserRolesV2(JsAuthenticationContext context, List roleListToAssign) { + + if (roleListToAssign == null || roleListToAssign.isEmpty()) { + return false; + } + + AuthenticatedUser subject = context.getWrapped().getSubject(); + if (subject.isFederatedUser()) { + return false; + } + + String applicationName = context.getWrapped().getServiceProviderName(); + String tenantDomain = context.getWrapped().getTenantDomain(); + + ServiceProvider application; + try { + application = UserFunctionsServiceHolder.getInstance().getApplicationManagementService() + .getApplicationExcludingFileBasedSPs(applicationName, tenantDomain); + } catch (IdentityApplicationManagementException e) { + LOG.error("Error occurred while retrieving the application", e); + return false; + } + + AssociatedRolesConfig associatedRolesConfig = application.getAssociatedRolesConfig(); + if (associatedRolesConfig == null || associatedRolesConfig.getRoles() == null + || associatedRolesConfig.getRoles().length == 0) { + // No roles associated with the application. + return false; + } + + List associatedRoles = Arrays.asList(associatedRolesConfig.getRoles()); + List allowedRoleListToAssign = new ArrayList<>(); + for (String roleName : roleListToAssign) { + // Check if the provided role name is associated with the application. + Optional roleOptional = + associatedRoles.stream().filter(role -> role.getName().equals(roleName)).findFirst(); + roleOptional.ifPresent(allowedRoleListToAssign::add); + } + + if (allowedRoleListToAssign.isEmpty()) { + return false; + } + + for (RoleV2 role : allowedRoleListToAssign) { + try { + UserFunctionsServiceHolder.getInstance().getRoleManagementService() + .updateUserListOfRole(role.getId(), Collections.singletonList(subject.getUserId()), + Collections.emptyList(), tenantDomain); + } catch (IdentityRoleManagementException | UserIdNotFoundException e) { + LOG.error("Error occurred while updating the roles of the user", e); + return false; + } + } + + return true; + } } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2Function.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2Function.java index c76cfade..15d9c294 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2Function.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2Function.java @@ -18,7 +18,7 @@ package org.wso2.carbon.identity.conditional.auth.functions.user; -import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; import java.util.List; @@ -29,14 +29,13 @@ @FunctionalInterface public interface HasAnyOfTheRolesV2Function { - /** - * Checks if the given user has the given roleName + * Check if the user in the authentication context has any of the given roles. * - * @param user Authenticated user. Ideally from a given step. + * @param context authentication context * @param roleNames Role to be checked * @return true if the user has at least one of the given roles. false for any other * case. */ - boolean hasAnyOfTheRolesV2(JsAuthenticatedUser user, List roleNames); + boolean hasAnyOfTheRolesV2(JsAuthenticationContext context, List roleNames); } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java index e437ba7a..3106abde 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java @@ -1,2 +1,108 @@ -package org.wso2.carbon.identity.conditional.auth.functions.user;public class HasAnyOfTheRolesV2FunctionImpl { +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; +import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException; +import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.common.model.AssociatedRolesConfig; +import org.wso2.carbon.identity.application.common.model.RoleV2; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.conditional.auth.functions.user.internal.UserFunctionsServiceHolder; +import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementException; +import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleBasicInfo; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** + * Implementation of the function to check if the given user has at least one of the given roles(v2). + */ +public class HasAnyOfTheRolesV2FunctionImpl implements HasAnyOfTheRolesV2Function { + + private static final Log LOG = LogFactory.getLog(HasAnyOfTheRolesV2FunctionImpl.class); + + @Override + public boolean hasAnyOfTheRolesV2(JsAuthenticationContext context, List roleNames) { + + if (roleNames == null || roleNames.isEmpty()) { + return false; + } + + AuthenticatedUser subject = context.getWrapped().getSubject(); + if (subject.isFederatedUser()) { + return false; + } + + String applicationName = context.getWrapped().getServiceProviderName(); + String tenantDomain = context.getWrapped().getTenantDomain(); + + ServiceProvider application; + try { + application = UserFunctionsServiceHolder.getInstance().getApplicationManagementService() + .getApplicationExcludingFileBasedSPs(applicationName, tenantDomain); + } catch (IdentityApplicationManagementException e) { + LOG.error("Error occurred while retrieving the application", e); + return false; + } + + AssociatedRolesConfig associatedRolesConfig = application.getAssociatedRolesConfig(); + if (associatedRolesConfig == null || associatedRolesConfig.getRoles() == null + || associatedRolesConfig.getRoles().length == 0) { + // No roles associated with the application. + return false; + } + + List roleListOfUser; + try { + roleListOfUser = UserFunctionsServiceHolder.getInstance().getRoleManagementService() + .getRoleListOfUser(subject.getUserId(), tenantDomain); + } catch (IdentityRoleManagementException | UserIdNotFoundException e) { + LOG.error("Error occurred while retrieving the user", e); + return false; + } + + if (roleListOfUser == null || roleListOfUser.isEmpty()) { + return false; + } + + List associatedRoles = Arrays.asList(associatedRolesConfig.getRoles()); + for (String roleName : roleNames) { + // Check if the provided role name is associated with the application. + Optional roleOptional = + associatedRoles.stream().filter(role -> role.getName().equals(roleName)).findFirst(); + + if (roleOptional.isPresent()) { + // Check if the user has the role from role id. + Optional role2 = roleListOfUser.stream() + .filter(roleBasicInfo -> roleBasicInfo.getId().equals(roleOptional.get().getId())) + .findFirst(); + if (role2.isPresent()) { + return true; + } + } + } + + return false; + } } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2Function.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2Function.java index b76577cd..88b3a391 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2Function.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2Function.java @@ -1,2 +1,40 @@ -package org.wso2.carbon.identity.conditional.auth.functions.user;public interface RemoveUserRolesV2Function { +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user; + +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; + +import java.util.List; + +/** + * Function to remove given roles(v2) for a given user. + * The purpose is to perform role(v2) removing during dynamic authentication. + */ +@FunctionalInterface +public interface RemoveUserRolesV2Function { + + /** + * Remove roles for a given user + * + * @param context authentication context + * @param roleListToRemove Roles to be removed. + * @return true If the role removal is successfully completed. false for any other case. + */ + boolean removeUserRolesV2(JsAuthenticationContext context, List roleListToRemove); } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java index fc6fbaee..7d531a5c 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java @@ -1,2 +1,103 @@ -package org.wso2.carbon.identity.conditional.auth.functions.user;public class RemoveUserRolesV2FunctionImpl { +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; +import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException; +import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.common.model.AssociatedRolesConfig; +import org.wso2.carbon.identity.application.common.model.RoleV2; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.conditional.auth.functions.user.internal.UserFunctionsServiceHolder; +import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * Implementation of the function to remove given roles for a given user. + */ +public class RemoveUserRolesV2FunctionImpl implements RemoveUserRolesV2Function { + + private static final Log LOG = LogFactory.getLog(RemoveUserRolesV2FunctionImpl.class); + + @Override + public boolean removeUserRolesV2(JsAuthenticationContext context, List roleListToRemove) { + + if (roleListToRemove == null || roleListToRemove.isEmpty()) { + return false; + } + + AuthenticatedUser subject = context.getWrapped().getSubject(); + if (subject.isFederatedUser()) { + return false; + } + + String applicationName = context.getWrapped().getServiceProviderName(); + String tenantDomain = context.getWrapped().getTenantDomain(); + + ServiceProvider application; + try { + application = UserFunctionsServiceHolder.getInstance().getApplicationManagementService() + .getApplicationExcludingFileBasedSPs(applicationName, tenantDomain); + } catch (IdentityApplicationManagementException e) { + LOG.error("Error occurred while retrieving the application", e); + return false; + } + + AssociatedRolesConfig associatedRolesConfig = application.getAssociatedRolesConfig(); + if (associatedRolesConfig == null || associatedRolesConfig.getRoles() == null + || associatedRolesConfig.getRoles().length == 0) { + // No roles associated with the application. + return false; + } + + List associatedRoles = Arrays.asList(associatedRolesConfig.getRoles()); + List allowedRoleListToRemove = new ArrayList<>(); + for (String roleName : roleListToRemove) { + // Check if the provided role name is associated with the application. + Optional roleOptional = + associatedRoles.stream().filter(role -> role.getName().equals(roleName)).findFirst(); + roleOptional.ifPresent(allowedRoleListToRemove::add); + } + + if (allowedRoleListToRemove.isEmpty()) { + return false; + } + + for (RoleV2 role : allowedRoleListToRemove) { + try { + UserFunctionsServiceHolder.getInstance().getRoleManagementService() + .updateUserListOfRole(role.getId(), Collections.emptyList(), + Collections.singletonList(subject.getUserId()), tenantDomain); + } catch (IdentityRoleManagementException | UserIdNotFoundException e) { + LOG.error("Error occurred while updating the roles of the user", e); + return false; + } + } + + return true; + } } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceComponent.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceComponent.java index 44419b2c..7ad30c96 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceComponent.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceComponent.java @@ -29,9 +29,14 @@ import org.osgi.service.component.annotations.ReferencePolicy; import org.wso2.carbon.identity.application.authentication.framework.JsFunctionRegistry; import org.wso2.carbon.identity.application.authentication.framework.UserSessionManagementService; +import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.identity.conditional.auth.functions.user.AssignUserRolesFunction; import org.wso2.carbon.identity.conditional.auth.functions.user.AssignUserRolesFunctionImpl; +import org.wso2.carbon.identity.conditional.auth.functions.user.AssignUserRolesV2Function; +import org.wso2.carbon.identity.conditional.auth.functions.user.AssignUserRolesV2FunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.CheckSessionExistenceFunctionImpl; +import org.wso2.carbon.identity.conditional.auth.functions.user.HasAnyOfTheRolesV2Function; +import org.wso2.carbon.identity.conditional.auth.functions.user.HasAnyOfTheRolesV2FunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.MicrosoftEmailVerificationFunction; import org.wso2.carbon.identity.conditional.auth.functions.user.MicrosoftEmailVerificationFunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.GetAssociatedLocalUserFunction; @@ -49,9 +54,12 @@ import org.wso2.carbon.identity.conditional.auth.functions.user.PromptIdentifierFunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.RemoveUserRolesFunction; import org.wso2.carbon.identity.conditional.auth.functions.user.RemoveUserRolesFunctionImpl; +import org.wso2.carbon.identity.conditional.auth.functions.user.RemoveUserRolesV2Function; +import org.wso2.carbon.identity.conditional.auth.functions.user.RemoveUserRolesV2FunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.TerminateUserSessionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.SetAccountAssociationToLocalUserImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.SetAccountAssociationToLocalUser; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; import org.wso2.carbon.idp.mgt.IdpManager; import org.wso2.carbon.user.core.service.RealmService; @@ -74,6 +82,9 @@ protected void activate(ComponentContext ctxt) { HasRoleFunction hasRoleFunctionImpl = new HasRoleFunctionImpl(); IsMemberOfAnyOfGroupsFunction isMemberOfAnyOfGroupsFunctionImpl = new IsMemberOfAnyOfGroupsFunctionImpl(); HasAnyOfTheRolesFunction hasAnyOfTheRolesFunctionImpl = new HasAnyOfTheRolesFunctionImpl(); + AssignUserRolesV2Function assignUserRolesV2FunctionImpl = new AssignUserRolesV2FunctionImpl(); + HasAnyOfTheRolesV2Function hasAnyOfTheRolesV2FunctionImpl = new HasAnyOfTheRolesV2FunctionImpl(); + RemoveUserRolesV2Function removeUserRolesV2FunctionImpl = new RemoveUserRolesV2FunctionImpl(); AssignUserRolesFunction assignUserRolesFunctionImpl = new AssignUserRolesFunctionImpl(); RemoveUserRolesFunction removeUserRolesFunctionImpl = new RemoveUserRolesFunctionImpl(); GetAssociatedLocalUserFunction getAssociatedLocalUserFunctionImpl = new GetAssociatedLocalUserFunctionImpl(); @@ -84,12 +95,18 @@ protected void activate(ComponentContext ctxt) { jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "hasRole", hasRoleFunctionImpl); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "hasAnyOfTheRoles", hasAnyOfTheRolesFunctionImpl); + jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "hasAnyOfTheRolesV2", + hasAnyOfTheRolesV2FunctionImpl); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "isMemberOfAnyOfGroups", isMemberOfAnyOfGroupsFunctionImpl); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "assignUserRoles", assignUserRolesFunctionImpl); + jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "assignUserRolesV2", + assignUserRolesV2FunctionImpl); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "removeUserRoles", removeUserRolesFunctionImpl); + jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "removeUserRolesV2", + removeUserRolesV2FunctionImpl); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "promptIdentifierForStep", new PromptIdentifierFunctionImpl()); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "checkSessionExistence", @@ -120,6 +137,7 @@ protected void deactivate(ComponentContext ctxt) { if (jsFunctionRegistry != null) { jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "hasRole"); jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "hasAnyOfTheRoles"); + jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "hasAnyOfTheRolesV2"); jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "isMemberOfAnyOfGroups"); jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "promptIdentifierForStep"); jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "checkSessionExistence"); @@ -219,4 +237,47 @@ protected void unsetIdentityProviderManagementService(IdpManager idpManager) { UserFunctionsServiceHolder.getInstance().setIdentityProviderManagementService(null); } + @Reference(name = "application.mgt.service", + service = ApplicationManagementService.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetApplicationManagementService") + protected void setApplicationManagementService(ApplicationManagementService applicationManagementService) { + + UserFunctionsServiceHolder.getInstance().setApplicationManagementService(applicationManagementService); + if (LOG.isDebugEnabled()) { + LOG.debug("Application management service is set in the conditional authentication user functions bundle."); + } + } + + protected void unsetApplicationManagementService(ApplicationManagementService applicationManagementService) { + + UserFunctionsServiceHolder.getInstance().setApplicationManagementService(null); + if (LOG.isDebugEnabled()) { + LOG.debug("Application management service is unset in the conditional authentication user functions " + + "bundle"); + } + } + + @Reference( + name = "role.management.service.v2", + service = RoleManagementService.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetRoleManagementService") + protected void setRoleManagementService(RoleManagementService roleManagementService) { + + UserFunctionsServiceHolder.getInstance().setRoleManagementService(roleManagementService); + if (LOG.isDebugEnabled()) { + LOG.debug("Role management service is set in the conditional authentication user functions bundle."); + } + } + + protected void unsetRoleManagementService(RoleManagementService roleManagementService) { + + UserFunctionsServiceHolder.getInstance().setRoleManagementService(null); + if (LOG.isDebugEnabled()) { + LOG.debug("Role management service is unset in the conditional authentication user functions bundle"); + } + } } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceHolder.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceHolder.java index 8ae363cf..08141c8e 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceHolder.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceHolder.java @@ -20,6 +20,8 @@ import org.wso2.carbon.identity.application.authentication.framework.JsFunctionRegistry; import org.wso2.carbon.identity.application.authentication.framework.UserSessionManagementService; +import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; import org.wso2.carbon.idp.mgt.IdpManager; import org.wso2.carbon.user.core.service.RealmService; @@ -30,6 +32,8 @@ public class UserFunctionsServiceHolder { private RealmService realmService; private UserSessionManagementService userSessionManagementService; private IdpManager identityProviderManagementService; + private ApplicationManagementService applicationManagementService; + private RoleManagementService roleManagementService; private JsFunctionRegistry jsFunctionRegistry; private UserFunctionsServiceHolder() { @@ -73,6 +77,26 @@ public void setIdentityProviderManagementService(IdpManager identityProviderMana this.identityProviderManagementService = identityProviderManagementService; } + public ApplicationManagementService getApplicationManagementService() { + + return applicationManagementService; + } + + public void setApplicationManagementService(ApplicationManagementService applicationManagementService) { + + this.applicationManagementService = applicationManagementService; + } + + public RoleManagementService getRoleManagementService() { + + return roleManagementService; + } + + public void setRoleManagementService(RoleManagementService roleManagementService) { + + this.roleManagementService = roleManagementService; + } + public JsFunctionRegistry getJsFunctionRegistry() { return jsFunctionRegistry;