Skip to content

Commit

Permalink
Merge pull request #5070 from SujanSanjula96/app-role-resolver
Browse files Browse the repository at this point in the history
Add App Associated Role Resolver implementation and handle roles claim
  • Loading branch information
SujanSanjula96 authored Oct 27, 2023
2 parents d444101 + 625bc5c commit ab584c2
Show file tree
Hide file tree
Showing 8 changed files with 507 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.framework</groupId>
<artifactId>org.wso2.carbon.identity.role.v2.mgt.core</artifactId>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -286,6 +290,7 @@
org.wso2.carbon.identity.configuration.mgt.core; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.configuration.mgt.core.exception; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.configuration.mgt.core.model; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.role.v2.mgt.core; version="${carbon.identity.package.import.version.range}",
</Import-Package>
<Export-Package>!org.wso2.carbon.identity.application.authentication.framework.internal,
org.wso2.carbon.identity.application.authentication.framework.*;
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.identity.application.authentication.framework.handler.approles.util;

import org.apache.commons.lang.ArrayUtils;
import org.wso2.carbon.identity.application.authentication.framework.handler.approles.constant.AppRolesConstants;
import org.wso2.carbon.identity.application.authentication.framework.handler.approles.exception.ApplicationRolesClientException;
import org.wso2.carbon.identity.application.authentication.framework.handler.approles.exception.ApplicationRolesServerException;

