Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[U2][Update 7738] Add support for local subject identifier configuration in the ServicePasswordCallbackHandler #138

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@
import org.wso2.carbon.identity.core.IdentityClaimManager;
import org.wso2.carbon.identity.core.util.IdentityCoreConstants;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.provider.IdentityProviderException;
import org.wso2.carbon.identity.sts.common.internal.IdentityProviderSTSServiceComponent;
import org.wso2.carbon.user.core.UserRealm;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.UserCoreConstants;
import org.wso2.carbon.user.core.UserStoreManager;
import org.wso2.carbon.user.core.claim.Claim;
import org.wso2.carbon.user.core.util.UserCoreUtil;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;

import javax.xml.namespace.QName;
Expand Down Expand Up @@ -109,6 +111,10 @@ public void handle(SAMLCallback callback) throws SAMLException {
splitArr = userIdentifier.split(",")[0].split("=");
if (splitArr.length == 2) {
userIdentifier = splitArr[1];
} else if (!userIdentifier.contains(UserCoreConstants.DOMAIN_SEPARATOR)) {
// if the user identifier is not qualified with user store domain, making it so.
nipunsampath marked this conversation as resolved.
Show resolved Hide resolved
userIdentifier = IdentityUtil.addDomainToName(userIdentifier,
UserCoreUtil.getDomainFromThreadLocal());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,18 @@ public class ServicePasswordCallbackHandler implements CallbackHandler {
private static final Log log = LogFactory.getLog(ServicePasswordCallbackHandler.class);

private static final String TENANT_DOMAIN_SEPARATOR = "@";
private static final String INCLUDE_USER_STORE_DOMAIN_IN_USERNAME = "SecurityTokenService.LocalSubjectIdentifier" +
".IncludeUserStoreDomain";
private static final String INCLUDE_TENANT_DOMAIN_IN_USERNAME = "SecurityTokenService.LocalSubjectIdentifier" +
".IncludeTenantDomain";

private String serviceGroupId = null;
private String serviceId = null;
private Registry registry = null;
private UserRealm realm = null;
private SecurityConfigParams configParams;
private final boolean includeUserStoreDomainInUsername;
private final boolean includeTenantInUsername;

//todo there's a API change here. apparently only security component uses this. If not, change the invocations accordingly.
public ServicePasswordCallbackHandler(SecurityConfigParams configParams, String serviceGroupId,
Expand All @@ -78,6 +84,12 @@ public ServicePasswordCallbackHandler(SecurityConfigParams configParams, String
this.serviceGroupId = serviceGroupId;
this.realm = realm;
this.configParams = configParams;
IdentityUtil.populateProperties();
// If the property is not available, default value is true.
this.includeUserStoreDomainInUsername = IdentityUtil.getProperty(INCLUDE_USER_STORE_DOMAIN_IN_USERNAME) == null
nipunsampath marked this conversation as resolved.
Show resolved Hide resolved
|| Boolean.parseBoolean(IdentityUtil.getProperty(INCLUDE_USER_STORE_DOMAIN_IN_USERNAME));
// If the property is not available, default value is false.
this.includeTenantInUsername = Boolean.parseBoolean(IdentityUtil.getProperty(INCLUDE_TENANT_DOMAIN_IN_USERNAME));
}

@Override
Expand Down Expand Up @@ -112,14 +124,8 @@ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallback
try {
if (receivedPasswd != null
&& this.authenticateUser(username, receivedPasswd)) {

String domainName = UserCoreUtil.getDomainFromThreadLocal();
String usernameWithDomain = IdentityUtil.addDomainToName(username, domainName);
if (log.isDebugEnabled()) {
log.debug("Updating username with userstore domain. Updated username is :" +
usernameWithDomain);
}
passwordCallback.setIdentifier(usernameWithDomain);
username = applyLocalSubjectIdentifierConfigs(username);
passwordCallback.setIdentifier(username);
} else {
throw new UnsupportedCallbackException(callbacks[i], "check failed");
}
Expand Down Expand Up @@ -218,6 +224,68 @@ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallback
}
}

/**
* Apply local subject identifier configurations to the username.
*
* @param username Username to be processed.
* @return Username with local subject identifier configurations applied.
* @throws UserStoreException {@link UserStoreException}
*/
private String applyLocalSubjectIdentifierConfigs(String username) throws UserStoreException {

String processedUsername;
if (includeTenantInUsername) {
processedUsername = getUsernameWithTenantDomain(username);
if (log.isDebugEnabled()) {
log.debug("Updating username with tenant domain. Updated username: " + processedUsername);
}
} else {
processedUsername = MultitenantUtils.getTenantAwareUsername(username);
if (log.isDebugEnabled()) {
log.debug("Removed tenant domain from the username. Updated username: " + processedUsername);
}
}

if (includeUserStoreDomainInUsername) {
String domainName = UserCoreUtil.getDomainFromThreadLocal();
processedUsername = IdentityUtil.addDomainToName(processedUsername, domainName);
if (log.isDebugEnabled()) {
log.debug("Updating username with user store domain. Updated username: " + processedUsername);
}
} else {
processedUsername = UserCoreUtil.removeDomainFromName(processedUsername);
if (log.isDebugEnabled()) {
log.debug("Removed user store domain from the username. Updated username is: " + processedUsername);
}
}
return processedUsername;
}

/**
* Get the username with the tenant domain appended.
* @param username Username to be processed.
* @return Username with the tenant domain appended.
* @throws UserStoreException {@link UserStoreException}
*/
private String getUsernameWithTenantDomain(String username) throws UserStoreException {

String tenantDomain = MultitenantUtils.getTenantDomain(username);
if (StringUtils.isBlank(tenantDomain) || (SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain) &&
!StringUtils.contains(username, SUPER_TENANT_DOMAIN_NAME))) {
// If the tenant domain cannot be determined using the username, use the tenant domain of the service
// provider
return getServiceTenantDomainAppendedUser(username);
}

if (log.isDebugEnabled()) {
log.debug("Tenant domain can be determined using the username. Hence appending the tenant domain to the " +
"tenant-aware username. Username: " + username + ", Tenant domain: " + tenantDomain);
}
String tenantAwareUsername = MultitenantUtils.getTenantAwareUsername(username);
return tenantAwareUsername + TENANT_DOMAIN_SEPARATOR + tenantDomain;
}


private String getServicePrincipalPassword()
throws SecurityConfigException {

Expand Down