From 1f706d3db729f6cd44971b0436ebe19d14385e49 Mon Sep 17 00:00:00 2001 From: shuhaib-aot Date: Wed, 5 Jun 2024 13:30:45 +0530 Subject: [PATCH 01/60] FWF-3381 [Feature] changed customRoles=user group --- forms-flow-api/src/formsflow_api/resources/formio.py | 2 +- forms-flow-api/tests/unit/api/test_formio.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/forms-flow-api/src/formsflow_api/resources/formio.py b/forms-flow-api/src/formsflow_api/resources/formio.py index f241f479c2..5e5020e7a3 100644 --- a/forms-flow-api/src/formsflow_api/resources/formio.py +++ b/forms-flow-api/src/formsflow_api/resources/formio.py @@ -120,7 +120,7 @@ def add_jwt_token_as_header(response): payload: Dict[str, any] = { "external": True, "form": {"_id": _resource_id}, - "user": {"_id": unique_user_id, "roles": _role_ids, "customRoles": user.roles}, + "user": {"_id": unique_user_id, "roles": _role_ids, "customRoles": user._groups}, } if project_id: payload["project"] = {"_id": project_id} diff --git a/forms-flow-api/tests/unit/api/test_formio.py b/forms-flow-api/tests/unit/api/test_formio.py index e985c62603..2c00d8d1a3 100644 --- a/forms-flow-api/tests/unit/api/test_formio.py +++ b/forms-flow-api/tests/unit/api/test_formio.py @@ -19,7 +19,7 @@ def test_formio_roles(app, client, session, jwt, mock_redis_client): Cache.set("user_resource_id", resource_id, timeout=0) # Requesting from client role - token = get_token(jwt, role="formsflow-client") + token = get_token(jwt, role="/formsflow/formsflow-designer") headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} response = client.get("/formio/roles", headers=headers) @@ -32,7 +32,7 @@ def test_formio_roles(app, client, session, jwt, mock_redis_client): key=app.config["FORMIO_JWT_SECRET"], ) assert decoded_token["form"]["_id"] == resource_id - assert decoded_token["user"]["customRoles"] == ["formsflow-client"] + assert decoded_token["user"]["customRoles"] == ["/formsflow/formsflow-designer"] # Requesting from reviewer role token = get_token(jwt, role="formsflow-reviewer") From 203efc3e7412a54384612762bf93f0c9d91ee020 Mon Sep 17 00:00:00 2001 From: auslin-aot Date: Wed, 5 Jun 2024 16:09:14 +0530 Subject: [PATCH 02/60] FWF-3325: [Feature] Save group role mapping --- .../src/formsflow_api/schemas/roles.py | 1 + .../factory/keycloak_client_service.py | 22 +++++++++++++------ .../factory/keycloak_group_service.py | 22 +++++++++++++++++++ forms-flow-api/tests/unit/api/test_roles.py | 2 +- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/forms-flow-api/src/formsflow_api/schemas/roles.py b/forms-flow-api/src/formsflow_api/schemas/roles.py index 22ec4d2aef..26a8bca7a8 100644 --- a/forms-flow-api/src/formsflow_api/schemas/roles.py +++ b/forms-flow-api/src/formsflow_api/schemas/roles.py @@ -14,3 +14,4 @@ class Meta: # pylint: disable=too-few-public-methods id = fields.Str(dump_only=True) name = fields.Str(required=True) description = fields.Str() + permissions = fields.List(fields.Str()) diff --git a/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py b/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py index 5080c78555..f49abc628b 100644 --- a/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py +++ b/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py @@ -12,6 +12,7 @@ from formsflow_api.services import KeycloakAdminAPIService, UserService from .keycloak_admin import KeycloakAdmin +from .keycloak_group_service import KeycloakGroupService class KeycloakClientService(KeycloakAdmin): @@ -93,14 +94,21 @@ def delete_group(self, group_id: str): url_path=f"clients/{client_id}/roles/{group_id}" ) - def create_group_role(self, data: Dict): + @user_context + def create_group_role(self, data: Dict, **kwargs): """Create role.""" - client_id = self.client.get_client_id() - response = self.client.create_request( - url_path=f"clients/{client_id}/roles", data=data - ) - role_name = response.headers["Location"].split("/")[-1] - return {"id": role_name} + current_app.logger.debug("Creating tenant group...") + user: UserContext = kwargs["user"] + tenant_key = user.tenant_key + # Append tenantKey to group in the group hierarchy. + # If user input is "group/sub-group" append tenantKey to each group + groups = [group for group in data["name"].split("/") if group] + appended_groups = [f"{tenant_key}-{group}" for group in groups] + + data["name"] = "/".join(appended_groups) + current_app.logger.debug(f"Tenant group: {data['name']}") + group_servie = KeycloakGroupService() + return group_servie.create_group_role(data) def add_user_to_group_role(self, user_id: str, group_id: str, payload: Dict): """Add user to role.""" diff --git a/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py b/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py index f3fc166739..bb4cc20128 100644 --- a/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py +++ b/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py @@ -91,6 +91,7 @@ def create_group_role(self, data: Dict): Split name parameter to create group/subgroups """ + permissions = data.pop("permissions") data = self.add_description(data) data["name"] = ( data["name"].lstrip("/") if data["name"].startswith("/") else data["name"] @@ -119,6 +120,8 @@ def create_group_role(self, data: Dict): ) group_id = response["id"] url_path = f"groups/{group_id}/children" + client_id = self.client.get_client_id() + self.create_group_permission_mapping(group_id, permissions, client_id) return {"id": group_id} def add_description(self, data: Dict): @@ -218,3 +221,22 @@ def add_user_to_tenant(self, data: Dict): return { "message": "The requested operation is not supported." }, HTTPStatus.BAD_REQUEST + + def create_group_permission_mapping(self, group_id, permissions, client_id): + """Set permission mapping to group.""" + current_app.logger.debug("Setting permission mapping to group") + roles = self.client.get_roles() + role_data_list = [] + for role in roles: + if permissions and role.get("name") in permissions: + role_data = { + "containerId": client_id, + "id": role.get("id"), + "clientRole": True, + "name": role.get("name"), + } + role_data_list.append(role_data) + self.client.create_request( + url_path=f"groups/{group_id}/role-mappings/clients/{client_id}", + data=role_data_list, + ) diff --git a/forms-flow-api/tests/unit/api/test_roles.py b/forms-flow-api/tests/unit/api/test_roles.py index c8c3779b37..f6d3e73f95 100644 --- a/forms-flow-api/tests/unit/api/test_roles.py +++ b/forms-flow-api/tests/unit/api/test_roles.py @@ -24,7 +24,7 @@ def test_keycloak_role_crud(self, app, client, session, jwt): "content-type": "application/json", } # Create new user group. - data = {"name": "new-test-group", "description": "Group"} + data = {"name": "new-test-group", "description": "Group", "permissions": ["view_designs", "create_designs"]} rv = client.post("/roles", headers=headers, json=data) assert rv.status_code == 201 assert rv.json.get("id") is not None From 90c7a357e93f4f1d73fed71b4ee389d5de864964 Mon Sep 17 00:00:00 2001 From: auslin-aot Date: Thu, 6 Jun 2024 11:16:17 +0530 Subject: [PATCH 03/60] FWF-3325: [Feature] Added tenantKey to main group --- .../services/factory/keycloak_client_service.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py b/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py index f49abc628b..dd04b43c0a 100644 --- a/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py +++ b/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py @@ -96,19 +96,16 @@ def delete_group(self, group_id: str): @user_context def create_group_role(self, data: Dict, **kwargs): - """Create role.""" + """Create tenant group.""" current_app.logger.debug("Creating tenant group...") user: UserContext = kwargs["user"] tenant_key = user.tenant_key - # Append tenantKey to group in the group hierarchy. - # If user input is "group/sub-group" append tenantKey to each group - groups = [group for group in data["name"].split("/") if group] - appended_groups = [f"{tenant_key}-{group}" for group in groups] - - data["name"] = "/".join(appended_groups) + name = data["name"].lstrip("/") + # Prefix the tenant_key to the main group + data["name"] = f"{tenant_key}-{name}" current_app.logger.debug(f"Tenant group: {data['name']}") - group_servie = KeycloakGroupService() - return group_servie.create_group_role(data) + group_service = KeycloakGroupService() + return group_service.create_group_role(data) def add_user_to_group_role(self, user_id: str, group_id: str, payload: Dict): """Add user to role.""" From 2e330977348dbc39e3547d992d2b50ecfc52bd3e Mon Sep 17 00:00:00 2001 From: shuhaib-aot Date: Thu, 6 Jun 2024 13:07:45 +0530 Subject: [PATCH 04/60] FWF:3381 [feature] Added tenantkey filteration in groups --- forms-flow-api/src/formsflow_api/resources/formio.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/forms-flow-api/src/formsflow_api/resources/formio.py b/forms-flow-api/src/formsflow_api/resources/formio.py index 5e5020e7a3..c8e1af95cf 100644 --- a/forms-flow-api/src/formsflow_api/resources/formio.py +++ b/forms-flow-api/src/formsflow_api/resources/formio.py @@ -117,10 +117,20 @@ def add_jwt_token_as_header(response): user.email or f"{user.user_name}@formsflow.ai" ) # Email is not mandatory in keycloak project_id: str = current_app.config.get("FORMIO_PROJECT_URL") + groups = user._groups + if user.tenant_key: + groups = [ + group for group in groups if group.startswith(f"/{user.tenant_key}") + ] + payload: Dict[str, any] = { "external": True, "form": {"_id": _resource_id}, - "user": {"_id": unique_user_id, "roles": _role_ids, "customRoles": user._groups}, + "user": { + "_id": unique_user_id, + "roles": _role_ids, + "customRoles": user._groups, + }, } if project_id: payload["project"] = {"_id": project_id} From 82db45357a60c2f078a1e709ca88046cfa8bb7ee Mon Sep 17 00:00:00 2001 From: auslin-aot Date: Thu, 6 Jun 2024 15:08:39 +0530 Subject: [PATCH 05/60] FWF-3325: [Feature] group role mapping changes in roles crud --- .../factory/keycloak_client_service.py | 60 ++++++++----------- .../factory/keycloak_group_service.py | 33 +++++++++- 2 files changed, 57 insertions(+), 36 deletions(-) diff --git a/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py b/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py index dd04b43c0a..a321ce7931 100644 --- a/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py +++ b/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py @@ -22,6 +22,7 @@ def __init__(self): """Initialize client.""" self.client = KeycloakAdminAPIService() self.user_service = UserService() + self.group_service = KeycloakGroupService() def __populate_user_roles(self, user_list: List) -> List: """Collects roles for a user list and populates the role attribute.""" @@ -36,13 +37,8 @@ def get_analytics_groups(self, page_no: int, limit: int): return self.client.get_analytics_roles(page_no, limit) def get_group(self, group_id: str): - """Get role by role name.""" - client_id = self.client.get_client_id() - response = self.client.get_request( - url_path=f"clients/{client_id}/roles/{group_id}" - ) - response["id"] = response.get("name", None) - return response + """Get group by group_id.""" + return self.group_service.get_group(group_id) def get_users( # pylint: disable-msg=too-many-arguments self, @@ -72,40 +68,23 @@ def get_users( # pylint: disable-msg=too-many-arguments return (users_list, users_count) def update_group(self, group_id: str, data: Dict): - """Update keycloak role by role name.""" - client_id = self.client.get_client_id() - return self.client.update_request( - url_path=f"clients/{client_id}/roles/{group_id}", - data=data, - ) + """Update keycloak group.""" + data = self.append_tenant_key(data) + return self.group_service.update_group(group_id, data) def get_groups_roles(self, search: str, sort_order: str): - """Get roles.""" - response = self.client.get_roles(search) - for role in response: - role["id"] = role.get("id") - role["description"] = role.get("description") - return self.sort_results(response, sort_order) + """Get groups.""" + return self.group_service.get_groups_roles(search, sort_order) def delete_group(self, group_id: str): - """Delete role by role name.""" - client_id = self.client.get_client_id() - return self.client.delete_request( - url_path=f"clients/{client_id}/roles/{group_id}" - ) + """Delete group.""" + return self.client.delete_request(url_path=f"groups/{group_id}") - @user_context - def create_group_role(self, data: Dict, **kwargs): - """Create tenant group.""" + def create_group_role(self, data: Dict): + """Create group.""" current_app.logger.debug("Creating tenant group...") - user: UserContext = kwargs["user"] - tenant_key = user.tenant_key - name = data["name"].lstrip("/") - # Prefix the tenant_key to the main group - data["name"] = f"{tenant_key}-{name}" - current_app.logger.debug(f"Tenant group: {data['name']}") - group_service = KeycloakGroupService() - return group_service.create_group_role(data) + self.append_tenant_key(data) + return self.group_service.create_group_role(data) def add_user_to_group_role(self, user_id: str, group_id: str, payload: Dict): """Add user to role.""" @@ -211,3 +190,14 @@ def add_user_to_tenant( ) return {"message": "User added to tenant"}, HTTPStatus.OK raise BusinessException(BusinessErrorCode.USER_NOT_FOUND) + + @user_context + def append_tenant_key(self, data, **kwargs): # pylint: disable=too-many-locals + """Append tenantkey to main group.""" + user: UserContext = kwargs["user"] + tenant_key = user.tenant_key + name = data["name"].lstrip("/") + # Prefix the tenant_key to the main group + data["name"] = f"{tenant_key}-{name}" + current_app.logger.debug(f"Tenant group: {data['name']}") + return data diff --git a/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py b/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py index bb4cc20128..2d0327e5d1 100644 --- a/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py +++ b/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py @@ -6,6 +6,7 @@ import requests from flask import current_app from formsflow_api_utils.exceptions import BusinessException +from formsflow_api_utils.utils.user_context import UserContext, user_context from formsflow_api.constants import BusinessErrorCode from formsflow_api.services import KeycloakAdminAPIService, UserService @@ -69,8 +70,10 @@ def get_users( # pylint: disable-msg=too-many-arguments def update_group(self, group_id: str, data: Dict): """Update group details.""" + permissions = data.pop("permissions") data = self.add_description(data) data["name"] = data["name"].split("/")[-1] + self.update_group_permission_mapping(group_id, permissions) return self.client.update_request(url_path=f"groups/{group_id}", data=data) def get_groups_roles(self, search: str, sort_order: str): @@ -174,9 +177,13 @@ def search_group(self, search, data): ) return search_list - def format_response(self, data): + @user_context + def format_response(self, data, **kwargs): """Format group response.""" + user: UserContext = kwargs["user"] + tenant_key = user.tenant_key data["description"] = "" + data["permissions"] = [] data["name"] = data.get("path") if data.get("attributes") != {}: # Reaarange description data["description"] = ( @@ -184,6 +191,11 @@ def format_response(self, data): if data["attributes"].get("description") else "" ) + if data.get("clientRoles") != {}: # Reaarange permissions + client_role = f"{tenant_key}-forms-flow-web" if tenant_key else "forms-flow-web" + client_roles = data['clientRoles'].get(client_role) + if client_roles: + data["permissions"] = client_roles return data def add_user_to_group_role(self, user_id: str, group_id: str, payload: Dict): @@ -240,3 +252,22 @@ def create_group_permission_mapping(self, group_id, permissions, client_id): url_path=f"groups/{group_id}/role-mappings/clients/{client_id}", data=role_data_list, ) + + def update_group_permission_mapping(self, group_id, permissions): + """Update permission mapping to group.""" + current_app.logger.debug("Updating permission mapping to group") + client_id = self.client.get_client_id() + permission_list = self.client.get_request( + url_path=f"groups/{group_id}/role-mappings/clients/{client_id}" + ) + + # Determine permissions to remove + role_remove_data_list = [] + for permission in permission_list: + if permission['name'] not in permissions: + role_remove_data_list.append(permission) + self.client.delete_request( + url_path=f"groups/{group_id}/role-mappings/clients/{client_id}", data=role_remove_data_list + ) + # Add permissions + self.create_group_permission_mapping(group_id, permissions, client_id) From 3f3cfb965f314f5efb8a38d2c90535a022916108 Mon Sep 17 00:00:00 2001 From: auslin-aot Date: Fri, 7 Jun 2024 14:35:54 +0530 Subject: [PATCH 06/60] FWF-3325: [Feature] Updated GroupService as baseclass for ClientService --- .../factory/keycloak_client_service.py | 26 +++---------------- .../factory/keycloak_group_service.py | 4 ++- forms-flow-api/tests/unit/api/test_roles.py | 2 +- 3 files changed, 7 insertions(+), 25 deletions(-) diff --git a/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py b/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py index a321ce7931..09af719813 100644 --- a/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py +++ b/forms-flow-api/src/formsflow_api/services/factory/keycloak_client_service.py @@ -9,21 +9,13 @@ from formsflow_api_utils.utils.user_context import UserContext, user_context from formsflow_api.constants import BusinessErrorCode -from formsflow_api.services import KeycloakAdminAPIService, UserService -from .keycloak_admin import KeycloakAdmin from .keycloak_group_service import KeycloakGroupService -class KeycloakClientService(KeycloakAdmin): +class KeycloakClientService(KeycloakGroupService): """Keycloak Admin implementation for client related operations.""" - def __init__(self): - """Initialize client.""" - self.client = KeycloakAdminAPIService() - self.user_service = UserService() - self.group_service = KeycloakGroupService() - def __populate_user_roles(self, user_list: List) -> List: """Collects roles for a user list and populates the role attribute.""" for user in user_list: @@ -36,10 +28,6 @@ def get_analytics_groups(self, page_no: int, limit: int): """Get analytics roles.""" return self.client.get_analytics_roles(page_no, limit) - def get_group(self, group_id: str): - """Get group by group_id.""" - return self.group_service.get_group(group_id) - def get_users( # pylint: disable-msg=too-many-arguments self, page_no: int, @@ -70,21 +58,13 @@ def get_users( # pylint: disable-msg=too-many-arguments def update_group(self, group_id: str, data: Dict): """Update keycloak group.""" data = self.append_tenant_key(data) - return self.group_service.update_group(group_id, data) - - def get_groups_roles(self, search: str, sort_order: str): - """Get groups.""" - return self.group_service.get_groups_roles(search, sort_order) - - def delete_group(self, group_id: str): - """Delete group.""" - return self.client.delete_request(url_path=f"groups/{group_id}") + return super().update_group(group_id, data) def create_group_role(self, data: Dict): """Create group.""" current_app.logger.debug("Creating tenant group...") self.append_tenant_key(data) - return self.group_service.create_group_role(data) + return super().create_group_role(data) def add_user_to_group_role(self, user_id: str, group_id: str, payload: Dict): """Add user to role.""" diff --git a/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py b/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py index 2d0327e5d1..38cdcff0f8 100644 --- a/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py +++ b/forms-flow-api/src/formsflow_api/services/factory/keycloak_group_service.py @@ -192,7 +192,9 @@ def format_response(self, data, **kwargs): else "" ) if data.get("clientRoles") != {}: # Reaarange permissions - client_role = f"{tenant_key}-forms-flow-web" if tenant_key else "forms-flow-web" + client_name = current_app.config.get("JWT_OIDC_AUDIENCE") + client_role = f"{tenant_key}-{client_name}" if tenant_key else client_name + current_app.logger.debug("Client name %s", client_role) client_roles = data['clientRoles'].get(client_role) if client_roles: data["permissions"] = client_roles diff --git a/forms-flow-api/tests/unit/api/test_roles.py b/forms-flow-api/tests/unit/api/test_roles.py index f6d3e73f95..2572ac29ee 100644 --- a/forms-flow-api/tests/unit/api/test_roles.py +++ b/forms-flow-api/tests/unit/api/test_roles.py @@ -30,7 +30,7 @@ def test_keycloak_role_crud(self, app, client, session, jwt): assert rv.json.get("id") is not None id = rv.json.get("id") # Update group. - data = {"name": "new-test-group", "description": "Test Group"} + data = {"name": "new-test-group", "description": "Test Group", "permissions": ["view_designs", "create_designs"]} rv = client.put(f"/roles/{id}", headers=headers, json=data) assert rv.status_code == 200 # Get group by id. From cbe6cf41f46e3c74a98484352881fe39a407ec8b Mon Sep 17 00:00:00 2001 From: abilpraju-aot Date: Wed, 12 Jun 2024 11:12:32 +0530 Subject: [PATCH 07/60] updated relm --- .../keycloak/imports/formsflow-ai-realm.json | 1929 ++++++++++------- 1 file changed, 1119 insertions(+), 810 deletions(-) diff --git a/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json b/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json index 204089d1e4..6d3c0997a0 100644 --- a/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json +++ b/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json @@ -50,6 +50,26 @@ "containerId": "forms-flow-ai", "attributes": {} }, + { + "name": "default-roles-forms-flow-ai", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "view-profile", + "manage-account" + ] + } + }, + "clientRole": false, + "containerId": "forms-flow-ai", + "attributes": {} + }, { "name": "uma_authorization", "description": "${role_uma_authorization}", @@ -62,11 +82,10 @@ "client": { "realm-management": [ { - "name": "query-groups", - "description": "${role_query-groups}", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", "composite": false, "clientRole": true, - "attributes": {} }, { @@ -74,31 +93,34 @@ "description": "${role_query-clients}", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "view-events", - "description": "${role_view-events}", + "name": "manage-authorization", + "description": "${role_manage-authorization}", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "impersonation", - "description": "${role_impersonation}", - "composite": false, + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, "clientRole": true, - "attributes": {} }, { - "name": "manage-events", - "description": "${role_manage-events}", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", "composite": false, "clientRole": true, - "attributes": {} }, { @@ -106,54 +128,34 @@ "description": "${role_query-realms}", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "query-users", - "description": "${role_query-users}", + "name": "view-realm", + "description": "${role_view-realm}", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "create-client", - "description": "${role_create-client}", + "name": "impersonation", + "description": "${role_impersonation}", "composite": false, "clientRole": true, - - "attributes": {} - }, - { - "name": "view-clients", - "description": "${role_view-clients}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "query-clients" - ] - } - }, - "clientRole": true, - "attributes": {} }, { - "name": "manage-authorization", - "description": "${role_manage-authorization}", + "name": "query-groups", + "description": "${role_query-groups}", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "view-identity-providers", - "description": "${role_view-identity-providers}", + "name": "view-authorization", + "description": "${role_view-authorization}", "composite": false, "clientRole": true, - "attributes": {} }, { @@ -163,13 +165,19 @@ "composites": { "client": { "realm-management": [ - "query-users", - "query-groups" + "query-groups", + "query-users" ] } }, "clientRole": true, - + "attributes": {} + }, + { + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, "attributes": {} }, { @@ -179,53 +187,49 @@ "composites": { "client": { "realm-management": [ - "query-groups", + "manage-identity-providers", "query-clients", - "view-events", - "impersonation", - "manage-events", - "query-realms", - "query-users", - "create-client", - "view-clients", "manage-authorization", "view-identity-providers", - "view-users", + "view-clients", + "query-realms", "view-realm", + "impersonation", + "query-groups", "view-authorization", - "manage-identity-providers", + "view-users", + "create-client", + "view-events", + "manage-clients", "manage-users", - "manage-realm", - "manage-clients" + "query-users", + "manage-events", + "manage-realm" ] } }, "clientRole": true, - "attributes": {} }, { - "name": "view-realm", - "description": "${role_view-realm}", + "name": "view-events", + "description": "${role_view-events}", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "view-authorization", - "description": "${role_view-authorization}", + "name": "manage-clients", + "description": "${role_manage-clients}", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "manage-identity-providers", - "description": "${role_manage-identity-providers}", + "name": "manage-events", + "description": "${role_manage-events}", "composite": false, "clientRole": true, - "attributes": {} }, { @@ -236,45 +240,117 @@ "attributes": {} }, { - "name": "manage-realm", - "description": "${role_manage-realm}", + "name": "query-users", + "description": "${role_query-users}", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "manage-clients", - "description": "${role_manage-clients}", + "name": "manage-realm", + "description": "${role_manage-realm}", "composite": false, "clientRole": true, - "attributes": {} } ], "forms-flow-web": [ { - "name": "formsflow-client", - "description": "Provides access to use the formsflow.ai solution. Required to access and submit forms.", + "name": "manage_tasks", + "description": "Can claim and work on tasks", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "formsflow-designer", - "description": "Provides access to use the formsflow.ai solution. Access to wok on form designer studio.", + "name": "view_tasks", + "description": "Access to tasks", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "formsflow-reviewer", - "description": "Provides access to use the formsflow.ai solution. Identifies the staff to work on applications and forms submissions.", + "name": "view_submissions", + "description": "Access to submissions", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "create_submissions", + "description": "Create submissions", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "manage_all_filters", + "description": "Manage all filters", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "view_designs", + "description": "Access to design", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "manage_dashboard_authorizations", + "description": "Manage Dashboard Authorization", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "view_filters", + "description": "Access to view filters", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "manage_roles", + "description": "Manage Roles", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "manage_integrations", + "description": "Access to Integrations", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "create_filters", + "description": "Access to create filters", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "manage_users", + "description": "Manage Users", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "create_designs", + "description": "Create Form, workflow designs", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "view_dashboards", + "description": "Access to dashboards", "composite": false, "clientRole": true, - "attributes": {} } ], @@ -288,33 +364,23 @@ "description": "${role_read-token}", "composite": false, "clientRole": true, - "attributes": {} } ], "forms-flow-analytics": [], "account": [ { - "name": "view-profile", - "description": "${role_view-profile}", + "name": "view-applications", + "description": "${role_view-applications}", "composite": false, "clientRole": true, - "attributes": {} }, { - "name": "manage-account", - "description": "${role_manage-account}", - "composite": true, - "composites": { - "client": { - "account": [ - "manage-account-links" - ] - } - }, + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, "clientRole": true, - "attributes": {} }, { @@ -322,7 +388,6 @@ "description": "${role_manage-account-links}", "composite": false, "clientRole": true, - "attributes": {} }, { @@ -330,7 +395,6 @@ "description": "${role_view-consent}", "composite": false, "clientRole": true, - "attributes": {} }, { @@ -345,15 +409,34 @@ } }, "clientRole": true, - "attributes": {} }, { - "name": "view-applications", - "description": "${role_view-applications}", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "attributes": {} + }, + { + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "delete-account", + "description": "${role_delete-account}", "composite": false, "clientRole": true, - "attributes": {} } ] @@ -363,103 +446,138 @@ { "name": "camunda-admin", "path": "/camunda-admin", + "subGroups": [], "attributes": {}, "realmRoles": [], - "clientRoles": {}, - "subGroups": [] + "clientRoles": {} }, { "name": "formsflow", "path": "/formsflow", - "attributes": {}, - "realmRoles": [], - "clientRoles": {}, "subGroups": [ + { + "name": "formsflow-admin", + "path": "/formsflow/formsflow-admin", + "subGroups": [], + "attributes": {}, + "realmRoles": [], + "clientRoles": { + "realm-management": [ + "query-clients", + "view-clients", + "query-groups", + "view-authorization", + "view-users", + "create-client", + "manage-clients", + "manage-users", + "query-users" + ], + "forms-flow-web": [ + "manage_roles", + "manage_integrations", + "manage_users" + ] + } + }, { "name": "formsflow-client", "path": "/formsflow/formsflow-client", + "subGroups": [], "attributes": {}, "realmRoles": [], "clientRoles": { "forms-flow-web": [ - "formsflow-client" + "view_submissions", + "create_submissions" ] - }, - "subGroups": [] + } }, { "name": "formsflow-designer", "path": "/formsflow/formsflow-designer", + "subGroups": [], "attributes": {}, "realmRoles": [], "clientRoles": { "forms-flow-web": [ - "formsflow-designer" + "create_designs", + "view_designs" ] - }, - "subGroups": [] + } }, { "name": "formsflow-reviewer", "path": "/formsflow/formsflow-reviewer", + "subGroups": [ + { + "name": "approver", + "path": "/formsflow/formsflow-reviewer/approver", + "subGroups": [], + "attributes": {}, + "realmRoles": [], + "clientRoles": {} + }, + { + "name": "clerk", + "path": "/formsflow/formsflow-reviewer/clerk", + "subGroups": [], + "attributes": {}, + "realmRoles": [], + "clientRoles": {} + } + ], "attributes": {}, "realmRoles": [], "clientRoles": { "forms-flow-web": [ - "formsflow-reviewer" + "manage_tasks", + "view_tasks", + "create_filters", + "view_dashboards", + "view_submissions", + "view_filters" ] - }, - "subGroups": [ - { - "name": "clerk", - "path": "/formsflow/formsflow-reviewer/clerk", - "attributes": {}, - "realmRoles": [], - "clientRoles": {}, - "subGroups": [] - }, - { - "name": "approver", - "path": "/formsflow/formsflow-reviewer/approver", - "attributes": {}, - "realmRoles": [], - "clientRoles": {}, - "subGroups": [] - } - ] + } } - ] + ], + "attributes": {}, + "realmRoles": [], + "clientRoles": {} }, { "name": "formsflow-analytics", "path": "/formsflow-analytics", - "attributes": {}, - "realmRoles": [], - "clientRoles": {}, "subGroups": [ { - "name": "group2", - "path": "/formsflow-analytics/group2", + "name": "group1", + "path": "/formsflow-analytics/group1", + "subGroups": [], "attributes": {}, "realmRoles": [], - "clientRoles": {}, - "subGroups": [] + "clientRoles": {} }, { - "name": "group1", - "path": "/formsflow-analytics/group1", + "name": "group2", + "path": "/formsflow-analytics/group2", + "subGroups": [], "attributes": {}, "realmRoles": [], - "clientRoles": {}, - "subGroups": [] + "clientRoles": {} } - ] + ], + "attributes": {}, + "realmRoles": [], + "clientRoles": {} } ], - "defaultRoles": [ - "offline_access", - "uma_authorization" - ], + "defaultRole": { + "name": "default-roles-forms-flow-ai", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "forms-flow-ai" + }, "defaultGroups": [ "/camunda-admin", "/formsflow", @@ -474,10 +592,13 @@ "otpPolicyDigits": 6, "otpPolicyLookAheadWindow": 1, "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, "otpSupportedApplications": [ - "FreeOTP", - "Google Authenticator" + "totpAppFreeOTPName", + "totpAppGoogleName", + "totpAppMicrosoftAuthenticatorName" ], + "localizationTexts": {}, "webAuthnPolicyRpEntityName": "keycloak", "webAuthnPolicySignatureAlgorithms": [ "ES256" @@ -490,6 +611,7 @@ "webAuthnPolicyCreateTimeout": 0, "webAuthnPolicyAvoidSameAuthenticatorRegister": false, "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyExtraOrigins": [], "webAuthnPolicyPasswordlessRpEntityName": "keycloak", "webAuthnPolicyPasswordlessSignatureAlgorithms": [ "ES256" @@ -502,145 +624,281 @@ "webAuthnPolicyPasswordlessCreateTimeout": 0, "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, "webAuthnPolicyPasswordlessAcceptableAaguids": [], - "users" : [ { - "createdTimestamp" : 1621862607660, - "username" : "formsflow-client", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Client", - "lastName" : "FFA", - "email" : "formsflow-client@example.com", - "credentials" : [ { - "type" : "password", - "createdDate" : 1621863987325, - "secretData" : "{\"value\":\"9R9a8Onha7JcZt59SIq8ngfqwDJwPKiKb8mJ2WO6p2eI3S9qhzR1GPDFtKjOWq8qpm8vsGfp/a/DyHWQuIvmlA==\",\"salt\":\"R/OTBeSXHzsKtJOV/bufEA==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ "UPDATE_PASSWORD" ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "view-profile", "manage-account" ] - }, - "notBefore" : 0, - "groups" : [ "/camunda-admin", "/formsflow/formsflow-client" ] - }, { - "createdTimestamp" : 1621862546931, - "username" : "formsflow-designer", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Designer", - "lastName" : "FFA", - "email" : "formsflow-designer@example.com", - "credentials" : [ { - "type" : "password", - "createdDate" : 1621864001408, - "secretData" : "{\"value\":\"XlcFXNSJAfv5YzTh5vd4NtyEjWm4B47CS9MA3aHmEjLNjdRMbnGFVFZwlZx3alXYBCg4Evs3md25DQ6Xvl+nZg==\",\"salt\":\"TefHE1L0xpqlAMg/h6w6BA==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ "UPDATE_PASSWORD" ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "view-profile", "manage-account" ] - }, - "notBefore" : 0, - "groups" : [ "/camunda-admin", "/formsflow/formsflow-designer" ] - }, { - "createdTimestamp" : 1625009614956, - "username" : "formsflow-approver", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Approver", - "lastName" : "FFA", - "email" : "formsflow-approver@aot-technologies.com", - "credentials" : [ { - "type" : "password", - "createdDate" : 1625009625540, - "secretData" : "{\"value\":\"Ej6BGTe5D+jLChY9zmoty3Jzt8i+KoV+UTPK6+1Vi+GaUpVfdJ0RFJ/7M4+1Y1jNGBcvMgc8knQT2AJDtixxRQ==\",\"salt\":\"MDP6nouKEx0l7hdJA+lIJw==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ "UPDATE_PASSWORD" ], - "notBefore" : 0, - "groups" : [ "/formsflow/formsflow-reviewer/approver", "/camunda-admin", "/formsflow" , "/formsflow-analytics/group1"] - }, { - "createdTimestamp" : 1625009564217, - "username" : "formsflow-clerk", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Clerk", - "lastName" : "FFA", - "email" : "formsflow-clerk@aot-technologies.com", - "credentials" : [ { - "type" : "password", - "createdDate" : 1625009575561, - "secretData" : "{\"value\":\"iWFPywh7ck8FesufjXu81lxpJ0XKSvPd9ladBcJrE4TTXLeQOhvqBOC5e+bwVg20Y61EwtkTta0L9MWtGpSraw==\",\"salt\":\"noE1kDJ7Lo20VYuTOHOBTw==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ "UPDATE_PASSWORD" ], - "notBefore" : 0, - "groups" : [ "/camunda-admin", "/formsflow/formsflow-reviewer/clerk", "/formsflow", "/formsflow-analytics/group2" ] - }, { - "createdTimestamp" : 1621862578318, - "username" : "formsflow-reviewer", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Reviewer", - "lastName" : "FFA", - "email" : "formsflow-reviewer@example.com", - "credentials" : [ { - "type" : "password", - "createdDate" : 1621864014317, - "secretData" : "{\"value\":\"bXzhJ0BrMJBWMzRRjO2khWgCRgDAA6vfTrE0UNNO1DNRzp1aMrGCz5kF20H76PjyuqNDZaKF1nKApEjccg+KRA==\",\"salt\":\"gmoZwO3i7Y6B+jpgnsnixw==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ "UPDATE_PASSWORD" ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "view-profile", "manage-account" ] - }, - "notBefore" : 0, - "groups" : [ "/camunda-admin", "/formsflow/formsflow-reviewer", "/formsflow-analytics/group1" ] - }, { - "createdTimestamp" : 1621585233480, - "username" : "service-account-forms-flow-bpm", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "forms-flow-bpm", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "realm-management" : [ "manage-users", "query-users", "query-groups", "view-users" , "manage-clients", "realm-admin"], - "account" : [ "view-profile", "manage-account" ] - }, - "notBefore" : 0, - "groups" : [ "/camunda-admin" ] - } ], - "scopeMappings" : [ { - "clientScope" : "offline_access", - "roles" : [ "offline_access" ] - } ], - "clientScopeMappings" : { - "account" : [ { - "client" : "account-console", - "roles" : [ "manage-account" ] - } ] - }, - "clients": [ + "webAuthnPolicyPasswordlessExtraOrigins": [], + "users": [ { - "clientId": "account", - "name": "${client_account}", + "createdTimestamp": 1718023583532, + "username": "formsflow-admin", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "ff", + "lastName": "admin", + "email": "formsflow-admin@aot-technologies.com", + "credentials": [ + { + "id": "d4d8336d-ba33-47f7-9a7e-91269f8b4cc9", + "type": "password", + "userLabel": "My password", + "createdDate": 1718087465595, + "secretData": "{\"value\":\"EpHuQHA+nMza4usSNWSDxl6bZ9pbKFe4vOjuMMEZijQ=\",\"salt\":\"Ht1p7xh28sqw6+FZ1ICcOg==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [ + "UPDATE_PASSWORD" + ], + "realmRoles": [ + "default-roles-forms-flow-ai" + ], + "notBefore": 0, + "groups": [ + "/camunda-admin", + "/formsflow/formsflow-admin", + "/formsflow-analytics" + ] + }, + { + "createdTimestamp": 1625009614956, + "username": "formsflow-approver", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Approver", + "lastName": "FFA", + "email": "formsflow-approver@aot-technologies.com", + "credentials": [ + { + "id": "c6aac3fc-3483-4afd-b46f-223641f3fe56", + "type": "password", + "userLabel": "My password", + "createdDate": 1718087451516, + "secretData": "{\"value\":\"vfZT65WYqEjeUdOBL61DMke/qy6YE1zJFKyoMNdxvUo=\",\"salt\":\"+7nUoa1MU7YgyyKI4x+/FA==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [ + "UPDATE_PASSWORD" + ], + "notBefore": 0, + "groups": [ + "/formsflow/formsflow-reviewer/approver", + "/camunda-admin", + "/formsflow-analytics/group1" + ] + }, + { + "createdTimestamp": 1625009564217, + "username": "formsflow-clerk", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Clerk", + "lastName": "FFA", + "email": "formsflow-clerk@aot-technologies.com", + "credentials": [ + { + "type": "password", + "userLabel": "My password", + "createdDate": 1718087400076, + "secretData": "{\"value\":\"XU5BFgu3R34Lj3jmJRnNddDUTusSjPATqzEAzObH8Qs=\",\"salt\":\"kJazPy8a3ds+akjIAj2v5w==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [ + "UPDATE_PASSWORD" + ], + "notBefore": 0, + "groups": [ + "/camunda-admin", + "/formsflow/formsflow-reviewer/clerk", + "/formsflow-analytics/group2" + ] + }, + { + "createdTimestamp": 1621862607660, + "username": "formsflow-client", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Client", + "lastName": "FFA", + "email": "formsflow-client@example.com", + "credentials": [ + { + "type": "password", + "userLabel": "My password", + "createdDate": 1718087389853, + "secretData": "{\"value\":\"Fehk9NWRH+UjlGacI2YqEoIr3u87E0QS5Wt1S4HNiGk=\",\"salt\":\"uTEVXddLwHNPWPhCUgqXbw==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [ + "UPDATE_PASSWORD" + ], + "realmRoles": [ + "offline_access", + "uma_authorization" + ], + "clientRoles": { + "account": [ + "view-profile", + "manage-account" + ] + }, + "notBefore": 0, + "groups": [ + "/camunda-admin", + "/formsflow/formsflow-client" + ] + }, + { + "createdTimestamp": 1621862546931, + "username": "formsflow-designer", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Designer", + "lastName": "FFA", + "email": "formsflow-designer@example.com", + "credentials": [ + { + "type": "password", + "userLabel": "My password", + "createdDate": 1718087380963, + "secretData": "{\"value\":\"X3Q2p9qUom86nW5MzPcVWSqRqOA79aGoWiXxPNa5CXg=\",\"salt\":\"axfCJmXlZ+fT5weWx7Ug7A==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [ + "UPDATE_PASSWORD" + ], + "realmRoles": [ + "offline_access", + "uma_authorization" + ], + "clientRoles": { + "forms-flow-web": [ + "create_designs", + "view_designs" + ], + "account": [ + "view-profile", + "manage-account" + ] + }, + "notBefore": 0, + "groups": [ + "/camunda-admin", + "/formsflow/formsflow-designer" + ] + }, + { + "createdTimestamp": 1621862578318, + "username": "formsflow-reviewer", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Reviewer", + "lastName": "FFA", + "email": "formsflow-reviewer@example.com", + "attributes": { + "locale": [ + "en" + ] + }, + "credentials": [ + { + "type": "password", + "userLabel": "My password", + "createdDate": 1718087367262, + "secretData": "{\"value\":\"1/Cx4BVLFu8pXA1pAwfLj/Ph01zlcTiWZS8dPfCavJA=\",\"salt\":\"XHQ4JeY44l/QChf27jiYNw==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [ + "UPDATE_PASSWORD" + ], + "realmRoles": [ + "offline_access", + "uma_authorization" + ], + "clientRoles": { + "account": [ + "view-profile", + "manage-account" + ] + }, + "notBefore": 0, + "groups": [ + "/camunda-admin", + "/formsflow/formsflow-reviewer", + "/formsflow-analytics/group1" + ] + }, + { + "createdTimestamp": 1621585233480, + "username": "service-account-forms-flow-bpm", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "forms-flow-bpm", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "offline_access", + "uma_authorization" + ], + "clientRoles": { + "realm-management": [ + "query-groups", + "view-users", + "realm-admin", + "manage-clients", + "manage-users", + "query-users" + ], + "account": [ + "view-profile", + "manage-account" + ] + }, + "notBefore": 0, + "groups": [ + "/camunda-admin" + ] + } + ], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account", + "view-groups" + ] + } + ] + }, + "clients": [ + { + "clientId": "account", + "name": "${client_account}", "rootUrl": "${authBaseUrl}", "baseUrl": "/realms/forms-flow-ai/account/", "surrogateAuthRequired": false, @@ -648,10 +906,6 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "**********", - "defaultRoles": [ - "view-profile", - "manage-account" - ], "redirectUris": [ "/realms/forms-flow-ai/account/*" ], @@ -666,15 +920,16 @@ "publicClient": false, "frontchannelLogout": false, "protocol": "openid-connect", - "attributes": {}, + "attributes": { + "post.logout.redirect.uris": "+" + }, "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, "defaultClientScopes": [ "web-origins", - "role_list", - "profile", "roles", + "profile", "email" ], "optionalClientScopes": [ @@ -709,6 +964,7 @@ "frontchannelLogout": false, "protocol": "openid-connect", "attributes": { + "post.logout.redirect.uris": "+", "pkce.code.challenge.method": "S256" }, "authenticationFlowBindingOverrides": {}, @@ -716,6 +972,7 @@ "nodeReRegistrationTimeout": 0, "protocolMappers": [ { + "id": "26fa11e0-b0c1-496d-83bb-f3c557fd0dce", "name": "audience resolve", "protocol": "openid-connect", "protocolMapper": "oidc-audience-resolve-mapper", @@ -725,7 +982,6 @@ ], "defaultClientScopes": [ "web-origins", - "role_list", "roles", "profile", "email" @@ -757,15 +1013,16 @@ "publicClient": true, "frontchannelLogout": false, "protocol": "openid-connect", - "attributes": {}, + "attributes": { + "post.logout.redirect.uris": "+" + }, "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, "defaultClientScopes": [ "web-origins", - "role_list", - "profile", "roles", + "profile", "email" ], "optionalClientScopes": [ @@ -795,15 +1052,16 @@ "publicClient": false, "frontchannelLogout": false, "protocol": "openid-connect", - "attributes": {}, + "attributes": { + "post.logout.redirect.uris": "+" + }, "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, "defaultClientScopes": [ "web-origins", - "role_list", - "profile", "roles", + "profile", "email" ], "optionalClientScopes": [ @@ -823,7 +1081,7 @@ "clientAuthenticatorType": "client-secret", "secret": "**********", "redirectUris": [ - "http://localhost:7000/*", + "http://localhost:7000/*", "*" ], "webOrigins": [], @@ -842,9 +1100,11 @@ "saml.force.post.binding": "false", "saml.multivalued.roles": "false", "saml.encrypt": "false", + "post.logout.redirect.uris": "+", "saml.server.signature": "false", "saml.server.signature.keyinfo.ext": "false", "exclude.session.state.from.auth.response": "false", + "saml.artifact.binding.identifier": "OOFH7REqnhW7gnm7DkWoK9smSR4=", "saml.signature.algorithm": "RSA_SHA256", "saml_force_name_id_format": "false", "saml.client.signature": "false", @@ -860,41 +1120,32 @@ "nodeReRegistrationTimeout": -1, "protocolMappers": [ { - "name": "X500 surname", + "name": "X500 givenName", "protocol": "saml", "protocolMapper": "saml-user-property-mapper", "consentRequired": false, "config": { - "user.attribute": "lastName", - "friendly.name": "LastName", - "attribute.name": "urn:oid:2.5.4.4" + "user.attribute": "firstName", + "friendly.name": "FirstName", + "attribute.name": "urn:oid:2.5.4.42" } }, { - "name": "X500 givenName", + "name": "X500 surname", "protocol": "saml", "protocolMapper": "saml-user-property-mapper", "consentRequired": false, "config": { - "user.attribute": "firstName", - "friendly.name": "FirstName", - "attribute.name": "urn:oid:2.5.4.42" + "user.attribute": "lastName", + "friendly.name": "LastName", + "attribute.name": "urn:oid:2.5.4.4" } } ], "defaultClientScopes": [ - "web-origins", - "role_list", - "profile", - "roles", - "email" + "role_list" ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] + "optionalClientScopes": [] }, { "clientId": "forms-flow-bpm", @@ -905,7 +1156,7 @@ "clientAuthenticatorType": "client-secret", "secret": "e4bdbd25-1467-4f7f-b993-bc4b1944c943", "redirectUris": [ - "http://localhost:8000/camunda/*", + "http://localhost:8000/camunda/*", "*" ], "webOrigins": [ @@ -926,6 +1177,7 @@ "saml.force.post.binding": "false", "saml.multivalued.roles": "false", "saml.encrypt": "false", + "post.logout.redirect.uris": "+", "saml.server.signature": "false", "saml.server.signature.keyinfo.ext": "false", "exclude.session.state.from.auth.response": "false", @@ -954,18 +1206,6 @@ "jsonType.label": "String" } }, - { - "name": "formsflow-web-mapper", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-mapper", - "consentRequired": false, - "config": { - "included.client.audience": "forms-flow-web", - "id.token.claim": "false", - "access.token.claim": "true", - "userinfo.token.claim": "false" - } - }, { "name": "Client IP Address", "protocol": "openid-connect", @@ -980,7 +1220,19 @@ "jsonType.label": "String" } }, - { + { + "name": "formsflow-web-mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "included.client.audience": "forms-flow-web", + "id.token.claim": "false", + "access.token.claim": "true", + "userinfo.token.claim": "false" + } + }, + { "name": "camunda-rest-api", "protocol": "openid-connect", "protocolMapper": "oidc-audience-mapper", @@ -988,7 +1240,8 @@ "config": { "id.token.claim": "false", "access.token.claim": "true", - "included.custom.audience": "camunda-rest-api" + "included.custom.audience": "camunda-rest-api", + "userinfo.token.claim": "false" } }, { @@ -1006,38 +1259,37 @@ } }, { - "name": "Client ID", + "name": "groups", "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", + "protocolMapper": "oidc-group-membership-mapper", "consentRequired": false, "config": { - "user.session.note": "clientId", - "userinfo.token.claim": "true", + "full.path": "true", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "clientId", - "jsonType.label": "String" + "claim.name": "groups", + "userinfo.token.claim": "true" } }, { - "name": "groups", + "name": "Client ID", "protocol": "openid-connect", - "protocolMapper": "oidc-group-membership-mapper", + "protocolMapper": "oidc-usersessionmodel-note-mapper", "consentRequired": false, "config": { - "full.path": "true", + "user.session.note": "clientId", + "userinfo.token.claim": "true", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "groups", - "userinfo.token.claim": "true" + "claim.name": "clientId", + "jsonType.label": "String" } } ], "defaultClientScopes": [ "web-origins", - "role_list", - "profile", "roles", + "profile", "camunda-rest-api", "email" ], @@ -1057,7 +1309,7 @@ "clientAuthenticatorType": "client-secret", "secret": "**********", "redirectUris": [ - "http://localhost:3000/*", + "http://localhost:3000/*", "*" ], "webOrigins": [ @@ -1078,6 +1330,7 @@ "saml.force.post.binding": "false", "saml.multivalued.roles": "false", "saml.encrypt": "false", + "post.logout.redirect.uris": "+", "saml.server.signature": "false", "saml.server.signature.keyinfo.ext": "false", "exclude.session.state.from.auth.response": "false", @@ -1093,39 +1346,28 @@ "nodeReRegistrationTimeout": -1, "protocolMappers": [ { - "name": "formsflow-web-mapper", + "name": "groups", "protocol": "openid-connect", - "protocolMapper": "oidc-audience-mapper", + "protocolMapper": "oidc-group-membership-mapper", "consentRequired": false, "config": { - "included.client.audience": "forms-flow-web", - "id.token.claim": "false", + "full.path": "true", + "id.token.claim": "true", "access.token.claim": "true", - "userinfo.token.claim": "false" + "claim.name": "groups", + "userinfo.token.claim": "true" } }, { - "name": "camunda-rest-api", + "name": "formsflow-web-mapper", "protocol": "openid-connect", "protocolMapper": "oidc-audience-mapper", "consentRequired": false, "config": { + "included.client.audience": "forms-flow-web", "id.token.claim": "false", "access.token.claim": "true", - "included.custom.audience": "camunda-rest-api" - } - }, - { - "name": "groups", - "protocol": "openid-connect", - "protocolMapper": "oidc-group-membership-mapper", - "consentRequired": false, - "config": { - "full.path": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "groups", - "userinfo.token.claim": "true" + "userinfo.token.claim": "false" } }, { @@ -1142,13 +1384,24 @@ "access.token.claim": "true", "claim.name": "dashboards" } + }, + { + "name": "camunda-rest-api", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "false", + "access.token.claim": "true", + "included.custom.audience": "camunda-rest-api", + "userinfo.token.claim": "false" + } } ], "defaultClientScopes": [ "web-origins", - "role_list", - "profile", "roles", + "profile", "camunda-rest-api", "email" ], @@ -1179,15 +1432,16 @@ "publicClient": false, "frontchannelLogout": false, "protocol": "openid-connect", - "attributes": {}, + "attributes": { + "post.logout.redirect.uris": "+" + }, "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, "defaultClientScopes": [ "web-origins", - "role_list", - "profile", "roles", + "profile", "email" ], "optionalClientScopes": [ @@ -1198,7 +1452,6 @@ ] }, { - "clientId": "security-admin-console", "name": "${client_security-admin-console}", "rootUrl": "${authAdminUrl}", "baseUrl": "/admin/forms-flow-ai/console/", @@ -1224,6 +1477,7 @@ "frontchannelLogout": false, "protocol": "openid-connect", "attributes": { + "post.logout.redirect.uris": "+", "pkce.code.challenge.method": "S256" }, "authenticationFlowBindingOverrides": {}, @@ -1247,9 +1501,8 @@ ], "defaultClientScopes": [ "web-origins", - "role_list", - "profile", "roles", + "profile", "email" ], "optionalClientScopes": [ @@ -1262,99 +1515,157 @@ ], "clientScopes": [ { - "name": "role_list", - "description": "SAML role list", - "protocol": "saml", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", "attributes": { - "consent.screen.text": "${samlRoleListScopeConsentText}", - "display.on.consent.screen": "true" + "include.in.token.scope": "true", + "display.on.consent.screen": "false" }, "protocolMappers": [ { - "name": "role list", - "protocol": "saml", - "protocolMapper": "saml-role-list-mapper", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { - "single": "false", - "attribute.nameformat": "Basic", - "attribute.name": "Role" + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" } - } - ] - }, - { - "name": "offline_access", - "description": "OpenID Connect built-in scope: offline_access", - "protocol": "openid-connect", - "attributes": { - "consent.screen.text": "${offlineAccessScopeConsentText}", - "display.on.consent.screen": "true" - } + }, + { + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] }, { - "name": "profile", - "description": "OpenID Connect built-in scope: profile", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", "protocol": "openid-connect", "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${profileScopeConsentText}" + "include.in.token.scope": "false", + "display.on.consent.screen": "false" }, "protocolMappers": [ { - "name": "full name", + "id": "4d629437-3940-47c4-9180-d88b4c1126f6", + "name": "acr loa level", "protocol": "openid-connect", - "protocolMapper": "oidc-full-name-mapper", + "protocolMapper": "oidc-acr-mapper", "consentRequired": false, "config": { "id.token.claim": "true", - "access.token.claim": "true", - "userinfo.token.claim": "true" + "introspection.token.claim": "true", + "access.token.claim": "true" } - }, + } + ] + }, + { + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ { - "name": "profile", + "id": "ae97ed8c-ec33-4a7e-ab86-7c122ef8bbc3", + "name": "allowed web origins", "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", "consentRequired": false, "config": { - "userinfo.token.claim": "true", - "user.attribute": "profile", - "id.token.claim": "true", + "user.attribute": "foo", "access.token.claim": "true", - "claim.name": "profile", - "jsonType.label": "String" + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" } }, { - "name": "gender", + "name": "realm roles", "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", + "protocolMapper": "oidc-usermodel-realm-role-mapper", "consentRequired": false, "config": { - "userinfo.token.claim": "true", - "user.attribute": "gender", - "id.token.claim": "true", + "user.attribute": "foo", "access.token.claim": "true", - "claim.name": "gender", - "jsonType.label": "String" + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" } }, { - "name": "website", + "name": "Role", "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", + "protocolMapper": "oidc-usermodel-client-role-mapper", "consentRequired": false, "config": { + "multivalued": "true", "userinfo.token.claim": "true", - "user.attribute": "website", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "website", - "jsonType.label": "String" + "claim.name": "role", + "usermodel.clientRoleMapping.clientId": "forms-flow-web" } }, + { + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ { "name": "zoneinfo", "protocol": "openid-connect", @@ -1370,360 +1681,286 @@ } }, { - "name": "given name", + "name": "picture", "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", + "protocolMapper": "oidc-usermodel-attribute-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "firstName", + "user.attribute": "picture", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "given_name", + "claim.name": "picture", "jsonType.label": "String" } }, { - "name": "nickname", + "name": "username", "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", + "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "nickname", + "user.attribute": "username", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "nickname", + "claim.name": "preferred_username", "jsonType.label": "String" } }, { - "name": "locale", + "name": "website", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "locale", + "user.attribute": "website", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "locale", + "claim.name": "website", "jsonType.label": "String" } }, { - "name": "updated at", + "name": "locale", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "updatedAt", + "user.attribute": "locale", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "updated_at", + "claim.name": "locale", "jsonType.label": "String" } }, { - "name": "birthdate", + "name": "full name", "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", + "protocolMapper": "oidc-full-name-mapper", "consentRequired": false, "config": { - "userinfo.token.claim": "true", - "user.attribute": "birthdate", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "birthdate", - "jsonType.label": "String" + "userinfo.token.claim": "true" } }, { - "name": "family name", + "name": "middle name", "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", + "protocolMapper": "oidc-usermodel-attribute-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "lastName", + "user.attribute": "middleName", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "family_name", + "claim.name": "middle_name", "jsonType.label": "String" } }, { - "name": "middle name", + "name": "updated at", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "middleName", + "user.attribute": "updatedAt", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "middle_name", + "claim.name": "updated_at", "jsonType.label": "String" } }, { - "name": "username", + "name": "given name", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "username", + "user.attribute": "firstName", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "preferred_username", + "claim.name": "given_name", "jsonType.label": "String" } }, { - "name": "picture", + "name": "nickname", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "picture", + "user.attribute": "nickname", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "picture", + "claim.name": "nickname", "jsonType.label": "String" } - } - ] - }, - { - "name": "email", - "description": "OpenID Connect built-in scope: email", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${emailScopeConsentText}" - }, - "protocolMappers": [ + }, { - "name": "email verified", + "name": "birthdate", "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", + "protocolMapper": "oidc-usermodel-attribute-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "emailVerified", + "user.attribute": "birthdate", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "email_verified", - "jsonType.label": "boolean" + "claim.name": "birthdate", + "jsonType.label": "String" } }, { - "name": "email", + "name": "family name", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "email", + "user.attribute": "lastName", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "email", + "claim.name": "family_name", "jsonType.label": "String" } - } - ] - }, - { - "name": "address", - "description": "OpenID Connect built-in scope: address", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${addressScopeConsentText}" - }, - "protocolMappers": [ - { - "name": "address", - "protocol": "openid-connect", - "protocolMapper": "oidc-address-mapper", - "consentRequired": false, - "config": { - "user.attribute.formatted": "formatted", - "user.attribute.country": "country", - "user.attribute.postal_code": "postal_code", - "userinfo.token.claim": "true", - "user.attribute.street": "street", - "id.token.claim": "true", - "user.attribute.region": "region", - "access.token.claim": "true", - "user.attribute.locality": "locality" - } - } - ] - }, - { - "name": "phone", - "description": "OpenID Connect built-in scope: phone", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${phoneScopeConsentText}" - }, - "protocolMappers": [ + }, { - "name": "phone number verified", + "name": "gender", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "phoneNumberVerified", + "user.attribute": "gender", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "phone_number_verified", - "jsonType.label": "boolean" + "claim.name": "gender", + "jsonType.label": "String" } }, { - "name": "phone number", + "name": "profile", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "phoneNumber", + "user.attribute": "profile", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "phone_number", + "claim.name": "profile", "jsonType.label": "String" } } ] }, { - "name": "roles", - "description": "OpenID Connect scope for add user roles to the access token", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", "protocol": "openid-connect", "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "true", - "consent.screen.text": "${rolesScopeConsentText}" - }, - "protocolMappers": [ - { - "name": "realm roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "realm_access.roles", - "jsonType.label": "String", - "multivalued": "true" - } - }, - { - "name": "client roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "resource_access.${client_id}.roles", - "jsonType.label": "String", - "multivalued": "true" - } - }, - { - "name": "Role", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "multivalued": "true", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "role", - "usermodel.clientRoleMapping.clientId": "forms-flow-web" - } - }, - { - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": {} - } - ] - }, - { - "name": "web-origins", - "description": "OpenID Connect scope for add allowed web origins to the access token", - "protocol": "openid-connect", + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false", - "consent.screen.text": "" + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" }, "protocolMappers": [ { - "name": "allowed web origins", - "protocol": "openid-connect", - "protocolMapper": "oidc-allowed-origins-mapper", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", "consentRequired": false, - "config": {} + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } } ] }, { - "name": "microprofile-jwt", - "description": "Microprofile - JWT built-in scope", + "name": "email", + "description": "OpenID Connect built-in scope: email", "protocol": "openid-connect", "attributes": { "include.in.token.scope": "true", - "display.on.consent.screen": "false" + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" }, "protocolMappers": [ { - "name": "groups", + "name": "email verified", "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", + "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { - "multivalued": "true", "userinfo.token.claim": "true", - "user.attribute": "foo", + "user.attribute": "emailVerified", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "groups", - "jsonType.label": "String" + "claim.name": "email_verified", + "jsonType.label": "boolean" } }, { - "name": "upn", + "name": "email", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", - "user.attribute": "username", + "user.attribute": "email", "id.token.claim": "true", "access.token.claim": "true", - "claim.name": "upn", + "claim.name": "email", "jsonType.label": "String" } } ] }, + { + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, { "name": "camunda-rest-api", "protocol": "openid-connect", @@ -1745,6 +1982,46 @@ } } ] + }, + { + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + }, + { + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + } + ] } ], "defaultDefaultClientScopes": [ @@ -1753,7 +2030,8 @@ "email", "roles", "web-origins", - "camunda-rest-api" + "camunda-rest-api", + "acr" ], "defaultOptionalClientScopes": [ "offline_access", @@ -1764,6 +2042,7 @@ "browserSecurityHeaders": { "contentSecurityPolicyReportOnly": "", "xContentTypeOptions": "nosniff", + "referrerPolicy": "no-referrer", "xRobotsTag": "none", "xFrameOptions": "SAMEORIGIN", "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", @@ -1771,6 +2050,10 @@ "strictTransportSecurity": "max-age=31536000; includeSubDomains" }, "smtpServer": {}, + "loginTheme": "formsflow", + "accountTheme": "", + "adminTheme": "", + "emailTheme": "", "eventsEnabled": false, "eventsListeners": [ "jboss-logging" @@ -1778,14 +2061,21 @@ "enabledEventTypes": [], "adminEventsEnabled": false, "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], "components": { "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ { - "name": "Consent Required", - "providerId": "consent-required", + "id": "d0d1c5d3-3dcb-44bb-982b-d426cd1486d7", + "name": "Max Clients Limit", + "providerId": "max-clients", "subType": "anonymous", "subComponents": {}, - "config": {} + "config": { + "max-clients": [ + "200" + ] + } }, { "name": "Allowed Client Scopes", @@ -1799,13 +2089,20 @@ } }, { - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", "subType": "anonymous", "subComponents": {}, "config": { - "allow-default-scopes": [ - "true" + "allowed-protocol-mapper-types": [ + "oidc-sha256-pairwise-sub-mapper", + "oidc-full-name-mapper", + "saml-role-list-mapper", + "oidc-usermodel-property-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "saml-user-property-mapper" ] } }, @@ -1817,78 +2114,71 @@ "config": {} }, { - "name": "Trusted Hosts", - "providerId": "trusted-hosts", + "name": "Consent Required", + "providerId": "consent-required", "subType": "anonymous", "subComponents": {}, - "config": { - "host-sending-registration-request-must-match": [ - "true" - ], - "client-uris-must-match": [ - "true" - ] - } + "config": {} }, { - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "authenticated", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", "subComponents": {}, "config": { - "allowed-protocol-mapper-types": [ - "oidc-usermodel-attribute-mapper", - "oidc-full-name-mapper", - "saml-user-attribute-mapper", - "saml-user-property-mapper", - "oidc-address-mapper", - "saml-role-list-mapper", - "oidc-sha256-pairwise-sub-mapper", - "oidc-usermodel-property-mapper" + "allow-default-scopes": [ + "true" ] } }, { - "name": "Max Clients Limit", - "providerId": "max-clients", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", "subType": "anonymous", "subComponents": {}, "config": { - "max-clients": [ - "200" + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" ] } }, { "name": "Allowed Protocol Mapper Types", "providerId": "allowed-protocol-mappers", - "subType": "anonymous", + "subType": "authenticated", "subComponents": {}, "config": { "allowed-protocol-mapper-types": [ - "saml-role-list-mapper", - "oidc-usermodel-attribute-mapper", - "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", - "oidc-full-name-mapper", + "saml-user-property-mapper", "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", - "saml-user-property-mapper" + "oidc-full-name-mapper", + "oidc-address-mapper", + "saml-role-list-mapper" ] } } ], "org.keycloak.keys.KeyProvider": [ { - "name": "hmac-generated", - "providerId": "hmac-generated", + "id": "49016060-904b-4d79-9d1b-57cb5d6a1a52", + "name": "aes-generated", + "providerId": "aes-generated", "subComponents": {}, "config": { + "kid": [ + "70affbd9-d904-4dcc-8838-70beb8f73aa3" + ], + "secret": [ + "62t32DLzCqO31BzHJ7KKgQ" + ], "priority": [ "100" - ], - "algorithm": [ - "HS256" ] } }, @@ -1897,18 +2187,33 @@ "providerId": "rsa-generated", "subComponents": {}, "config": { + "privateKey": [ + "MIIEpAIBAAKCAQEA6bYyvyeConvAkWBbiXypa4UWFMLJhiutcm2C3GElTSQjsoDorz7/Kj3v5svKe2/NXly6lvNcbV63Ot5dUfr2LvNgetfMH8bXf96kZeOyZxPFGhPvI4IjQWVcxqObMsD3ZtYOLM1Q1YoNv20Rs8UhZnqwYrqsq+6eGEaN/UAMN4+O5T1ZxStKNSDIPETqZJOvozKhgY7uYANxHSRDLC/FYS+y3NaERNDeu1eDN8Qi8Z+p1BBZo8A1A5rz0puzrK3b2K/W4bPayGc7EHIA8LiGfiJXzhX2/V57dzW1qMy6OjUdt63UjPRvxNcgekbP1DOpdLQkBlCO8F6DxNY4VIDXGQIDAQABAoIBAAKpMTpi7pup/AnLsTnHV73NJfC2PQl63X6EMlgO/8KOlZzL10UI2xU136be4snKqT8YoC6QIRkaWcy2SRViCEPa6oTLiIaYws2xERRwkLtCtYeepXuKg5s+1l0T8h7ppTIgYB3wzSmj6OnT3z6O5oVJAqbFHaqBd38AQqVDrD/vrBccUZ0HnDXWT4gEyTNsUAoZ8SIFHK1ab4C2cse+FfszyrxxQRmDyckJ9/0c7YObbuk1NDm4KLZyyVhZ2QB20RqwZj3C3YlOs0So9BrkooZI+PmCmq4ikZGJRwVqAdH3t5HpaXxnt9Ytq5+e+gLyy+QO5Audd7vblAVi4eJeJ5kCgYEA+eQaSBYGLAUfUm3akVxLZF0UfYxrOn/tUA56anNbyhDHkWsJDGHMQWtXMhZruevVGTCNrMt6rAtCcHcObwR4uXiK/rxrYMGNqV/Y6jZPwkaTwbc6KJyyoNynBMRJBXlNUAtikq7bB72VC2BIThw9L/x95dkdEdoIOpI2aJZa8G0CgYEA72zXHOLufBjXE69Qe9dUqHOVSGUhZ6ou4Xpo1YLzwTvI9Z7dWaj134fHsrXfmZ1W4Z2yGephZ9NK6uw2D23GAgJO9Bv7sdVdOzkDaXb3sL7n3w7wyJPR+yk4U+hV/sEtuRnNUoNIYiyYUodKSJAsZO8qmX4qRvB9jcUnz1BYzd0CgYB3CJMEV4llGqOK7k05BM/c5QHHtEW3vgxbICpr3ruQi2GlAWlz/nn/h5QnhcqW66G8uAYkk2DB5zMkw3GarHSdVLBRG4vCsTA7yC5Zkrl3f4sOsasAgXQNcE4W1TE7bEbJpEK2QJiRHVuL6bdHjegPnaSTAlL4l/VngRJty4FSGQKBgQDQpXDw43IhAySrKuRgh85m3hMB+9+Yj147cIlbR7tUcd027zLGp89c9N66hnRNUigchWhn3TD1YdSv1RlnaKpdpdVYNeqplt6gdZbbmalQhY1bfZGnueoLjmhf9uC6GW7XF/0uIuo5Y9N6WBwMEFgfvazKBoChQYKowV9n8wTwoQKBgQC6gjg7X2bCLwFQS6yY/smv3PrG9moB5PxyDcFp8DJty23jSx4vuNfQDB3P97Z/rZW8S/QuSsqLN37vb1gwSR+BiI5A6+8dVSL8m8XMDOOA5IVschphECxmbucoefIWEBiAquNsVz9+4AmWDsMJ81I35mc/SBZf5eC84UcDZXN/kg==" + ], + "certificate": [ + "MIICqTCCAZECBgGPw87+UDANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1mb3Jtcy1mbG93LWFpMB4XDTI0MDUyOTEwMDI1M1oXDTM0MDUyOTEwMDQzM1owGDEWMBQGA1UEAwwNZm9ybXMtZmxvdy1haTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOm2Mr8ngqJ7wJFgW4l8qWuFFhTCyYYrrXJtgtxhJU0kI7KA6K8+/yo97+bLyntvzV5cupbzXG1etzreXVH69i7zYHrXzB/G13/epGXjsmcTxRoT7yOCI0FlXMajmzLA92bWDizNUNWKDb9tEbPFIWZ6sGK6rKvunhhGjf1ADDePjuU9WcUrSjUgyDxE6mSTr6MyoYGO7mADcR0kQywvxWEvstzWhETQ3rtXgzfEIvGfqdQQWaPANQOa89Kbs6yt29iv1uGz2shnOxByAPC4hn4iV84V9v1ee3c1tajMujo1Hbet1Iz0b8TXIHpGz9QzqXS0JAZQjvBeg8TWOFSA1xkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAIXZ1wxy9msKuXQRzLXZ6obmymetOliWjAU7rQpXktUDj6X33JLNxYr6MFFd4jb5E6nKPXmZEXRMq2Q/iOAFun8DUIqVd1ZoYUvYMVsSgrafT25A0v0kvuENBTI/Jz9no+2z3mHw34s4BbhZRxO0lue7ms8OFs+2lR2jSLTzlxzlY/vG9fCG7t3Q/WAm7kfLa7+mDOn9ELHG0T+xZtmhuZ2QVSNmriFK6KEBpXA7GdUJBXWKmuQeBBqFDE7Jo+mt2FSK8JpKCw4MP1IVf5Ft/OU2DFJkI4GTJagQjWYcQ1IIs0fFy3TtQv3ToJHfrr81sDFX6Ua3pEnRwfXhz3a+k2Q==" + ], "priority": [ "100" ] } }, { - "name": "aes-generated", - "providerId": "aes-generated", + "name": "hmac-generated", + "providerId": "hmac-generated", "subComponents": {}, "config": { + "kid": [ + "927e4878-e36e-45b3-a979-dc53a7ee0fde" + ], + "secret": [ + "tOFkTA2NWJ9cZhqAyf1dNar3zKTuKMtMY7_5d0ED7md22CZqNMAjd3MWwawjk1FR6EVL-KkiTJ7g90Y5Jp094A" + ], "priority": [ "100" + ], + "algorithm": [ + "HS256" ] } } @@ -1926,47 +2231,19 @@ "authenticationExecutions": [ { "authenticator": "idp-email-verification", + "authenticatorFlow": false, "requirement": "ALTERNATIVE", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { + "authenticatorFlow": true, "requirement": "ALTERNATIVE", "priority": 20, + "autheticatorFlow": true, "flowAlias": "Verify Existing Account by Re-authentication", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "alias": "Authentication Options", - "description": "Authentication options.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "basic-auth", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "basic-auth-otp", - "requirement": "DISABLED", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "auth-spnego", - "requirement": "DISABLED", - "priority": 30, - "userSetupAllowed": false, - "autheticatorFlow": false + "userSetupAllowed": false } ] }, @@ -1979,17 +2256,19 @@ "authenticationExecutions": [ { "authenticator": "conditional-user-configured", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "auth-otp-form", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false } ] }, @@ -2002,17 +2281,19 @@ "authenticationExecutions": [ { "authenticator": "conditional-user-configured", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false } ] }, @@ -2025,17 +2306,19 @@ "authenticationExecutions": [ { "authenticator": "conditional-user-configured", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "auth-otp-form", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false } ] }, @@ -2048,17 +2331,19 @@ "authenticationExecutions": [ { "authenticator": "idp-confirm-link", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { + "authenticatorFlow": true, "requirement": "REQUIRED", "priority": 20, + "autheticatorFlow": true, "flowAlias": "Account verification options", - "userSetupAllowed": false, - "autheticatorFlow": true + "userSetupAllowed": false } ] }, @@ -2071,17 +2356,19 @@ "authenticationExecutions": [ { "authenticator": "conditional-user-configured", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "reset-otp", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false } ] }, @@ -2095,17 +2382,19 @@ { "authenticatorConfig": "create unique user config", "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, "requirement": "ALTERNATIVE", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { + "authenticatorFlow": true, "requirement": "ALTERNATIVE", "priority": 20, + "autheticatorFlow": true, "flowAlias": "Handle Existing Account", - "userSetupAllowed": false, - "autheticatorFlow": true + "userSetupAllowed": false } ] }, @@ -2118,17 +2407,19 @@ "authenticationExecutions": [ { "authenticator": "idp-username-password-form", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { + "authenticatorFlow": true, "requirement": "CONDITIONAL", "priority": 20, + "autheticatorFlow": true, "flowAlias": "First broker login - Conditional OTP", - "userSetupAllowed": false, - "autheticatorFlow": true + "userSetupAllowed": false } ] }, @@ -2141,31 +2432,35 @@ "authenticationExecutions": [ { "authenticator": "auth-cookie", + "authenticatorFlow": false, "requirement": "ALTERNATIVE", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "auth-spnego", + "authenticatorFlow": false, "requirement": "DISABLED", "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, "requirement": "ALTERNATIVE", "priority": 25, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { + "authenticatorFlow": true, "requirement": "ALTERNATIVE", "priority": 30, + "autheticatorFlow": true, "flowAlias": "forms", - "userSetupAllowed": false, - "autheticatorFlow": true + "userSetupAllowed": false } ] }, @@ -2178,31 +2473,35 @@ "authenticationExecutions": [ { "authenticator": "client-secret", + "authenticatorFlow": false, "requirement": "ALTERNATIVE", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "client-jwt", + "authenticatorFlow": false, "requirement": "ALTERNATIVE", "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "client-secret-jwt", + "authenticatorFlow": false, "requirement": "ALTERNATIVE", "priority": 30, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "client-x509", + "authenticatorFlow": false, "requirement": "ALTERNATIVE", "priority": 40, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false } ] }, @@ -2215,24 +2514,27 @@ "authenticationExecutions": [ { "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { + "authenticatorFlow": true, "requirement": "CONDITIONAL", "priority": 30, + "autheticatorFlow": true, "flowAlias": "Direct Grant - Conditional OTP", - "userSetupAllowed": false, - "autheticatorFlow": true + "userSetupAllowed": false } ] }, @@ -2245,10 +2547,11 @@ "authenticationExecutions": [ { "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false } ] }, @@ -2262,17 +2565,19 @@ { "authenticatorConfig": "review profile config", "authenticator": "idp-review-profile", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { + "authenticatorFlow": true, "requirement": "REQUIRED", "priority": 20, + "autheticatorFlow": true, "flowAlias": "User creation or linking", - "userSetupAllowed": false, - "autheticatorFlow": true + "userSetupAllowed": false } ] }, @@ -2285,40 +2590,19 @@ "authenticationExecutions": [ { "authenticator": "auth-username-password-form", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { + "authenticatorFlow": true, "requirement": "CONDITIONAL", "priority": 20, + "autheticatorFlow": true, "flowAlias": "Browser - Conditional OTP", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "alias": "http challenge", - "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "no-cookie-redirect", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "requirement": "REQUIRED", - "priority": 20, - "flowAlias": "Authentication Options", - "userSetupAllowed": false, - "autheticatorFlow": true + "userSetupAllowed": false } ] }, @@ -2331,11 +2615,12 @@ "authenticationExecutions": [ { "authenticator": "registration-page-form", + "authenticatorFlow": true, "requirement": "REQUIRED", "priority": 10, + "autheticatorFlow": true, "flowAlias": "registration form", - "userSetupAllowed": false, - "autheticatorFlow": true + "userSetupAllowed": false } ] }, @@ -2348,31 +2633,27 @@ "authenticationExecutions": [ { "authenticator": "registration-user-creation", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "registration-profile-action", - "requirement": "REQUIRED", - "priority": 40, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "registration-password-action", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 50, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, "requirement": "DISABLED", "priority": 60, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false } ] }, @@ -2385,31 +2666,35 @@ "authenticationExecutions": [ { "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "reset-credential-email", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { "authenticator": "reset-password", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 30, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false }, { + "authenticatorFlow": true, "requirement": "CONDITIONAL", "priority": 40, + "autheticatorFlow": true, "flowAlias": "Reset - Conditional OTP", - "userSetupAllowed": false, - "autheticatorFlow": true + "userSetupAllowed": false } ] }, @@ -2422,10 +2707,11 @@ "authenticationExecutions": [ { "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, "requirement": "REQUIRED", "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false + "autheticatorFlow": false, + "userSetupAllowed": false } ] } @@ -2455,9 +2741,9 @@ "config": {} }, { - "alias": "terms_and_conditions", + "alias": "TERMS_AND_CONDITIONS", "name": "Terms and Conditions", - "providerId": "terms_and_conditions", + "providerId": "TERMS_AND_CONDITIONS", "enabled": false, "defaultAction": false, "priority": 20, @@ -2490,6 +2776,15 @@ "priority": 50, "config": {} }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, { "alias": "update_user_locale", "name": "Update User Locale", @@ -2507,11 +2802,25 @@ "clientAuthenticationFlow": "clients", "dockerAuthenticationFlow": "docker auth", "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaExpiresIn": "120", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DeviceCodeLifespan": "600", "clientOfflineSessionMaxLifespan": "0", + "oauth2DevicePollingInterval": "5", "clientSessionIdleTimeout": "0", + "parRequestUriLifespan": "60", "clientSessionMaxLifespan": "0", - "clientOfflineSessionIdleTimeout": "0" + "clientOfflineSessionIdleTimeout": "0", + "cibaInterval": "5", + "realmReusableOtpCode": "false" + }, + "keycloakVersion": "23.0.7", + "userManagedAccessAllowed": false, + "clientProfiles": { + "profiles": [] }, - "keycloakVersion": "11.0.0", - "userManagedAccessAllowed": false -} + "clientPolicies": { + "policies": [] + } +} \ No newline at end of file From c5c1004a77fbf2910d39234d5f6182b0c3e91786 Mon Sep 17 00:00:00 2001 From: abilpraju-aot Date: Tue, 18 Jun 2024 10:17:52 +0530 Subject: [PATCH 08/60] updated changes for manage_integretion --- forms-flow-idm/keycloak/imports/formsflow-ai-realm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json b/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json index 6d3c0997a0..b286b748ac 100644 --- a/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json +++ b/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json @@ -475,7 +475,6 @@ ], "forms-flow-web": [ "manage_roles", - "manage_integrations", "manage_users" ] } @@ -502,7 +501,8 @@ "clientRoles": { "forms-flow-web": [ "create_designs", - "view_designs" + "view_designs", + "manage_integrations" ] } }, From 4e899a112b24ae300e4c8aeeb8bca71f7e12f5eb Mon Sep 17 00:00:00 2001 From: Abil P Raju <83952803+abilpraju-aot@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:14:19 +0530 Subject: [PATCH 09/60] Update formsflow-ai-realm.json --- .../keycloak/imports/formsflow-ai-realm.json | 298 +++++------------- 1 file changed, 72 insertions(+), 226 deletions(-) diff --git a/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json b/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json index b286b748ac..126a9422bd 100644 --- a/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json +++ b/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json @@ -55,15 +55,9 @@ "description": "${role_default-roles}", "composite": true, "composites": { - "realm": [ - "offline_access", - "uma_authorization" - ], + "realm": ["offline_access", "uma_authorization"], "client": { - "account": [ - "view-profile", - "manage-account" - ] + "account": ["view-profile", "manage-account"] } }, "clientRole": false, @@ -108,9 +102,7 @@ "composite": true, "composites": { "client": { - "realm-management": [ - "query-clients" - ] + "realm-management": ["query-clients"] } }, "clientRole": true, @@ -164,10 +156,7 @@ "composite": true, "composites": { "client": { - "realm-management": [ - "query-groups", - "query-users" - ] + "realm-management": ["query-groups", "query-users"] } }, "clientRole": true, @@ -255,6 +244,13 @@ } ], "forms-flow-web": [ + { + "name": "admin", + "description": "Administrator Role", + "composite": false, + "clientRole": true, + "attributes": {} + }, { "name": "manage_tasks", "description": "Can claim and work on tasks", @@ -403,9 +399,7 @@ "composite": true, "composites": { "client": { - "account": [ - "view-consent" - ] + "account": ["view-consent"] } }, "clientRole": true, @@ -417,9 +411,7 @@ "composite": true, "composites": { "client": { - "account": [ - "manage-account-links" - ] + "account": ["manage-account-links"] } }, "clientRole": true, @@ -474,6 +466,8 @@ "query-users" ], "forms-flow-web": [ + "admin", + "manage_dashboard_authorizations", "manage_roles", "manage_users" ] @@ -486,10 +480,7 @@ "attributes": {}, "realmRoles": [], "clientRoles": { - "forms-flow-web": [ - "view_submissions", - "create_submissions" - ] + "forms-flow-web": ["view_submissions", "create_submissions"] } }, { @@ -578,14 +569,8 @@ "clientRole": false, "containerId": "forms-flow-ai" }, - "defaultGroups": [ - "/camunda-admin", - "/formsflow", - "/formsflow-analytics" - ], - "requiredCredentials": [ - "password" - ], + "defaultGroups": ["/camunda-admin", "/formsflow", "/formsflow-analytics"], + "requiredCredentials": ["password"], "otpPolicyType": "totp", "otpPolicyAlgorithm": "HmacSHA1", "otpPolicyInitialCounter": 0, @@ -600,9 +585,7 @@ ], "localizationTexts": {}, "webAuthnPolicyRpEntityName": "keycloak", - "webAuthnPolicySignatureAlgorithms": [ - "ES256" - ], + "webAuthnPolicySignatureAlgorithms": ["ES256"], "webAuthnPolicyRpId": "", "webAuthnPolicyAttestationConveyancePreference": "not specified", "webAuthnPolicyAuthenticatorAttachment": "not specified", @@ -613,9 +596,7 @@ "webAuthnPolicyAcceptableAaguids": [], "webAuthnPolicyExtraOrigins": [], "webAuthnPolicyPasswordlessRpEntityName": "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms": [ - "ES256" - ], + "webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"], "webAuthnPolicyPasswordlessRpId": "", "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", @@ -646,12 +627,8 @@ } ], "disableableCredentialTypes": [], - "requiredActions": [ - "UPDATE_PASSWORD" - ], - "realmRoles": [ - "default-roles-forms-flow-ai" - ], + "requiredActions": ["UPDATE_PASSWORD"], + "realmRoles": ["default-roles-forms-flow-ai"], "notBefore": 0, "groups": [ "/camunda-admin", @@ -679,9 +656,7 @@ } ], "disableableCredentialTypes": [], - "requiredActions": [ - "UPDATE_PASSWORD" - ], + "requiredActions": ["UPDATE_PASSWORD"], "notBefore": 0, "groups": [ "/formsflow/formsflow-reviewer/approver", @@ -708,9 +683,7 @@ } ], "disableableCredentialTypes": [], - "requiredActions": [ - "UPDATE_PASSWORD" - ], + "requiredActions": ["UPDATE_PASSWORD"], "notBefore": 0, "groups": [ "/camunda-admin", @@ -737,24 +710,13 @@ } ], "disableableCredentialTypes": [], - "requiredActions": [ - "UPDATE_PASSWORD" - ], - "realmRoles": [ - "offline_access", - "uma_authorization" - ], + "requiredActions": ["UPDATE_PASSWORD"], + "realmRoles": ["offline_access", "uma_authorization"], "clientRoles": { - "account": [ - "view-profile", - "manage-account" - ] + "account": ["view-profile", "manage-account"] }, "notBefore": 0, - "groups": [ - "/camunda-admin", - "/formsflow/formsflow-client" - ] + "groups": ["/camunda-admin", "/formsflow/formsflow-client"] }, { "createdTimestamp": 1621862546931, @@ -775,28 +737,14 @@ } ], "disableableCredentialTypes": [], - "requiredActions": [ - "UPDATE_PASSWORD" - ], - "realmRoles": [ - "offline_access", - "uma_authorization" - ], + "requiredActions": ["UPDATE_PASSWORD"], + "realmRoles": ["offline_access", "uma_authorization"], "clientRoles": { - "forms-flow-web": [ - "create_designs", - "view_designs" - ], - "account": [ - "view-profile", - "manage-account" - ] + "forms-flow-web": ["create_designs", "view_designs"], + "account": ["view-profile", "manage-account"] }, "notBefore": 0, - "groups": [ - "/camunda-admin", - "/formsflow/formsflow-designer" - ] + "groups": ["/camunda-admin", "/formsflow/formsflow-designer"] }, { "createdTimestamp": 1621862578318, @@ -808,9 +756,7 @@ "lastName": "FFA", "email": "formsflow-reviewer@example.com", "attributes": { - "locale": [ - "en" - ] + "locale": ["en"] }, "credentials": [ { @@ -822,18 +768,10 @@ } ], "disableableCredentialTypes": [], - "requiredActions": [ - "UPDATE_PASSWORD" - ], - "realmRoles": [ - "offline_access", - "uma_authorization" - ], + "requiredActions": ["UPDATE_PASSWORD"], + "realmRoles": ["offline_access", "uma_authorization"], "clientRoles": { - "account": [ - "view-profile", - "manage-account" - ] + "account": ["view-profile", "manage-account"] }, "notBefore": 0, "groups": [ @@ -852,10 +790,7 @@ "credentials": [], "disableableCredentialTypes": [], "requiredActions": [], - "realmRoles": [ - "offline_access", - "uma_authorization" - ], + "realmRoles": ["offline_access", "uma_authorization"], "clientRoles": { "realm-management": [ "query-groups", @@ -865,33 +800,23 @@ "manage-users", "query-users" ], - "account": [ - "view-profile", - "manage-account" - ] + "account": ["view-profile", "manage-account"] }, "notBefore": 0, - "groups": [ - "/camunda-admin" - ] + "groups": ["/camunda-admin"] } ], "scopeMappings": [ { "clientScope": "offline_access", - "roles": [ - "offline_access" - ] + "roles": ["offline_access"] } ], "clientScopeMappings": { "account": [ { "client": "account-console", - "roles": [ - "manage-account", - "view-groups" - ] + "roles": ["manage-account", "view-groups"] } ] }, @@ -906,9 +831,7 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "**********", - "redirectUris": [ - "/realms/forms-flow-ai/account/*" - ], + "redirectUris": ["/realms/forms-flow-ai/account/*"], "webOrigins": [], "notBefore": 0, "bearerOnly": false, @@ -926,12 +849,7 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "roles", - "profile", - "email" - ], + "defaultClientScopes": ["web-origins", "roles", "profile", "email"], "optionalClientScopes": [ "address", "phone", @@ -949,9 +867,7 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "**********", - "redirectUris": [ - "/realms/forms-flow-ai/account/*" - ], + "redirectUris": ["/realms/forms-flow-ai/account/*"], "webOrigins": [], "notBefore": 0, "bearerOnly": false, @@ -980,12 +896,7 @@ "config": {} } ], - "defaultClientScopes": [ - "web-origins", - "roles", - "profile", - "email" - ], + "defaultClientScopes": ["web-origins", "roles", "profile", "email"], "optionalClientScopes": [ "address", "phone", @@ -1019,12 +930,7 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "roles", - "profile", - "email" - ], + "defaultClientScopes": ["web-origins", "roles", "profile", "email"], "optionalClientScopes": [ "address", "phone", @@ -1058,12 +964,7 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "roles", - "profile", - "email" - ], + "defaultClientScopes": ["web-origins", "roles", "profile", "email"], "optionalClientScopes": [ "address", "phone", @@ -1080,10 +981,7 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "**********", - "redirectUris": [ - "http://localhost:7000/*", - "*" - ], + "redirectUris": ["http://localhost:7000/*", "*"], "webOrigins": [], "notBefore": 0, "bearerOnly": false, @@ -1142,9 +1040,7 @@ } } ], - "defaultClientScopes": [ - "role_list" - ], + "defaultClientScopes": ["role_list"], "optionalClientScopes": [] }, { @@ -1155,13 +1051,8 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "e4bdbd25-1467-4f7f-b993-bc4b1944c943", - "redirectUris": [ - "http://localhost:8000/camunda/*", - "*" - ], - "webOrigins": [ - "*" - ], + "redirectUris": ["http://localhost:8000/camunda/*", "*"], + "webOrigins": ["*"], "notBefore": 0, "bearerOnly": false, "consentRequired": false, @@ -1308,13 +1199,8 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "**********", - "redirectUris": [ - "http://localhost:3000/*", - "*" - ], - "webOrigins": [ - "*" - ], + "redirectUris": ["http://localhost:3000/*", "*"], + "webOrigins": ["*"], "notBefore": 0, "bearerOnly": false, "consentRequired": false, @@ -1438,12 +1324,7 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "roles", - "profile", - "email" - ], + "defaultClientScopes": ["web-origins", "roles", "profile", "email"], "optionalClientScopes": [ "address", "phone", @@ -1460,12 +1341,8 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "**********", - "redirectUris": [ - "/admin/forms-flow-ai/console/*" - ], - "webOrigins": [ - "+" - ], + "redirectUris": ["/admin/forms-flow-ai/console/*"], + "webOrigins": ["+"], "notBefore": 0, "bearerOnly": false, "consentRequired": false, @@ -1499,12 +1376,7 @@ } } ], - "defaultClientScopes": [ - "web-origins", - "roles", - "profile", - "email" - ], + "defaultClientScopes": ["web-origins", "roles", "profile", "email"], "optionalClientScopes": [ "address", "phone", @@ -2055,9 +1927,7 @@ "adminTheme": "", "emailTheme": "", "eventsEnabled": false, - "eventsListeners": [ - "jboss-logging" - ], + "eventsListeners": ["jboss-logging"], "enabledEventTypes": [], "adminEventsEnabled": false, "adminEventsDetailsEnabled": false, @@ -2072,9 +1942,7 @@ "subType": "anonymous", "subComponents": {}, "config": { - "max-clients": [ - "200" - ] + "max-clients": ["200"] } }, { @@ -2083,9 +1951,7 @@ "subType": "authenticated", "subComponents": {}, "config": { - "allow-default-scopes": [ - "true" - ] + "allow-default-scopes": ["true"] } }, { @@ -2126,9 +1992,7 @@ "subType": "anonymous", "subComponents": {}, "config": { - "allow-default-scopes": [ - "true" - ] + "allow-default-scopes": ["true"] } }, { @@ -2137,12 +2001,8 @@ "subType": "anonymous", "subComponents": {}, "config": { - "host-sending-registration-request-must-match": [ - "true" - ], - "client-uris-must-match": [ - "true" - ] + "host-sending-registration-request-must-match": ["true"], + "client-uris-must-match": ["true"] } }, { @@ -2171,15 +2031,9 @@ "providerId": "aes-generated", "subComponents": {}, "config": { - "kid": [ - "70affbd9-d904-4dcc-8838-70beb8f73aa3" - ], - "secret": [ - "62t32DLzCqO31BzHJ7KKgQ" - ], - "priority": [ - "100" - ] + "kid": ["70affbd9-d904-4dcc-8838-70beb8f73aa3"], + "secret": ["62t32DLzCqO31BzHJ7KKgQ"], + "priority": ["100"] } }, { @@ -2193,9 +2047,7 @@ "certificate": [ "MIICqTCCAZECBgGPw87+UDANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1mb3Jtcy1mbG93LWFpMB4XDTI0MDUyOTEwMDI1M1oXDTM0MDUyOTEwMDQzM1owGDEWMBQGA1UEAwwNZm9ybXMtZmxvdy1haTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOm2Mr8ngqJ7wJFgW4l8qWuFFhTCyYYrrXJtgtxhJU0kI7KA6K8+/yo97+bLyntvzV5cupbzXG1etzreXVH69i7zYHrXzB/G13/epGXjsmcTxRoT7yOCI0FlXMajmzLA92bWDizNUNWKDb9tEbPFIWZ6sGK6rKvunhhGjf1ADDePjuU9WcUrSjUgyDxE6mSTr6MyoYGO7mADcR0kQywvxWEvstzWhETQ3rtXgzfEIvGfqdQQWaPANQOa89Kbs6yt29iv1uGz2shnOxByAPC4hn4iV84V9v1ee3c1tajMujo1Hbet1Iz0b8TXIHpGz9QzqXS0JAZQjvBeg8TWOFSA1xkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAIXZ1wxy9msKuXQRzLXZ6obmymetOliWjAU7rQpXktUDj6X33JLNxYr6MFFd4jb5E6nKPXmZEXRMq2Q/iOAFun8DUIqVd1ZoYUvYMVsSgrafT25A0v0kvuENBTI/Jz9no+2z3mHw34s4BbhZRxO0lue7ms8OFs+2lR2jSLTzlxzlY/vG9fCG7t3Q/WAm7kfLa7+mDOn9ELHG0T+xZtmhuZ2QVSNmriFK6KEBpXA7GdUJBXWKmuQeBBqFDE7Jo+mt2FSK8JpKCw4MP1IVf5Ft/OU2DFJkI4GTJagQjWYcQ1IIs0fFy3TtQv3ToJHfrr81sDFX6Ua3pEnRwfXhz3a+k2Q==" ], - "priority": [ - "100" - ] + "priority": ["100"] } }, { @@ -2203,18 +2055,12 @@ "providerId": "hmac-generated", "subComponents": {}, "config": { - "kid": [ - "927e4878-e36e-45b3-a979-dc53a7ee0fde" - ], + "kid": ["927e4878-e36e-45b3-a979-dc53a7ee0fde"], "secret": [ "tOFkTA2NWJ9cZhqAyf1dNar3zKTuKMtMY7_5d0ED7md22CZqNMAjd3MWwawjk1FR6EVL-KkiTJ7g90Y5Jp094A" ], - "priority": [ - "100" - ], - "algorithm": [ - "HS256" - ] + "priority": ["100"], + "algorithm": ["HS256"] } } ] @@ -2823,4 +2669,4 @@ "clientPolicies": { "policies": [] } -} \ No newline at end of file +} From 0c4c0115623012eabe5cceaae06aa57f4344ec99 Mon Sep 17 00:00:00 2001 From: shuhaib-aot Date: Tue, 25 Jun 2024 11:21:23 +0530 Subject: [PATCH 10/60] FWF:3327 [feature] Created Permissions file to handle permission --- .../src/formsflow_api_utils/utils/__init__.py | 2 +- .../formsflow_api_utils/utils/constants.py | 73 +------------------ .../formsflow_api_utils/utils/permisions.py | 37 ++++++++++ .../src/formsflow_api_utils/utils/roles.py | 9 --- .../src/formsflow_api/resources/roles.py | 4 +- 5 files changed, 41 insertions(+), 84 deletions(-) create mode 100644 forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py delete mode 100644 forms-flow-api-utils/src/formsflow_api_utils/utils/roles.py diff --git a/forms-flow-api-utils/src/formsflow_api_utils/utils/__init__.py b/forms-flow-api-utils/src/formsflow_api_utils/utils/__init__.py index 8853734ec2..6a75d64903 100644 --- a/forms-flow-api-utils/src/formsflow_api_utils/utils/__init__.py +++ b/forms-flow-api-utils/src/formsflow_api_utils/utils/__init__.py @@ -20,9 +20,9 @@ NEW_APPLICATION_STATUS, REVIEWER_GROUP, HTTP_TIMEOUT, - PERMISSIONS ) from .enums import ApplicationSortingParameters +from .permisions import PERMISSION_DETAILS, Permissions from .file_log_handler import CustomTimedRotatingFileHandler, register_log_handlers from .format import CustomFormatter from .logging import setup_logging, log_bpm_error diff --git a/forms-flow-api-utils/src/formsflow_api_utils/utils/constants.py b/forms-flow-api-utils/src/formsflow_api_utils/utils/constants.py index 1539baa0b6..08b2396b6a 100644 --- a/forms-flow-api-utils/src/formsflow_api_utils/utils/constants.py +++ b/forms-flow-api-utils/src/formsflow_api_utils/utils/constants.py @@ -46,75 +46,4 @@ DEFAULT_PROCESS_KEY = "Defaultflow" DEFAULT_PROCESS_NAME = "Default Flow" -HTTP_TIMEOUT = 30 - -PERMISSIONS = [{ - "name": "create_designs", - "description": "Create Form, workflow designs", - "depends_on": ["view_designs"] - }, - { - "name": "view_designs", - "description": "Access to design", - "depends_on": [] - }, - { - "name": "create_submissions", - "description": "Create submissions", - "depends_on": [] - }, - { - "name": "view_submissions", - "description": "Access to submissions", - "depends_on": [] - }, - { - "name": "view_dashboards", - "description": "Access to dashboards", - "depends_on": [] - }, - { - "name": "view_tasks", - "description": "Access to tasks", - "depends_on": [] - }, - { - "name": "manage_tasks", - "description": "Can claim and work on tasks", - "depends_on": ["view_tasks"] - },{ - "name": "manage_all_filters", - "description": "Manage all filters", - "depends_on": ["view_filters","create_filters"] - }, - { - "name": "create_filters", - "description": "Access to create filters", - "depends_on": ["view_filters"] - }, - { - "name": "view_filters", - "description": "Access to view filters", - "depends_on": [] - }, - { - "name": "manage_integrations", - "description": "Access to Integrations", - "depends_on": [] - }, - { - "name": "manage_dashboard_authorizations", - "description": "Manage Dashboard Authorization", - "depends_on": ["view_dashboards"] - }, - { - "name": "manage_users", - "description": "Manage Users", - "depends_on": [] - }, - { - "name": "manage_roles", - "description": "Manage Roles", - "depends_on": ["manage_users"] - } -] \ No newline at end of file +HTTP_TIMEOUT = 30 \ No newline at end of file diff --git a/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py b/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py new file mode 100644 index 0000000000..19632f2a2c --- /dev/null +++ b/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py @@ -0,0 +1,37 @@ +"""Permission definitions.""" +from enum import Enum + +class Permissions(Enum): + CREATE_DESIGNS = "create_designs" + VIEW_DESIGNS = "view_designs" + CREATE_SUBMISSIONS = "create_submissions" + VIEW_SUBMISSIONS = "view_submissions" + VIEW_DASHBOARDS = "view_dashboards" + VIEW_TASKS = "view_tasks" + MANAGE_TASKS = "manage_tasks" + MANAGE_ALL_FILTERS = "manage_all_filters" + CREATE_FILTERS = "create_filters" + VIEW_FILTERS = "view_filters" + MANAGE_INTEGRATIONS = "manage_integrations" + MANAGE_DASHBOARD_AUTHORIZATIONS = "manage_dashboard_authorizations" + MANAGE_USERS = "manage_users" + MANAGE_ROLES = "manage_roles" + ADMIN= "admin" + +PERMISSION_DETAILS = [ + {"name": Permissions.CREATE_DESIGNS, "description": "Create Form, workflow designs", "depends_on": [Permissions.VIEW_DESIGNS]}, + {"name": Permissions.VIEW_DESIGNS, "description": "Access to design", "depends_on": []}, + {"name": Permissions.CREATE_SUBMISSIONS, "description": "Create submissions", "depends_on": []}, + {"name": Permissions.VIEW_SUBMISSIONS, "description": "Access to submissions", "depends_on": []}, + {"name": Permissions.VIEW_DASHBOARDS, "description": "Access to dashboards", "depends_on": []}, + {"name": Permissions.VIEW_TASKS, "description": "Access to tasks", "depends_on": []}, + {"name": Permissions.MANAGE_TASKS, "description": "Can claim and work on tasks", "depends_on": [Permissions.VIEW_TASKS]}, + {"name": Permissions.MANAGE_ALL_FILTERS, "description": "Manage all filters", "depends_on": [Permissions.VIEW_FILTERS, Permissions.CREATE_FILTERS]}, + {"name": Permissions.CREATE_FILTERS, "description": "Access to create filters", "depends_on": [Permissions.VIEW_FILTERS]}, + {"name": Permissions.VIEW_FILTERS, "description": "Access to view filters", "depends_on": []}, + {"name": Permissions.MANAGE_INTEGRATIONS, "description": "Access to Integrations", "depends_on": []}, + {"name": Permissions.MANAGE_DASHBOARD_AUTHORIZATIONS, "description": "Manage Dashboard Authorization", "depends_on": [Permissions.VIEW_DASHBOARDS]}, + {"name": Permissions.MANAGE_USERS, "description": "Manage Users", "depends_on": []}, + {"name": Permissions.MANAGE_ROLES, "description": "Manage Roles", "depends_on": [Permissions.MANAGE_USERS]}, + {"name": Permissions.ADMIN, "description": "Administrator Role", "depends_on": []}, +] diff --git a/forms-flow-api-utils/src/formsflow_api_utils/utils/roles.py b/forms-flow-api-utils/src/formsflow_api_utils/utils/roles.py deleted file mode 100644 index 53c32928e1..0000000000 --- a/forms-flow-api-utils/src/formsflow_api_utils/utils/roles.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Role definitions.""" - - -# class Role: # pylint: disable=too-few-public-methods -# """User Role.""" - -# rpas_designer = "rpas-designer" -# rpas_reviewer = "rpas-reviewer" -# rpas_client = "rpas-client" diff --git a/forms-flow-api/src/formsflow_api/resources/roles.py b/forms-flow-api/src/formsflow_api/resources/roles.py index 7861fcd441..79a7be44a4 100644 --- a/forms-flow-api/src/formsflow_api/resources/roles.py +++ b/forms-flow-api/src/formsflow_api/resources/roles.py @@ -7,7 +7,7 @@ from formsflow_api_utils.utils import ( ADMIN_GROUP, DESIGNER_GROUP, - PERMISSIONS, + PERMISSION_DETAILS, REVIEWER_GROUP, auth, cors_preflight, @@ -167,4 +167,4 @@ class Permissions(Resource): ) def get(): """Return permission list.""" - return PERMISSIONS + return PERMISSION_DETAILS From 7e081bc5e794afbb7fd60e0661f9f204597da040 Mon Sep 17 00:00:00 2001 From: shuhaib-aot Date: Tue, 25 Jun 2024 11:33:40 +0530 Subject: [PATCH 11/60] FWF:3327 [feature] changed utils link --- forms-flow-api/requirements.txt | 2 +- forms-flow-api/requirements/prod.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/forms-flow-api/requirements.txt b/forms-flow-api/requirements.txt index ad963d8f18..1706af2ec9 100644 --- a/forms-flow-api/requirements.txt +++ b/forms-flow-api/requirements.txt @@ -27,7 +27,7 @@ ecdsa==0.18.0 flask-jwt-oidc==0.3.0 flask-marshmallow==1.2.1 flask-restx==1.3.0 -formsflow_api_utils @ git+https://github.com/AOT-Technologies/forms-flow-ai.git@develop#subdirectory=forms-flow-api-utils +formsflow_api_utils @ git+https://github.com/shuhaib-aot/forms-flow-ai.git@Feature/FWF-3327-secure-endpoint-with-role#subdirectory=forms-flow-api-utils gunicorn==21.2.0 h11==0.14.0 h2==4.1.0 diff --git a/forms-flow-api/requirements/prod.txt b/forms-flow-api/requirements/prod.txt index f64f617eb7..64ffd6f17e 100644 --- a/forms-flow-api/requirements/prod.txt +++ b/forms-flow-api/requirements/prod.txt @@ -16,4 +16,4 @@ sqlalchemy_utils markupsafe PyJWT redis -git+https://github.com/AOT-Technologies/forms-flow-ai.git@develop#egg=formsflow_api_utils&subdirectory=forms-flow-api-utils +git+https://github.com/shuhaib-aot/forms-flow-ai.git@Feature/FWF-3327-secure-endpoint-with-role#subdirectory=forms-flow-api-utils \ No newline at end of file From e0d203a4d4ed67158b0f7d8b10860ee6b5caca9c Mon Sep 17 00:00:00 2001 From: shuhaib-aot Date: Tue, 25 Jun 2024 15:19:55 +0530 Subject: [PATCH 12/60] FWF:3327 [feature] fixed permissions in util folder --- .../formsflow_api_utils/utils/permisions.py | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py b/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py index 19632f2a2c..5c050d2ab7 100644 --- a/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py +++ b/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py @@ -19,19 +19,19 @@ class Permissions(Enum): ADMIN= "admin" PERMISSION_DETAILS = [ - {"name": Permissions.CREATE_DESIGNS, "description": "Create Form, workflow designs", "depends_on": [Permissions.VIEW_DESIGNS]}, - {"name": Permissions.VIEW_DESIGNS, "description": "Access to design", "depends_on": []}, - {"name": Permissions.CREATE_SUBMISSIONS, "description": "Create submissions", "depends_on": []}, - {"name": Permissions.VIEW_SUBMISSIONS, "description": "Access to submissions", "depends_on": []}, - {"name": Permissions.VIEW_DASHBOARDS, "description": "Access to dashboards", "depends_on": []}, - {"name": Permissions.VIEW_TASKS, "description": "Access to tasks", "depends_on": []}, - {"name": Permissions.MANAGE_TASKS, "description": "Can claim and work on tasks", "depends_on": [Permissions.VIEW_TASKS]}, - {"name": Permissions.MANAGE_ALL_FILTERS, "description": "Manage all filters", "depends_on": [Permissions.VIEW_FILTERS, Permissions.CREATE_FILTERS]}, - {"name": Permissions.CREATE_FILTERS, "description": "Access to create filters", "depends_on": [Permissions.VIEW_FILTERS]}, - {"name": Permissions.VIEW_FILTERS, "description": "Access to view filters", "depends_on": []}, - {"name": Permissions.MANAGE_INTEGRATIONS, "description": "Access to Integrations", "depends_on": []}, - {"name": Permissions.MANAGE_DASHBOARD_AUTHORIZATIONS, "description": "Manage Dashboard Authorization", "depends_on": [Permissions.VIEW_DASHBOARDS]}, - {"name": Permissions.MANAGE_USERS, "description": "Manage Users", "depends_on": []}, - {"name": Permissions.MANAGE_ROLES, "description": "Manage Roles", "depends_on": [Permissions.MANAGE_USERS]}, - {"name": Permissions.ADMIN, "description": "Administrator Role", "depends_on": []}, + {"name": Permissions.CREATE_DESIGNS.value, "description": "Create Form, workflow designs", "depends_on": [Permissions.VIEW_DESIGNS.value]}, + {"name": Permissions.VIEW_DESIGNS.value, "description": "Access to design", "depends_on": []}, + {"name": Permissions.CREATE_SUBMISSIONS.value, "description": "Create submissions", "depends_on": []}, + {"name": Permissions.VIEW_SUBMISSIONS.value, "description": "Access to submissions", "depends_on": []}, + {"name": Permissions.VIEW_DASHBOARDS.value, "description": "Access to dashboards", "depends_on": []}, + {"name": Permissions.VIEW_TASKS.value, "description": "Access to tasks", "depends_on": []}, + {"name": Permissions.MANAGE_TASKS.value, "description": "Can claim and work on tasks", "depends_on": [Permissions.VIEW_TASKS.value]}, + {"name": Permissions.MANAGE_ALL_FILTERS.value, "description": "Manage all filters", "depends_on": [Permissions.VIEW_FILTERS.value, Permissions.CREATE_FILTERS.value]}, + {"name": Permissions.CREATE_FILTERS.value, "description": "Access to create filters", "depends_on": [Permissions.VIEW_FILTERS.value]}, + {"name": Permissions.VIEW_FILTERS.value, "description": "Access to view filters", "depends_on": []}, + {"name": Permissions.MANAGE_INTEGRATIONS.value, "description": "Access to Integrations", "depends_on": []}, + {"name": Permissions.MANAGE_DASHBOARD_AUTHORIZATIONS.value, "description": "Manage Dashboard Authorization", "depends_on": [Permissions.VIEW_DASHBOARDS.value]}, + {"name": Permissions.MANAGE_USERS.value, "description": "Manage Users", "depends_on": []}, + {"name": Permissions.MANAGE_ROLES.value, "description": "Manage Roles", "depends_on": [Permissions.MANAGE_USERS.value]}, + {"name": Permissions.ADMIN.value, "description": "Administrator Role", "depends_on": []}, ] From 1da480f2da44aee39c86811b24ece48aeab940bf Mon Sep 17 00:00:00 2001 From: auslin-aot Date: Tue, 25 Jun 2024 19:13:48 +0530 Subject: [PATCH 13/60] FWF-3380: [Feature] captured tenant based groups in camunda context --- .../rest/KeycloakAuthenticationFilter.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java index 7ee9e5c3b8..780672571a 100644 --- a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java +++ b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java @@ -16,6 +16,7 @@ import org.camunda.bpm.extension.commons.utils.RestAPIBuilderUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; @@ -36,6 +37,9 @@ public class KeycloakAuthenticationFilter implements Filter { private final String userNameAttribute; + @Value("${plugin.identity.keycloak.enableMultiTenancy}") + private boolean enableMultiTenancy; + /** Access to Camunda's IdentityService. */ private IdentityService identityService; @@ -109,11 +113,14 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha private List getUserGroups(String userId, Map claims, String tenantKey) { List groupIds = new ArrayList<>(); - if (claims != null && claims.containsKey("groups")) { +// LOG.debug(enableMultiTenancy+ "multitenancy enabled.."); // returning false + if (claims != null && claims.containsKey("groups") && tenantKey != null) { + groupIds.addAll(getKeys(claims, "groups", tenantKey)); + } + else if (claims != null && claims.containsKey("groups")) { groupIds.addAll(getKeys(claims, "groups", null)); - } else if (claims != null && claims.containsKey("roles")) { // Treat roles as alternative to groups - groupIds.addAll(getKeys(claims, "roles", tenantKey)); - } else { + } + else { identityService.createGroupQuery().groupMember(userId).list().forEach(g -> groupIds.add(g.getId())); } return groupIds; @@ -126,10 +133,15 @@ private List getKeys(Map claims, String nodeName, String for (Object key : (List) claims.get(nodeName)) { String keyValue = key.toString(); keyValue = StringUtils.contains(keyValue, "/") ? StringUtils.substringAfter(keyValue, "/") : keyValue; - if (tenantKey != null) - keyValue = tenantKey + "-" + keyValue; - keys.add(keyValue); + if (tenantKey != null) { + if (StringUtils.startsWith(keyValue, tenantKey)) { + keys.add(keyValue); + } + } else { + keys.add(keyValue); + } } + // keys.add("camunda-admin"); } return keys; } From 273dbea104b0be68d96907c84a74c79b0467ae07 Mon Sep 17 00:00:00 2001 From: Sumesh Kariyil Date: Tue, 25 Jun 2024 14:58:04 -0700 Subject: [PATCH 14/60] BPM changes --- .../keycloak/plugin/KeycloakGroupService.java | 13 +++- .../keycloak/plugin/KeycloakUserService.java | 26 ++++---- .../rest/KeycloakAuthenticationFilter.java | 66 ++++++++++++------- .../sso/KeycloakAuthenticationProvider.java | 13 +++- .../sso/OAuth2LoginSecurityConfig.java | 10 ++- 5 files changed, 89 insertions(+), 39 deletions(-) diff --git a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakGroupService.java b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakGroupService.java index 65d2078b85..e35f385ded 100644 --- a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakGroupService.java +++ b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakGroupService.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.camunda.bpm.engine.authorization.Groups; @@ -69,11 +70,20 @@ public KeycloakGroupService(KeycloakConfiguration keycloakConfiguration, Keycloa public List requestGroupsByUserId(CacheableKeycloakGroupQuery query) { LOG.debug("requestGroupsByUserId >> enableClientAuth value " + enableClientAuth); List userGroups = null; - if (enableClientAuth) { + if (enableClientAuth && !enableMultiTenancy) { userGroups = this.requestClientRolesByUserId(query); + userGroups = userGroups.stream().filter(group -> group.getName().startsWith("GROUP_")).collect(Collectors.toList()); } else { userGroups = super.requestGroupsByUserId(query); } + // Hacky solution, TODO Fix this. Here check if the group name ends with camunda-admin, then set the group as system group + for (Group group : userGroups) { + if (group.getName().endsWith(Groups.CAMUNDA_ADMIN) || group.getName().endsWith(keycloakConfiguration.getAdministratorGroupName())) { + group.setType(Groups.GROUP_TYPE_SYSTEM); + group.setId(keycloakConfiguration.getAdministratorGroupName()); + group.setName(keycloakConfiguration.getAdministratorGroupName()); + } + } return userGroups; } @@ -92,6 +102,7 @@ public List requestGroupsWithoutUserId(CacheableKeycloakGroupQuery query) } return roles; } + /** diff --git a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakUserService.java b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakUserService.java index 65c978f52f..3cf388dddc 100644 --- a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakUserService.java +++ b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakUserService.java @@ -60,12 +60,12 @@ public KeycloakUserService(KeycloakConfiguration keycloakConfiguration, Keycloak @Override public List requestUsersByGroupId(CacheableKeycloakUserQuery query) { List users; - if (enableClientAuth) { - if (enableMultiTenancy) { - users = this.requestUsersByClientRoleAndTenantId(); - } else { + if (enableClientAuth && !enableMultiTenancy) { +// if (enableMultiTenancy) { +// users = this.requestUsersByClientRoleAndTenantId(); +// } else { users = this.requestUsersByClientRole(); - } +// } } else { users = super.requestUsersByGroupId(query); } @@ -76,12 +76,12 @@ public List requestUsersByGroupId(CacheableKeycloakUserQuery query) { @Override public List requestUsersWithoutGroupId(CacheableKeycloakUserQuery query) { List users; - if (enableClientAuth) { - if (enableMultiTenancy) { - users = this.requestUsersByClientRoleAndTenantId(); - } else { - users = this.requestUsersByClientRole(); - } + if (enableClientAuth && !enableMultiTenancy) { +// if (enableMultiTenancy) { +// users = this.requestUsersByClientRoleAndTenantId(); +// } else { + users = this.requestUsersByClientRole(); +// } } else { users = super.requestUsersWithoutGroupId(query); } @@ -106,7 +106,7 @@ protected List requestUsersByClientRole(){ // get groups of this user ResponseEntity response = restTemplate.exchange(keycloakConfiguration.getKeycloakAdminUrl() - + "/clients/" + keycloakClientID + "/roles/formsflow-reviewer/users", HttpMethod.GET, + + "/clients/" + keycloakClientID + "/roles/view_tasks/users", HttpMethod.GET, String.class); if (!response.getStatusCode().equals(HttpStatus.OK)) { throw new IdentityProviderException( @@ -163,7 +163,7 @@ protected List requestUsersByClientRoleAndTenantId(){ // get groups of this user ResponseEntity response = restTemplate.exchange(keycloakConfiguration.getKeycloakAdminUrl() - + "/clients/" + keycloakClientID + "/roles/formsflow-reviewer/users", HttpMethod.GET, + + "/clients/" + keycloakClientID + "/roles/view_tasks/users", HttpMethod.GET, String.class); if (!response.getStatusCode().equals(HttpStatus.OK)) { throw new IdentityProviderException( diff --git a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java index 780672571a..04407357f4 100644 --- a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java +++ b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java @@ -2,8 +2,10 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; @@ -16,6 +18,7 @@ import org.camunda.bpm.extension.commons.utils.RestAPIBuilderUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -34,27 +37,36 @@ public class KeycloakAuthenticationFilter implements Filter { /** This class' logger. */ private static final Logger LOG = LoggerFactory.getLogger(KeycloakAuthenticationFilter.class); + + private static List HARD_CODED_ROLES = Arrays.asList("create_designs", "create_submissions", "view_submissions", "view_tasks", "manage_tasks", "admin"); + private final String userNameAttribute; - @Value("${plugin.identity.keycloak.enableMultiTenancy}") - private boolean enableMultiTenancy; - /** Access to Camunda's IdentityService. */ private IdentityService identityService; /** Access to the OAuth2 client service. */ private OAuth2AuthorizedClientService clientService; + private boolean enableClientAuth; + + + private boolean enableMultiTenancy; + + + /** * Creates a new KeycloakAuthenticationFilter. * * @param identityService access to Camunda's IdentityService */ - public KeycloakAuthenticationFilter(IdentityService identityService, OAuth2AuthorizedClientService clientService, String userNameAttribute) { + public KeycloakAuthenticationFilter(IdentityService identityService, OAuth2AuthorizedClientService clientService, String userNameAttribute, boolean enableClientAuth, boolean enableMultiTenancy) { this.identityService = identityService; this.clientService = clientService; this.userNameAttribute = userNameAttribute; + this.enableClientAuth = enableClientAuth; + this.enableMultiTenancy = enableMultiTenancy; } /** @@ -82,6 +94,8 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha } LOG.debug("Extracted userId from bearer token: {}", userId); + LOG.debug("enableClientAuth--> {}", enableClientAuth); + LOG.debug("enableMultiTenancy--> {}", enableMultiTenancy); try { String tenantKey = null; @@ -90,6 +104,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha if (claims != null && claims.containsKey("tenantKey")) { tenantKey = claims.get("tenantKey").toString(); tenantIds.add(tenantKey); + MDC.put("tenantKey", tenantKey); } userGroups = getUserGroups(userId, claims, tenantKey); if (tenantKey != null) @@ -112,38 +127,43 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha */ private List getUserGroups(String userId, Map claims, String tenantKey) { List groupIds = new ArrayList<>(); - -// LOG.debug(enableMultiTenancy+ "multitenancy enabled.."); // returning false - if (claims != null && claims.containsKey("groups") && tenantKey != null) { - groupIds.addAll(getKeys(claims, "groups", tenantKey)); - } - else if (claims != null && claims.containsKey("groups")) { - groupIds.addAll(getKeys(claims, "groups", null)); - } - else { + // + if (claims != null && claims.containsKey("groups")) { + List groups = getKeys(claims, "groups"); + if (enableMultiTenancy) { // For multi-tenant setup filter out the groups which are not part of the current tenant. + groups = groups.stream().filter(group -> group.startsWith(tenantKey)).collect(Collectors.toList()); + // For existing setup we may need to use existing camunda-admin role + List roles = getKeys(claims, "roles"); + if (roles.indexOf("camunda-admin") >= 0 ) { + groups.add(tenantKey+"-camunda-admin"); + } + } + groupIds.addAll(groups); + } else if (claims != null && claims.containsKey("roles")) { // Treat roles as alternative to groups + List groups = getKeys(claims, "roles"); + if (enableClientAuth) { // If client-auth is enabled, means customer cannot create group and is using client roles instead. In this case create each group as role with prefix GROUP_. + groups = groups.stream().filter(group -> group.startsWith("GROUP_")).collect(Collectors.toList()); + } + groupIds.addAll(groups); + } else { identityService.createGroupQuery().groupMember(userId).list().forEach(g -> groupIds.add(g.getId())); } + // TODO - Set the permission roles to match with the authorizations. + // TODO Here iterate the user's roles with HARD_CODED_ROLES, and set the matching ones as groups. Reason for this is, we could use these groups to set the authorization in camunda. return groupIds; } - private List getKeys(Map claims, String nodeName, String tenantKey) { + private List getKeys(Map claims, String nodeName) { List keys = new ArrayList<>(); if (claims.containsKey(nodeName)) { for (Object key : (List) claims.get(nodeName)) { String keyValue = key.toString(); keyValue = StringUtils.contains(keyValue, "/") ? StringUtils.substringAfter(keyValue, "/") : keyValue; - if (tenantKey != null) { - if (StringUtils.startsWith(keyValue, tenantKey)) { - keys.add(keyValue); - } - } else { - keys.add(keyValue); - } + keys.add(keyValue); } - // keys.add("camunda-admin"); } return keys; } -} +} \ No newline at end of file diff --git a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java index 46ea820b29..e518c66b23 100644 --- a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java +++ b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java @@ -17,7 +17,7 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; - +import java.util.Collections; /** * Keycloak Authentication Provider. * OAuth2 Authentication Provider for usage with Keycloak and @@ -49,6 +49,16 @@ public AuthenticationResult extractAuthenticatedUser(HttpServletRequest request, // Authentication successful AuthenticationResult authenticationResult = new AuthenticationResult(userId, true); authenticationResult.setGroups(getUserGroups(userId, engine, oidcUserPrincipal)); + + String tenantKeyAttr = (String) oidcUserPrincipal.getAttributes().get("tenantKey"); + if (tenantKeyAttr != null) { + // Create a list with tenantKeyAttr and set it to the authentication result + List tenants = Collections.singletonList(tenantKeyAttr); + authenticationResult.setTenants(tenants); + } else { + // Handle the case where tenantKeyAttr is null + authenticationResult.setTenants(Collections.emptyList()); + } return authenticationResult; } @@ -56,6 +66,7 @@ public AuthenticationResult extractAuthenticatedUser(HttpServletRequest request, private List getUserGroups(String userId, ProcessEngine engine, OidcUser principal) { List groupIds = new ArrayList<>(); // Find groups or roles from the idToken. + // TODO Fix this to get the values from here itself if (!enableClientAuth && principal.getIdToken().getClaims().containsKey("groups")) { groupIds.addAll(getKeys(principal.getIdToken(), "groups")); } else if (enableClientAuth && principal.getIdToken().getClaims().containsKey("roles")) { diff --git a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/OAuth2LoginSecurityConfig.java b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/OAuth2LoginSecurityConfig.java index 7533ed7823..c593fa5102 100644 --- a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/OAuth2LoginSecurityConfig.java +++ b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/OAuth2LoginSecurityConfig.java @@ -27,6 +27,7 @@ import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; import org.camunda.bpm.engine.IdentityService; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpMethod; @@ -70,6 +71,13 @@ public class OAuth2LoginSecurityConfig { @Inject private KeycloakCockpitConfiguration keycloakCockpitConfiguration; + + @Value("${plugin.identity.keycloak.enableClientAuth}") + private boolean enableClientAuth; + + + @Value("${plugin.identity.keycloak.enableMultiTenancy}") + private boolean enableMultiTenancy; @Bean @Order(1) @@ -154,7 +162,7 @@ public FilterRegistrationBean keycloakAuthenticationFilter(){ String userNameAttribute = this.applicationContext.getEnvironment().getRequiredProperty( "spring.security.oauth2.client.provider." + this.configProps.getProvider() + ".user-name-attribute"); - filterRegistration.setFilter(new KeycloakAuthenticationFilter(identityService, clientService, userNameAttribute)); + filterRegistration.setFilter(new KeycloakAuthenticationFilter(identityService, clientService, userNameAttribute, enableMultiTenancy, enableClientAuth)); filterRegistration.setOrder(102); filterRegistration.addUrlPatterns("/engine-rest/*"); filterRegistration.addUrlPatterns("/engine-rest-ext/*"); From 195eb97d8dd1cf51dbeca77470efce0f7b81c5c4 Mon Sep 17 00:00:00 2001 From: Sumesh Kariyil Date: Tue, 25 Jun 2024 15:07:21 -0700 Subject: [PATCH 15/60] Update KeycloakAuthenticationProvider.java --- .../extension/keycloak/sso/KeycloakAuthenticationProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java index e518c66b23..9032bf61ab 100644 --- a/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java +++ b/forms-flow-bpm/forms-flow-bpm-camunda/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java @@ -66,7 +66,7 @@ public AuthenticationResult extractAuthenticatedUser(HttpServletRequest request, private List getUserGroups(String userId, ProcessEngine engine, OidcUser principal) { List groupIds = new ArrayList<>(); // Find groups or roles from the idToken. - // TODO Fix this to get the values from here itself + // TODO Fix this to get the values from here itself, currently in all case if - else if are always FALSE. Fix this if (!enableClientAuth && principal.getIdToken().getClaims().containsKey("groups")) { groupIds.addAll(getKeys(principal.getIdToken(), "groups")); } else if (enableClientAuth && principal.getIdToken().getClaims().containsKey("roles")) { From d0074ba174c59ba9987bfe265488283d50df19a5 Mon Sep 17 00:00:00 2001 From: shuhaib-aot Date: Wed, 26 Jun 2024 14:27:52 +0530 Subject: [PATCH 16/60] FWF:3327 [feature] Modified auth role checking function --- .../src/formsflow_api_utils/utils/auth.py | 23 +++++++++++++++++-- .../formsflow_api_utils/utils/permisions.py | 11 +++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/forms-flow-api-utils/src/formsflow_api_utils/utils/auth.py b/forms-flow-api-utils/src/formsflow_api_utils/utils/auth.py index dcd37a7319..eaba5ec14c 100644 --- a/forms-flow-api-utils/src/formsflow_api_utils/utils/auth.py +++ b/forms-flow-api-utils/src/formsflow_api_utils/utils/auth.py @@ -8,7 +8,7 @@ from jose import jwt as json_web_token from jose.exceptions import JWTError - +from .permisions import build_permission_dict from ..exceptions import BusinessException, ExternalError jwt = JwtManager() # pylint: disable=invalid-name @@ -43,9 +43,28 @@ def decorated(f): @Auth.require @wraps(f) def wrapper(*args, **kwargs): - if jwt.contains_role(roles): + PERMISSIONS = build_permission_dict() + # Set to store roles that do not have any dependencies + non_dependencies_roles = set() + + # Set to store roles that have dependencies + dependent_roles = set() + + for role in roles: + permission = PERMISSIONS.get(role) + if permission: + # Check if the role depends on any other roles + if permission["depends_on"]: + dependent_roles.add(role) + dependent_roles.update(permission["depends_on"]) + else: + non_dependencies_roles.add(role) + + if non_dependencies_roles and jwt.contains_role(list(non_dependencies_roles)): return f(*args, **kwargs) + if dependent_roles and jwt.validate_roles(list(dependent_roles)): + return f(*args, **kwargs) raise BusinessException(ExternalError.UNAUTHORIZED) return wrapper diff --git a/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py b/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py index 5c050d2ab7..258b94df13 100644 --- a/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py +++ b/forms-flow-api-utils/src/formsflow_api_utils/utils/permisions.py @@ -35,3 +35,14 @@ class Permissions(Enum): {"name": Permissions.MANAGE_ROLES.value, "description": "Manage Roles", "depends_on": [Permissions.MANAGE_USERS.value]}, {"name": Permissions.ADMIN.value, "description": "Administrator Role", "depends_on": []}, ] + + +def build_permission_dict(): + """ + Builds a dictionary of permissions where the key is the permission name and + the value is the permission detail. + + Returns: + dict: A dictionary of permission details. + """ + return {permission["name"]: permission for permission in PERMISSION_DETAILS} From eec0af1da2d62d54e7b4855332d603c114921883 Mon Sep 17 00:00:00 2001 From: shuhaib-aot Date: Wed, 26 Jun 2024 14:29:02 +0530 Subject: [PATCH 17/60] FWF:3327 [Modified] utils urls --- forms-flow-api/requirements.txt | 2 +- forms-flow-api/requirements/prod.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/forms-flow-api/requirements.txt b/forms-flow-api/requirements.txt index 1706af2ec9..6525943c6c 100644 --- a/forms-flow-api/requirements.txt +++ b/forms-flow-api/requirements.txt @@ -27,7 +27,7 @@ ecdsa==0.18.0 flask-jwt-oidc==0.3.0 flask-marshmallow==1.2.1 flask-restx==1.3.0 -formsflow_api_utils @ git+https://github.com/shuhaib-aot/forms-flow-ai.git@Feature/FWF-3327-secure-endpoint-with-role#subdirectory=forms-flow-api-utils +formsflow_api_utils @ git+https://github.com/shuhaib-aot/forms-flow-ai.git@Feature/FWF-3327-auth-function-modified#subdirectory=forms-flow-api-utils gunicorn==21.2.0 h11==0.14.0 h2==4.1.0 diff --git a/forms-flow-api/requirements/prod.txt b/forms-flow-api/requirements/prod.txt index 64ffd6f17e..1e70920c3b 100644 --- a/forms-flow-api/requirements/prod.txt +++ b/forms-flow-api/requirements/prod.txt @@ -16,4 +16,4 @@ sqlalchemy_utils markupsafe PyJWT redis -git+https://github.com/shuhaib-aot/forms-flow-ai.git@Feature/FWF-3327-secure-endpoint-with-role#subdirectory=forms-flow-api-utils \ No newline at end of file +git+https://github.com/shuhaib-aot/forms-flow-ai.git@Feature/FWF-3327-auth-function-modified#subdirectory=forms-flow-api-utils \ No newline at end of file From 4d563b6cdf1f5f3c78f33853447b6b5612492976 Mon Sep 17 00:00:00 2001 From: Bonymol-aot Date: Thu, 27 Jun 2024 03:15:25 -0700 Subject: [PATCH 18/60] FWF-3326: [Feature] Added permission matrix changes for design, task, submission, filter, dashboard --- .../Application/ApplicationTable.js | 12 +- .../Form/FormOperations/FormOperations.js | 18 +- .../src/components/Form/Item/Preview.js | 72 ++--- .../Form/Item/Submission/Item/Edit.js | 4 +- .../Form/Item/Submission/Item/index.js | 3 +- .../components/Form/Item/Submission/List.js | 7 +- .../components/Form/Item/Submission/index.js | 14 +- .../src/components/Form/Item/index.js | 12 +- forms-flow-web/src/components/Form/List.js | 23 +- .../components/Form/Steps/PreviewStepper.js | 8 +- .../src/components/Form/Steps/SaveNext.js | 31 ++- .../src/components/Form/Steps/WorkFlow.js | 6 +- .../components/Form/constants/ClientTable.js | 7 +- .../components/Form/constants/FormTable.js | 45 ++-- .../Form/constants/formListConstants.js | 9 +- forms-flow-web/src/components/Form/index.js | 31 ++- .../src/components/Modeler/index.js | 31 ++- .../src/components/PrivateRoute.jsx | 66 ++--- .../ServiceFlow/details/TaskHeaderListView.js | 250 +++++++++--------- .../ServiceFlow/list/sort/CreateNewFilter.js | 28 +- forms-flow-web/src/constants/permissions.js | 25 ++ 21 files changed, 381 insertions(+), 321 deletions(-) create mode 100644 forms-flow-web/src/constants/permissions.js diff --git a/forms-flow-web/src/components/Application/ApplicationTable.js b/forms-flow-web/src/components/Application/ApplicationTable.js index 2e62bb6e35..7eddefd981 100644 --- a/forms-flow-web/src/components/Application/ApplicationTable.js +++ b/forms-flow-web/src/components/Application/ApplicationTable.js @@ -1,11 +1,9 @@ import React, { useState } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { getUserRolePermission } from "../../helper/user"; import { - CLIENT, MULTITENANCY_ENABLED, - STAFF_REVIEWER, } from "../../constants/constants"; + import { CLIENT_EDIT_STATUS } from "../../constants/applicationConstants"; import { HelperServices } from "@formsflow/service"; import { Translation } from "react-i18next"; @@ -13,6 +11,7 @@ import ApplicationFilter from "./ApplicationFilter"; import { Dropdown } from "react-bootstrap"; import Pagination from "react-js-pagination"; import { useTranslation } from "react-i18next"; +import userRoles from "../../constants/permissions"; import { setApplicationListActivePage, @@ -37,7 +36,7 @@ const ApplicationTable = () => { const tenantKey = useSelector((state) => state.tenants?.tenantId); const redirectUrl = MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : "/"; - const userRoles = useSelector((state) => state.user.roles); + const { createSubmissions } = userRoles(); const pageNo = useSelector((state) => state.applications?.activePage); const limit = useSelector((state) => state.applications?.countPerPage); const sortOrder = useSelector((state) => state.applications?.sortOrder); @@ -50,10 +49,7 @@ const ApplicationTable = () => { (state) => state.applications?.applicationCount ); const isClientEdit = (applicationStatus) => { - if ( - getUserRolePermission(userRoles, CLIENT) || - getUserRolePermission(userRoles, STAFF_REVIEWER) - ) { + if (createSubmissions) { return CLIENT_EDIT_STATUS.includes(applicationStatus); } else { return false; diff --git a/forms-flow-web/src/components/Form/FormOperations/FormOperations.js b/forms-flow-web/src/components/Form/FormOperations/FormOperations.js index f908239f6c..ee1fd15963 100644 --- a/forms-flow-web/src/components/Form/FormOperations/FormOperations.js +++ b/forms-flow-web/src/components/Form/FormOperations/FormOperations.js @@ -2,11 +2,9 @@ import React from "react"; import { useDispatch, useSelector } from "react-redux"; import { push } from "connected-react-router"; import { - CLIENT, MULTITENANCY_ENABLED, - STAFF_DESIGNER, - STAFF_REVIEWER, } from "../../../constants/constants"; +import userRoles from "../../../constants/permissions"; import { setIsApplicationCountLoading, setResetProcess, @@ -21,6 +19,8 @@ import { import { Translation } from "react-i18next"; const FormOperations = React.memo(({ formData }) => { + const { createDesigns, createSubmissions } = userRoles(); + const tenantKey = useSelector((state) => state.tenants?.tenantId); const redirectUrl = MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : "/"; const dispatch = useDispatch(); @@ -84,16 +84,16 @@ const FormOperations = React.memo(({ formData }) => { ); let buttons = { - CLIENT_OR_REVIEWER: [submitNew], - STAFF_DESIGNER: [viewOrEdit, deleteForm], + SUBMIT_NEW: [submitNew], + CREATE_DESIGNS: [viewOrEdit, deleteForm], }; const formButtonOperations = () => { let operationButtons = []; - if (userRoles.includes(CLIENT) || userRoles.includes(STAFF_REVIEWER)) { - operationButtons.push(buttons.CLIENT_OR_REVIEWER); + if (createSubmissions) { + operationButtons.push(buttons.SUBMIT_NEW); } - if (userRoles.includes(STAFF_DESIGNER)) { - operationButtons.push(buttons.STAFF_DESIGNER); // OPERATIONS.edit, + if (createDesigns) { + operationButtons.push(buttons.CREATE_DESIGNS); // OPERATIONS.edit, } return operationButtons; }; diff --git a/forms-flow-web/src/components/Form/Item/Preview.js b/forms-flow-web/src/components/Form/Item/Preview.js index 0788a322a8..8a0922ea74 100644 --- a/forms-flow-web/src/components/Form/Item/Preview.js +++ b/forms-flow-web/src/components/Form/Item/Preview.js @@ -7,6 +7,7 @@ import Loading from "../../../containers/Loading"; import { Translation } from "react-i18next"; import { RESOURCE_BUNDLES_DATA } from "../../../resourceBundles/i18n"; import { MULTITENANCY_ENABLED } from "../../../constants/constants"; +import userRoles from "../../../constants/permissions"; import { setFormFailureErrorData, setFormHistories, @@ -38,6 +39,8 @@ const Preview = ({handleNext, hideComponents, activeStep}) => { const {form, isActive: isFormActive, errors} = useSelector(state => state.form || {}); const lang = useSelector(state => state.user.lang); const formProcessList = useSelector(state => state.process?.formProcessList); + const { createDesigns } = userRoles(); + const handleModalChange = () => { setHistoryModal(!historyModal); @@ -157,42 +160,39 @@ const Preview = ({handleNext, hideComponents, activeStep}) => {