/**
* Utility class for Roles Resolver.
*/
public class RoleResolverUtils {

/**
* Throw an ApplicationRolesServerException with the given error message.
*
* @param error The error enum.
* @param e The throwable.
* @param data The error message data.
* @return ApplicationRolesServerException.
*/
public static ApplicationRolesServerException handleServerException(
AppRolesConstants.ErrorMessages error, Throwable e, String... data) {

String description = error.getDescription();
if (ArrayUtils.isNotEmpty(data)) {
description = String.format(description, data);
}
return new ApplicationRolesServerException(error.getMessage(), description, error.getCode(), e);
}

/**
* Throw an ApplicationRolesClientException with the given error message.
*
* @param error The error enum.
* @param data The error message data.
* @return ApplicationRolesClientException.
*/
public static ApplicationRolesClientException handleClientException(
AppRolesConstants.ErrorMessages error, String... data) {

String description = error.getDescription();
if (ArrayUtils.isNotEmpty(data)) {
description = String.format(description, data);
}
return new ApplicationRolesClientException(error.getMessage(), description, error.getCode());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.identity.application.authentication.framework.ApplicationAuthenticator;
import org.wso2.carbon.identity.application.authentication.framework.config.builder.FileBasedConfigurationBuilder;
Expand Down Expand Up @@ -217,6 +218,11 @@ protected Map<String, String> handleFederatedClaims(Map<String, String> remoteCl

if (StringUtils.isNotBlank(applicationRoles)) {
localUnfilteredClaims.put(FrameworkConstants.APP_ROLES_CLAIM, applicationRoles);
if (!CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME) {
// Add app associated roles to roles claim in Role V2 runtime.
String rolesClaimURI = getLocalGroupsClaimURI();
localUnfilteredClaims.put(rolesClaimURI, applicationRoles);
}
}

// claim mapping from local service provider to remote service provider.
Expand Down Expand Up @@ -570,7 +576,14 @@ protected Map<String, String> handleLocalClaims(String spStandardDialect,
// Retrieve all non-null user claim values against local claim uris.
allLocalClaims = retrieveAllNunNullUserClaimValues(authenticatedUser, claimManager, appConfig, userStore);

handleApplicationRolesForLocalUser(stepConfig, context, allLocalClaims);
String applicationRoles = getApplicationRoles(authenticatedUser, context);

handleApplicationRolesForLocalUser(stepConfig, context, allLocalClaims, applicationRoles);

if (!CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME) {
// Handle app associated roles in roles claim in Role V2 runtime.
handleRoleAppAssoication(allLocalClaims, applicationRoles);
}

// Insert the runtime claims from the context. The priority is for runtime claims.
allLocalClaims.putAll(context.getRuntimeClaims());
Expand Down Expand Up @@ -1098,6 +1111,22 @@ private boolean enableMergingCustomClaimMappingsWithDefaultMappings() {
.isMergingCustomClaimMappingsWithDefaultClaimMappingsAllowed();
}

/**
* Handle role app association in roles claim.
*
* @param appAssociatedRoles App associated roles.
* @param mappedAttrs Mapped claim attributes.
*/
private void handleRoleAppAssoication(Map<String, String> mappedAttrs, String appAssociatedRoles) {

// Getting roles claim URI by checking legacy config.
String rolesClaimURI = getLocalGroupsClaimURI();
if (mappedAttrs.containsKey(rolesClaimURI)) {
mappedAttrs.put(rolesClaimURI,
StringUtils.isEmpty(appAssociatedRoles) ? StringUtils.EMPTY : appAssociatedRoles);
}
}

/**
* Specially handle role claim values.
*
Expand Down Expand Up @@ -1172,7 +1201,7 @@ protected String getApplicationRolesForFederatedUser(StepConfig stepConfig, Auth
* @throws FrameworkException Exception on handling application roles for local user.
*/
protected void handleApplicationRolesForLocalUser(StepConfig stepConfig, AuthenticationContext context,
Map<String, String> allLocalClaims)
Map<String, String> allLocalClaims, String appAssociatedRoles)
throws FrameworkException {

AuthenticatedUser authenticatedUser = getAuthenticatedUser(stepConfig, context);
Expand All @@ -1183,9 +1212,8 @@ protected void handleApplicationRolesForLocalUser(StepConfig stepConfig, Authent
String requestedAppRoleClaim = context.getSequenceConfig().getApplicationConfig()
.getRequestedClaimMappings().get(FrameworkConstants.APP_ROLES_CLAIM);
if (requestedAppRoleClaim != null) {
String appRoles = getApplicationRoles(authenticatedUser, context);
if (appRoles != null) {
allLocalClaims.put(FrameworkConstants.APP_ROLES_CLAIM, appRoles);
if (appAssociatedRoles != null) {
allLocalClaims.put(FrameworkConstants.APP_ROLES_CLAIM, appAssociatedRoles);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.wso2.carbon.identity.application.authentication.framework.dao.impl.LongWaitStatusDAOImpl;
import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException;
import org.wso2.carbon.identity.application.authentication.framework.handler.approles.ApplicationRolesResolver;
import org.wso2.carbon.identity.application.authentication.framework.handler.approles.impl.AppAssociatedRolesResolverImpl;
import org.wso2.carbon.identity.application.authentication.framework.handler.claims.ClaimFilter;
import org.wso2.carbon.identity.application.authentication.framework.handler.claims.impl.DefaultClaimFilter;
import org.wso2.carbon.identity.application.authentication.framework.handler.provisioning.listener.JITProvisioningIdentityProviderMgtListener;
Expand Down Expand Up @@ -110,6 +111,7 @@
import org.wso2.carbon.identity.multi.attribute.login.mgt.MultiAttributeLoginService;
import org.wso2.carbon.identity.organization.management.service.OrganizationManagementInitialize;
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService;
import org.wso2.carbon.identity.user.profile.mgt.association.federation.FederatedAssociationManager;
import org.wso2.carbon.idp.mgt.IdpManager;
import org.wso2.carbon.idp.mgt.listener.IdentityProviderMgtListener;
Expand Down Expand Up @@ -212,6 +214,9 @@ protected void activate(ComponentContext ctxt) {
new SessionExtenderResponseFactory(), null);
bundleContext.registerService(IdentityProcessor.class.getName(), new SessionExtenderProcessor(), null);

bundleContext.registerService(ApplicationRolesResolver.class.getName(), new AppAssociatedRolesResolverImpl(),
null);

ServerSessionManagementService serverSessionManagementService = new ServerSessionManagementServiceImpl();
bundleContext.registerService(ServerSessionManagementService.class.getName(),
serverSessionManagementService, null);
Expand Down Expand Up @@ -1048,4 +1053,22 @@ protected void unregisterConfigurationManager(ConfigurationManager configuration
}
FrameworkServiceDataHolder.getInstance().setConfigurationManager(null);
}

@Reference(
name = "org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService",
service = org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unsetRoleManagementServiceV2")
protected void setRoleManagementServiceV2(RoleManagementService roleManagementService) {

FrameworkServiceDataHolder.getInstance().setRoleManagementServiceV2(roleManagementService);
log.debug("RoleManagementServiceV2 set in FrameworkServiceComponent bundle.");
}

protected void unsetRoleManagementServiceV2(RoleManagementService roleManagementService) {

FrameworkServiceDataHolder.getInstance().setRoleManagementServiceV2(null);
log.debug("RoleManagementServiceV2 unset in FrameworkServiceComponent bundle.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.wso2.carbon.identity.multi.attribute.login.mgt.MultiAttributeLoginService;
import org.wso2.carbon.identity.organization.management.service.OrganizationManagementInitialize;
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService;
import org.wso2.carbon.identity.user.profile.mgt.association.federation.FederatedAssociationManager;
import org.wso2.carbon.idp.mgt.IdpManager;
import org.wso2.carbon.user.core.service.RealmService;
Expand Down Expand Up @@ -112,6 +113,7 @@ public class FrameworkServiceDataHolder {
private boolean isAdaptiveAuthenticationAvailable = false;
private boolean isOrganizationManagementEnable = false;
private OrganizationManager organizationManager;
private RoleManagementService roleManagementServiceV2;

private FrameworkServiceDataHolder() {

Expand Down Expand Up @@ -721,4 +723,24 @@ public ConfigurationManager getConfigurationManager() {

return configurationManager;
}

/**
* Get {@link RoleManagementService}.
*
* @return Instance of {@link RoleManagementService}.
*/
public RoleManagementService getRoleManagementServiceV2() {

return roleManagementServiceV2;
}

/**
* Set {@link RoleManagementService}.
*
* @param roleManagementServiceV2 Instance of {@link RoleManagementService}.
*/
public void setRoleManagementServiceV2(RoleManagementService roleManagementServiceV2) {

this.roleManagementServiceV2 = roleManagementServiceV2;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ public void testHandleApplicationRolesForLocalUser() throws Exception {
when(applicationRolesResolver.getRoles(eq(authenticatedUser), eq(applicationId))).thenReturn(
mappedApplicationRoles);

defaultClaimHandler.handleApplicationRolesForLocalUser(stepConfig, authenticationContext, localClaims);
defaultClaimHandler.handleApplicationRolesForLocalUser(stepConfig, authenticationContext, localClaims,
String.join(FrameworkUtils.getMultiAttributeSeparator(), mappedApplicationRoles));

Assert.assertEquals(localClaims.get(FrameworkConstants.APP_ROLES_CLAIM),
String.join(",", mappedApplicationRoles));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

package org.wso2.carbon.identity.application.authentication.framework.handler.sequence.impl;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.application.authentication.framework.config.model.SequenceConfig;
import org.wso2.carbon.identity.application.authentication.framework.context.AuthHistory;
Expand Down Expand Up @@ -57,6 +59,12 @@
@WithAxisConfiguration
public class GraphBasedSequenceHandlerAcrTest extends GraphBasedSequenceHandlerAbstractTest {

@BeforeClass
public void setUpMocks() {

CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true;
}

@Test(dataProvider = "staticAcrDataProvider")
public void testHandleStaticJavascriptAcr(String spFileName, String[] acrArray, int authHistoryCount) throws
Exception {
Expand Down

0 comments on commit ab584c2

Please sign in to comment.